精华内容
参与话题
问答
  • Repository

    千次阅读 2018-08-06 21:55:52
    Repository的概念 在Spring中有Repository的概念,repository原意指的是仓库,即数据仓库的意思。Repository居于业务层和数据层之间,将两者隔离开来,在它的内部封装了数据查询和存储的逻辑。这样设计的好处有两个...

    Repository的概念

    在Spring中有Repository的概念,repository原意指的是仓库,即数据仓库的意思。Repository居于业务层和数据层之间,将两者隔离开来,在它的内部封装了数据查询和存储的逻辑。这样设计的好处有两个:

    1. 降低层级之间的耦合:更换、升级ORM引擎(Hibernate)并不会影响业务逻辑
    2. 提高测试效率:如果在测试时能用Mock数据对象代替实际的数据库操作,运行速度会快很多

    Repository和DAO的区别

    DAO是传统MVC中Model的关键角色,全称是Data Access Object。DAO直接负责数据库的存取工作,乍一看两者非常类似,但从架构设计上讲两者有着本质的区别:

    Repository蕴含着真正的OO概念,即一个数据仓库角色,负责所有对象的持久化管理。DAO则没有摆脱数据的影子,仍然停留在数据操作的层面上。Repository是相对对象而言,DAO则是相对数据库而言,虽然可能是同一个东西 ,但侧重点完全不同。

    三种Repository介绍

    在Spring和Spring Data JPA中,有三种Repository接口方便开发者直接操作数据仓库。
    它们之间的关系如下:

    CrudRepository

      <S extends T> S save(S entity);
      <S extends T> Iterable<S> save(Iterable<S> entities);
      T findOne(ID id);
      boolean exists(ID id);
      Iterable<T> findAll();
      Iterable<T> findAll(Iterable<ID> ids);
      long count();
      void delete(ID id);
      void delete(T entity);
      void delete(Iterable<? extends T> entities);
      void deleteAll();

    CrudRepository类如其名,可以胜任最基本的CRUD操作。其中save方法在可两用,参数中不存在主键时执行insert操作,存在主键则执行update操作,相当于是一个upsert操作。

    PagingAndSortingRepository

      Iterable<T> findAll(Sort sort);
      Page<T> findAll(Pageable pageable);

    PagingAndSortingRepository继承了CrudRepository接口,增加了分页和排序的方法。

    分页

    要达到分页的目的,需要传入一个Pageble接口对象,controller中代码如下:

    @GetMapping("")
    public ResponseEntity<?> getList(
      @RequestParam(value="page", defaultValue="0") int page,
      @RequestParam(value="size", defaultValue="10") int size ) {
            
      Pageable pageable = new PageRequest(page, size);
      return new ResponseEntity<Object>(userService.getUserList(pageable), HttpStatus.OK);
    }

    <说明>

    1. @RequestParam注解,表明了需要传入URL参数page和size,用于计算分页的offset值。
    2. PageRequest是Pageable的实现类,传入初始化page和size即可生成分页参数。

    在Service中,仅需加入pageable对象即可达到分页的效果。代码如下:

    public Iterable<User> getUserList(Pageable pageable) {
      return userRepo.findAll(pageable);
    }

    此时在POSTMAN中输入访问地址:'127.0.0.1:8080/user?page=0&size=5',得到以下结果:

    {
      "content": [
        { "id": 12, "name": "F1" },
        { "id": 13, "name": "A" },
        { "id": 14, "name": "B" },
        { "id": 15, "name": "C" },
        { "id": 16, "name": "D" }
      ],
      "last": false,
      "totalPages": 3,
      "totalElements": 11,
      "size": 5,
      "number": 0,
      "numberOfElements": 5,
      "first": true,
      "sort": null
    }

    从结果可以看出,不仅在content中有查询的数组信息,还包括totalPages等分页信息。

    排序

    与分页类似,要达到排序的目录,仅需要传入Sort对象即可,controller中代码如下:

    @GetMapping("")
    public ResponseEntity<?> getList(
      @RequestParam(value="page", defaultValue="0") int page,
      @RequestParam(value="size", defaultValue="10") int size ) {
            
      Sort sort = new Sort(Sort.Direction.DESC, "name");
    // Pageable pageable = new PageRequest(page, size);
      return new ResponseEntity<Object>(userService.getUserList(sort), HttpStatus.OK);
    }

    同样的,在Service中需要新增接口,如下:

    public Iterable<User> getUserList(Sort sort) {
      return userRepo.findAll(sort);
    }

    此时在POSTMAN中输入访问地址:'127.0.0.1:8080/user',得到以下结果:

    [
        { "id": 22, "name": "K" },
        { "id": 21, "name": "J" },
        { "id": 20, "name": "I" },
        { "id": 19, "name": "H" },
        { "id": 18, "name": "G" },
        { "id": 12, "name": "F1" },
        { "id": 17, "name": "E" },
        { "id": 16, "name": "D" },
        { "id": 15, "name": "C" },
        { "id": 14, "name": "B" },
        { "id": 13, "name": "A" }
    ]

    得到的正是name属性按DESC排序的结果列表

    排序后分页

    PagingAndSortingRepository提供了分页和排序的接口,那如果两者都要做,该怎么写呢?
    其实在Pageable中,还可以传入Sort属性,这样就可以在分页中达到排序的目的。

    同样的,把Controller代码稍稍调整一下:

    @GetMapping("")
    public ResponseEntity<?> getList(
      @RequestParam(value="page", defaultValue="0") int page,
      @RequestParam(value="size", defaultValue="10") int size ) {
            
      Sort sort = new Sort(Sort.Direction.DESC, "name");
      Pageable pageable = new PageRequest(page, size, sort);
      return new ResponseEntity<Object>(userService.getUserList(pageable), HttpStatus.OK);
    }

    <说明>

    1. Sort对象作为PageRequest的第三个参数传入。

    这样调整以后,UserService这边就不在需要入参为Sort的getUserList接口了。

    此时在POSTMAN中输入访问地址:'127.0.0.1:8080/user?page=0&size=5',得到以下结果:

    {
      "content":[
        {"id":22,"name":"K"},
        {"id":21,"name":"J"},
        {"id":20,"name":"I"},
        {"id":19,"name":"H"},
        {"id":18,"name":"G"}
      ],
      "totalPages":3,
      "totalElements":11,
      "last":false,"size":5,
      "number":0,
      "first":true,
      "numberOfElements":5,
      "sort":[{
        "direction":"DESC",
        "property":"name",
        "ignoreCase":false,
        "nullHandling":"NATIVE",
        "ascending":false,
        "descending":true
      }]
    }

    sort显然不应该出现在应答结果中,以后的代码会将它去除出去。

    JpaRepository

      List<T> findAll();
      List<T> findAll(Sort sort);
      List<T> findAll(Iterable<ID> ids);
      <S extends T> List<S> save(Iterable<S> entities);
      void flush();
      <S extends T> S saveAndFlush(S entity);
      void deleteInBatch(Iterable<T> entities);
      void deleteAllInBatch();
      T getOne(ID id);
      @Override
      <S extends T> List<S> findAll(Example<S> example);
      @Override
      <S extends T> List<S> findAll(Example<S> example, Sort sort);

    JpaRepository则进一步在PagingAndSorting的基础上,扩展了部分功能:

    1. 查询列表(返回值为List)
    2. 批量删除
    3. 强制同步
    4. Example查询

    这部分将在以后的内容中不断细化。

    展开全文
  • 前一节我们看到了使用缺省Repository的局限性。解决这种局限性有两种办法,一种是在Application层引入EF,这样可以在ApplicationService中使用EF的扩展,如Include等,弥补通用Repository的不足。还有一种办法是编写...

    前一节我们看到了使用缺省Repository的局限性。解决这种局限性有两种办法,一种是在Application层引入EF,这样可以在ApplicationService中使用EF的扩展,如Include等,弥补通用Repository的不足。还有一种办法是编写定制的Repository。我们不希望应用层依赖特定的数据库框架(不远的将来我们会把数据移动到MongoDb),所以我们采用第二种办法。

    定制Repository需要两部分代码:在领域层的Repository接口和在特定数据访问层种的实现。我们需要定义两个定制的Repository:ICategoryPoemRepository和IPoemRepository,这两个接口在ZL.AbpNext.Poem.Core项目Repositories目录下:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Volo.Abp.Domain.Repositories;
    using ZL.AbpNext.Poem.Core.Poems;
    
    namespace ZL.AbpNext.Poem.Core.Repositories
    {
        public interface ICategoryPoemRepository : IRepository<CategoryPoem, int>
        {
            List<Category> GetPoemCategories(int poemid);
    
            List<Core.Poems.Poem> GetPoemsOfCategory(int categoryid);
        }
    }
    
    using System.Collections.Generic;
    using System.Text;
    using System.Threading.Tasks;
    using Volo.Abp.Domain.Repositories;
    
    namespace ZL.AbpNext.Poem.Core.Repositories
    {
        public interface IPoemRepository : IRepository<Core.Poems.Poem , int>
        {
            Task<List<Core.Poems.Poem>> GetPagedPoems(int maxResult,int skip,string author,string keyword,string[] categories,out int total);
        }
    }
    
    

    对应的实现在ZL.AbpNext.Poem.EF项目中:

    using Microsoft.EntityFrameworkCore;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
    using Volo.Abp.EntityFrameworkCore;
    using ZL.AbpNext.Poem.Core.Poems;
    using ZL.AbpNext.Poem.Core.Repositories;
    using ZL.AbpNext.Poem.EF.EntityFramework;
    
    namespace ZL.AbpNext.Poem.EF.Repositories
    {
        public class CategoryPoemRepository : EfCoreRepository<PoemDbContext, CategoryPoem, int>, ICategoryPoemRepository
        {
            public CategoryPoemRepository(IDbContextProvider<PoemDbContext> dbContextProvider)
            : base(dbContextProvider)
            {
    
            }
            public List<Category> GetPoemCategories(int poemid)
            {
                var set = DbContext.Set<CategoryPoem>().Include(o => o.Category).AsQueryable();
                var lst = set.Where(p => p.PoemId == poemid).Select(o => o.Category);
                return lst.ToList();
            }
    
            public List<Core.Poems.Poem> GetPoemsOfCategory(int categoryid)
            {
                var set = DbContext.Set<CategoryPoem>().Include(o => o.Poem).AsQueryable();
                var lst = set.Where(p => p.CategoryId == categoryid).Select(o=>o.Poem);
                return lst.ToList();
            }
        }
    }
    
    
    using Microsoft.EntityFrameworkCore;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
    using Volo.Abp.EntityFrameworkCore;
    using ZL.AbpNext.Poem.Core.Repositories;
    using ZL.AbpNext.Poem.EF.EntityFramework;
    
    namespace ZL.AbpNext.Poem.EF.Repositories
    {
        public class PoemRepository : EfCoreRepository<PoemDbContext, Core.Poems.Poem, int>, IPoemRepository
        {
            public PoemRepository(IDbContextProvider<PoemDbContext> dbContextProvider)
            : base(dbContextProvider)
            {
    
            }
    
            public Task<List<Core.Poems.Poem>> GetPagedPoems(int maxResult, int skip, string author, string keyword, string[] categories, out int total)
            {
                var set=DbContext.Set<Core.Poems.Poem>().Include(o=>o.Author).Include(o=>o.PoemCategories).AsQueryable();
                if (!string.IsNullOrEmpty(author))
                {
                    set = set.Where(o => o.Author.Name == author);
                }
                if (!string.IsNullOrEmpty(keyword))
                {
                    set = set.Where(o => o.Title.Contains(keyword) );
                }
                if (categories != null && categories.Length > 0)
                {
                    foreach (var category in categories)
                    {
                        set = set.Where(o => o.PoemCategories.Any(q => q.Category.CategoryName == category));
                    }
                }
                total = set.Count();
                var lst = set.OrderBy(o => o.Id).PageBy(skip,maxResult).ToListAsync();
                return lst;
            }
        }
    }
    

    完整的PoemAppService如下:

    using System.Collections.Generic;
    using System.Linq;
    using Volo.Abp.Application.Dtos;
    using Volo.Abp.Application.Services;
    using Volo.Abp.Domain.Repositories;
    using ZL.AbpNext.Poem.Core.Poems;
    using ZL.AbpNext.Poem.Core.Repositories;
    
    namespace ZL.AbpNext.Poem.Application.Poems
    {
        public class PoemAppService : ApplicationService, IPoemAppService
        {
            private readonly IPoemRepository _poemRepository;
            private readonly IRepository<Category> _categoryRepository;
            private readonly IRepository<Poet> _poetRepository;
            private readonly ICategoryPoemRepository _categoryPoemRepository;
            public PoemAppService(IPoemRepository poemRepository
                , IRepository<Category> categoryRepository
                , IRepository<Poet> poetRepository
                , ICategoryPoemRepository categoryPoemRepository)
            {
                _poemRepository = poemRepository;
                _categoryRepository = categoryRepository;
                _poetRepository = poetRepository;
                _categoryPoemRepository = categoryPoemRepository;
            }
    
            public CategoryDto AddCategory(CategoryDto category)
            {
                var cate = _categoryRepository.FirstOrDefault(o => o.CategoryName == category.CategoryName);
    
                if (cate == null)
                {
                    cate= _categoryRepository.InsertAsync(new Category { CategoryName = category.CategoryName },true).Result;
                }
                return ObjectMapper.Map<Category,CategoryDto>(cate); 
                
            }
    
            public void AddPoemToCategory(CategoryPoemDto categoryPoem)
            {
                var categorypoem = _categoryPoemRepository.FirstOrDefault(o => o.CategoryId == categoryPoem.CategoryId && o.PoemId == categoryPoem.PoemId);
                if (categorypoem == null)
                {
                    categorypoem = new CategoryPoem { CategoryId = categoryPoem.CategoryId, PoemId = categoryPoem.PoemId };
                    _categoryPoemRepository.InsertAsync(categorypoem,true);
                }
            }
    
            public PoetDto AddPoet(PoetDto poet)
            {
                var addpoet=_poetRepository.InsertAsync(new Poet
                {
                     Name=poet.Name,
                     Description=poet.Description
                },true).Result;
                return new PoetDto
                {
                    Id=addpoet.Id,
                    Name=addpoet.Name,
                    Description=addpoet.Description
                };
            }
    
            public void DeleteCategory(CategoryDto category)
            {
                if (category.Id > 0)
                {
                    var cat = _categoryRepository.FirstOrDefault(o => o.Id == category.Id);
                    if (cat != null)
                    {
                        _categoryRepository.DeleteAsync(cat, true);
                    }
                }
                else if (!string.IsNullOrEmpty(category.CategoryName))
                {
                    var cat = _categoryRepository.FirstOrDefault(o => o.CategoryName == category.CategoryName);
                    if (cat != null)
                    {
                        _categoryRepository.DeleteAsync(cat,true);
                    }
                }
            }
    
            public List<CategoryDto> GetAllCategories()
            {
                return ObjectMapper.Map<List<Category>, List<CategoryDto>>(_categoryRepository.ToList());
            }
    
            public List<CategoryPoemDto> GetCategoryPoems()
            {
                return ObjectMapper.Map<List<CategoryPoem>, List<CategoryPoemDto>>(_categoryPoemRepository.ToList());
            }
    
            public PagedResultDto<PoemDto> GetPagedPoems(PagedResultRequestDto dto)
            {
                var count = _poemRepository.Count();
                var lst = _poemRepository.OrderBy(o => o.Id).PageBy(dto).ToList();
    
                return new PagedResultDto<PoemDto>
                {
                    TotalCount = count,
                    Items = ObjectMapper.Map<List<Core.Poems.Poem>, List<PoemDto>>(lst) //lst.MapTo<List<PoemDto>>()
                };
            }
    
            public PagedResultDto<PoetDto> GetPagedPoets(PagedResultRequestDto dto)
            {
                    var count = _poetRepository.Count();
                    var lst = _poetRepository.OrderBy(o => o.Id).PageBy(dto).ToList();
                    var items = new List<PoetDto>();
                    
                    return new PagedResultDto<PoetDto>
                    {
                        TotalCount = count,
                        Items = ObjectMapper.Map<List<Poet>, List<PoetDto>>(lst)
                    };
            }
    
            public List<CategoryDto> GetPoemCategories(int poemid)
            {
                var lst = _categoryPoemRepository.GetPoemCategories(poemid);
                return ObjectMapper.Map<List<Category>, List<CategoryDto>>(lst);
            }
    
            public List<PoemDto> GetPoemsOfCategory(int categoryid)
            {
                var lst = _categoryPoemRepository.GetPoemsOfCategory(categoryid);
                return ObjectMapper.Map<List<Core.Poems.Poem>, List<PoemDto>>(lst);
            }
    
            public void RemovePoemFromCategory(CategoryPoemDto categoryPoem)
            {
                var categorypoem = _categoryPoemRepository.FirstOrDefault(o => o.CategoryId == categoryPoem.CategoryId && o.PoemId == categoryPoem.PoemId);
                if (categorypoem != null)
                {
                    _categoryPoemRepository.DeleteAsync(categorypoem,true);
                }
            }
    
            public PagedResultDto<PoemDto> SearchPoems(SearchPoemDto dto)
            {
               
                int total;
                var lst = _poemRepository.GetPagedPoems(dto.MaxResultCount, dto.SkipCount, dto.AuthorName, dto.Keyword,dto.Categories, out total).Result;
                return new PagedResultDto<PoemDto> {
                    TotalCount = total,
                    Items=ObjectMapper.Map<List<Core.Poems.Poem>, List<PoemDto>>(lst)
            };
            }
    
            public PagedResultDto<PoetDto> SearchPoets(SearchPoetDto dto)
            {
                var res = _poetRepository.AsQueryable();
                if (!string.IsNullOrEmpty(dto.Keyword))
                {
                    res = res.Where(o => o.Name.Contains(dto.Keyword));
                }
                var count = res.Count();
                var lst = res.OrderBy(o => o.Id).PageBy(dto).ToList();
    
                return new PagedResultDto<PoetDto>
                {
                    TotalCount = count,
                    Items = ObjectMapper.Map< List < Poet> ,List <PoetDto>>(lst)
                };
            }
        }
    }
    
    
    展开全文
  • 初始化某个repository

    2015-06-25 09:03:54
    (2)思路:每个模块对应一个字符串,该字符串与service或repository同名,如“attributeRepository”、“analyticRepository”等。然后将该字符串及service或repository放入map中, 这样就可以根据传入的字符串得到...
  • Repository模式

    万次阅读 2015-09-22 19:27:19
    最近开发的MVC项目使用了Repository模式。啥是Repository模式?从图看,有一个仓库接口,一个实现了这个仓库接口的基类;然后在使用方,编写一个数据库操作类,一方面,要声明一个继承于仓库接口的子接口,另一方面...

    最近开发的MVC项目使用了Repository模式。

    啥是Repository模式?

    这里写图片描述

    从图看,有一个仓库接口,一个实现了这个仓库接口的基类;然后在使用方,一方面,要声明一个继承于仓库接口的子接口,另一方面,编写一个数据库操作类,继承仓库基类,并实现这个子接口。

    继承仓库基类容易理解,为啥还要搞一个子接口呢?直接实现仓库接口不就完啦?思考其中原因,应该是为了控制反转,依赖注入,总之一个类对应一个接口就是了。

    Repository模式意义何在呢?

    Repository模式是一个中间层,位于 数据库映射层 和 领域层(业务逻辑层)之间。本来嘛,ORM或者DAL已经为我们隔离了数据库,BLL并没有直接访问数据库,如果数据库更换,那改写ORM或DAL即可。那么现在又增加一层Repository,目的何在呢?

    摘录一些话,姑妄听之。反正他们牛逼,怎么说都行:

    Repository 是一个独立的层,介于领域层与数据映射层 (数据访问层) 之间。它的存在让领域层感觉不到数据访问层的存在,它提供一个类似集合的接口提供给领域层进行领域对象的访问。Repository 是仓库管理员,领域层需要什么东西只需告诉仓库管理员,由仓库管理员把东西拿给它,并不需要知道东西实际放在哪。(咦,难道DAL\ORM不是这样的吗?)
    Repository 模式是架构模式,在设计架构时,才有参考价值;
    Repository 模式主要是封装数据查询和存储逻辑;
    Repository 模式实际用途:更换、升级 ORM 引擎,不影响业务逻辑;
    Repository 模式能提高测试效率,单元测试时,用 Mock 对象代替实际的数据库存取,可以成倍地提高测试用例运行速度。

    这几句话中,好像亮点在于换ORM,比如将NHibernate换成EF,BLL也不受影响。呵呵。

    也有一些钻研者自我安慰:
    使用Repository,隐含着一种意图倾向,就是 Domain需要什么我才提供什么,不该提供的功能就不要提供,一切都是以Domain的需求为核心;而使用Dal,其意图倾向在于我Dal层能使用的数 据库访问操作提供给Business层,你Business要用哪个自己选。换一个Business也可以用我这个Dal,一切是以我Dal能提供什么操 作为核心。

    也有后起之秀顿悟:
    仓储模式最大的优点就是所有的数据访问首先是通过仓库的,对仓库的增删改都不会立即提交到数据库,而只有当调用了仓库包裹器,这些增删改的操作才会一次提交到数据库。

    但我怎么看,都看不出这个批量提交、仓库包裹器与Repository有什么关系。


    今天看到一种隐隐约约的说法,说资源库(大概就是Repository模式吧)有个好处,就是可以兼容缓存。BLL通过资源库来存取数据,而不必知道这些数据是来自于数据库还是缓存。

    展开全文
  • SpringDataJpa:JpaRepository增删改查

    万次阅读 多人点赞 2017-11-17 08:32:19
    1. JpaRepository简单查询 基本查询也分为两种,一种是spring data默认已经实现,一种是根据查询的方法来自动解析成SQL。 预先生成方法 spring data jpa 默认预先生成了一些基本的CURD的方法,例如:增、删、...

    Jpa查询

    1. JpaRepository简单查询

    基本查询也分为两种,一种是spring data默认已经实现,一种是根据查询的方法来自动解析成SQL。

    • 预先生成方法

    spring data jpa 默认预先生成了一些基本的CURD的方法,例如:增、删、改等等

    继承JpaRepository

    public interface UserRepository extends JpaRepository<User, Long> {
    }
    • 使用默认方法

    @Test
    public void testBaseQuery() throws Exception {
        User user=new User();
        userRepository.findAll();
        userRepository.findOne(1l);
        userRepository.save(user);
        userRepository.delete(user);
        userRepository.count();
        userRepository.exists(1l);
        // ...
    }
    • 自定义的简单查询就是根据方法名来自动生成SQL,主要的语法是findXXBy,readAXXBy,queryXXBy,countXXBygetXXBy后面跟属性名称:
    • 具体的关键字,使用方法和生产成SQL如下表所示
    Keyword Sample JPQL snippet
    And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2
    Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
    Is,Equals findByFirstnameIs,findByFirstnameEquals … where x.firstname = ?1
    Between findByStartDateBetween … where x.startDate between ?1 and ?2
    LessThan findByAgeLessThan … where x.age < ?1
    LessThanEqual findByAgeLessThanEqual … where x.age ⇐ ?1
    GreaterThan findByAgeGreaterThan … where x.age > ?1
    GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1
    After findByStartDateAfter … where x.startDate > ?1
    Before findByStartDateBefore … where x.startDate < ?1
    IsNull findByAgeIsNull … where x.age is null
    IsNotNull,NotNull findByAge(Is)NotNull … where x.age not null
    Like findByFirstnameLike … where x.firstname like ?1
    NotLike findByFirstnameNotLike … where x.firstname not like ?1
    StartingWith findByFirstnameStartingWith … where x.firstname like ?1 (parameter bound with appended %)
    EndingWith findByFirstnameEndingWith … where x.firstname like ?1 (parameter bound with prepended %)
    Containing findByFirstnameContaining … where x.firstname like ?1 (parameter bound wrapped in %)
    OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc
    Not findByLastnameNot … where x.lastname <> ?1
    In findByAgeIn(Collection ages) … where x.age in ?1
    NotIn findByAgeNotIn(Collection age) … where x.age not in ?1
    TRUE findByActiveTrue() … where x.active = true
    FALSE findByActiveFalse() … where x.active = false
    IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstame) = UPPER(?1)

    按照Spring Data的规范,查询方法以find | read | get 开头,涉及查询条件时,条件的属性条件关键字连接,

    要注意的是条件属性以首字母大写

    • 示例:

    例如:定义一个Entity实体类:

    class People{
           private String firstName;
           private String lastName;
    }

    以上使用and条件查询时,应这样写:

    findByLastNameAndFirstName(String lastName,String firstName);

    注意:条件的属性名称与个数要与参数的位置与个数一一对应

     

    2.JpaRepository查询方法解析流程

    JPA方法名解析流程

    • Spring Data JPA框架在进行方法名解析时,会先把方法名多余的前缀截取掉
    • 比如findfindByreadreadBygetgetBy,然后对剩下部分进行解析。
    • 假如创建如下的查询:findByUserDepUuid(),框架在解析该方法时,首先剔除findBy,然后对剩下的属性进行解析,假设查询实体为Doc

    -- 1.先判断userDepUuid (根据POJOPlain Ordinary Java Object简单java对象,实际就是普通java bean)规范,首字母变为小写。)是否是查询实体的一个属性

    如果根据该属性进行查询;如果没有该属性,继续第二步。

     

    -- 2.从右往左截取第一个大写字母开头的字符串(此处为Uuid),然后检查剩下的字符串是否为查询实体的一个属性

    如果是,则表示根据该属性进行查询;如果没有该属性,则重复第二步,继续从右往左截取;最后假设 user为查询实体的一个属性。

     

    -- 3.接着处理剩下部分DepUuid),先判断 user 所对应的类型是否有depUuid属性,

    如果有,则表示该方法最终是根据 Doc.user.depUuid 的取值进行查询;

    否则继续按照步骤 2 的规则从右往左截取,最终表示根据 Doc.user.dep.uuid 的值进行查询。

     

    -- 4.可能会存在一种特殊情况,比如 Doc包含一个 user 的属性,也有一个 userDep 属性,此时会存在混淆。

    可以明确在属性之间加上 "_" 以显式表达意图,比如 "findByUser_DepUuid()" 或者 "findByUserDep_uuid()"


    特殊的参数(分页或排序):

    • 还可以直接在方法的参数上加入分页或排序的参数,比如:
    Page<UserModel> findByName(String name, Pageable pageable);
    List<UserModel> findByName(String name, Sort sort);
    • Pageable 是spring封装的分页实现类,使用的时候需要传入页数、每页条数和排序规则
    @Test
    public void testPageQuery() throws Exception {
        int page=1,size=10;
        Sort sort = new Sort(Direction.DESC, "id");
        Pageable pageable = new PageRequest(page, size, sort);
        userRepository.findALL(pageable);
        userRepository.findByUserName("testName", pageable);
    }

    使用JPANamedQueries

    • 方法如下:

    1:在实体类上使用@NamedQuery,示例如下:

    @NamedQuery(name = "UserModel.findByAge",query = "select o from UserModel o where o.age >= ?1")

     

    2:在自己实现的DAO的Repository接口里面定义一个同名的方法,示例如下:

    public List<UserModel> findByAge(int age);

     

    3:然后就可以使用了,Spring会先找是否有同名的NamedQuery,如果有,那么就不会按照接口定义的方法来解析。

    使用@Query来指定本地查询

    只要设置nativeQuery为true

    • 比如:
    @Query(value="select * from tbl_user where name like %?1" ,nativeQuery=true)
    public List<UserModel> findByUuidOrAge(String name);

    注意:当前版本的本地查询不支持翻页和动态的排序

    使用命名化参数

    使用@Param即可

    比如:

    @Query(value="select o from UserModel o where o.name like %:nn")
    public List<UserModel> findByUuidOrAge(@Param("nn") String name);

    创建查询的顺序

    • Spring Data JPA 在为接口创建代理对象时,如果发现同时存在多种上述情况可用,它该优先采用哪种策略呢?

    <jpa:repositories> 提供了query-lookup-strategy 属性,用以指定查找的顺序。它有如下三个取值:

     

    1:create-if-not-found:

    如果方法通过@Query指定了查询语句,则使用该语句实现查询;

    如果没有,则查找是否定义了符合条件的命名查询,如果找到,则使用该命名查询;

    如果两者都没有找到,则通过解析方法名字来创建查询。

    这是querylookup-strategy 属性的默认值

     

    2:create:通过解析方法名字来创建查询。

    即使有符合的命名查询,或者方法通过@Query指定的查询语句,都将会被忽略

     

    3:use-declared-query:

    如果方法通过@Query指定了查询语句,则使用该语句实现查询;

    如果没有,则查找是否定义了符合条件的命名查询,如果找到,则使用该

    命名查询;如果两者都没有找到,则抛出异常

    3.JpaRepository限制查询

    • 有时候我们只需要查询前N个元素,或者支取前一个实体。
    User findFirstByOrderByLastnameAsc();
    User findTopByOrderByAgeDesc();
    Page<User> queryFirst10ByLastname(String lastname, Pageable pageable);
    List<User> findFirst10ByLastname(String lastname, Sort sort);
    List<User> findTop10ByLastname(String lastname, Pageable pageable);

    4.JpaRepository多表查询

    • 多表查询在spring data jpa中有两种实现方式,第一种是利用hibernate的级联查询来实现,第二种是创建一个结果集的接口来接收连表查询后的结果,这里主要第二种方式。
    • 首先需要定义一个结果集的接口类
    public interface HotelSummary {
        City getCity();
        String getName();
        Double getAverageRating();
        default Integer getAverageRatingRounded() {
            return getAverageRating() == null ? null : (int) Math.round(getAverageRating());
        }
    }
    • 查询的方法返回类型设置为新创建的接口
    @Query("select h.city as city, h.name as name, avg(r.rating) as averageRating "
            + "from Hotel h left outer join h.reviews r where h.city = ?1 group by h")
    Page<HotelSummary> findByCity(City city, Pageable pageable);
    
    
    @Query("select h.name as name, avg(r.rating) as averageRating "
            + "from Hotel h left outer join h.reviews r  group by h")
    Page<HotelSummary> findByCity(Pageable pageable);
    • 使用
    Page<HotelSummary> hotels = this.hotelRepository.findByCity(new PageRequest(0, 10, Direction.ASC, "name"));
    for(HotelSummary summay:hotels){
            System.out.println("Name" +summay.getName());
        }

    在运行中Spring会给接口(HotelSummary)自动生产一个代理类来接收返回的结果,代码汇总使用getXX的形式来获取

     

    JPA更新

    支持更新类的Query语句

    添加@Modifying即可

    • 比如:
    @Modifying
    @Query(value="update UserModel o set o.name=:newName where o.name like %:nn")
    public int findByUuidOrAge(@Param("nn") String name,@Param("newName") String newName);

    注意:

    1:方法的返回值应该是int,表示更新语句所影响的行数

    2:在调用的地方必须加事务,没有事务不能正常执行

    JPA删除

     

    SQL方式-删除

    @Query(value = "delete from r_upa where user_id= ?1 and point_indecs_id in (?2)", nativeQuery = true)
    @Modifying
    void deleteByUserAndPointIndecs(Long uid, List<Long> hids);

    注意:

    执行delete和update语句一样,需要添加@Modifying注解,使用时在Repository或者更上层需要@Transactional注解。

    函数(delete)方式-删除

    • 直接可以使用delete(id),依据id来删除一条数据
    • 也可以使用deleteByName(String name)时,需要添加@Transactional注解,才能使用
    • Spring Data JPA的deleteByXXXX,是先select,在整个Transaction完了之后才执行delete

     JpaRepository

    @NoRepositoryBean
    public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
        
        /**
    	 * Deletes the given entities in a batch which means it will create a single {@link Query}. Assume that we will clear
    	 * the {@link javax.persistence.EntityManager} after the call.
    	 *
    	 * @param entities
         * 批量解绑多个,优势:只会形成一个SQL语句
    	 */
    	void deleteInBatch(Iterable<T> entities);
    
    	/**
    	 * Deletes all entities in a batch call.
    	 */
    	void deleteAllInBatch();
    
       
    }

    CrudRepository

    @NoRepositoryBean
    public interface CrudRepository<T, ID> extends Repository<T, ID> {
       
        /**
    	 * Deletes the entity with the given id.
    	 *
    	 * @param id must not be {@literal null}.
    	 * @throws IllegalArgumentException in case the given {@code id} is {@literal null}
    	 */
    	void deleteById(ID id);
    
    	/**
    	 * Deletes a given entity.
    	 *
    	 * @param entity
    	 * @throws IllegalArgumentException in case the given entity is {@literal null}.
    	 */
    	void delete(T entity);
    
    	/**
    	 * Deletes the given entities.
    	 *
    	 * @param entities
    	 * @throws IllegalArgumentException in case the given {@link Iterable} is {@literal null}.
    	 */
    	void deleteAll(Iterable<? extends T> entities);
    
    	/**
    	 * Deletes all entities managed by the repository.
    	 */
    	void deleteAll();
    }

     

    JPA添加

    利用JpaRepository和CrudRepository中的 save操作

    JpaRepository

    @NoRepositoryBean
    public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
    
    	
    	/*
    	 * (non-Javadoc)
    	 * @see org.springframework.data.repository.CrudRepository#save(java.lang.Iterable)
    	 */
    	<S extends T> List<S> saveAll(Iterable<S> entities);
    
    	/**
    	 * Flushes all pending changes to the database.
    	 */
    	void flush();
    
    	/**
    	 * Saves an entity and flushes changes instantly.
    	 *
    	 * @param entity
    	 * @return the saved entity
    	 */
    	<S extends T> S saveAndFlush(S entity);
    
    	
    }

    CrudRepository

    @NoRepositoryBean
    public interface CrudRepository<T, ID> extends Repository<T, ID> {
    
    	/**
    	 * Saves a given entity. Use the returned instance for further operations as the save operation might have changed the
    	 * entity instance completely.
    	 *
    	 * @param entity must not be {@literal null}.
    	 * @return the saved entity will never be {@literal null}.
    	 */
    	<S extends T> S save(S entity);
    
    	/**
    	 * Saves all given entities.
    	 *
    	 * @param entities must not be {@literal null}.
    	 * @return the saved entities will never be {@literal null}.
    	 * @throws IllegalArgumentException in case the given entity is {@literal null}.
    	 */
    	<S extends T> Iterable<S> saveAll(Iterable<S> entities);
    }

    JpaRepository和CrudRepository 的区别

    • JpaRepository 中的save方法实现源码:
      @Transactional
        public <S extends T> List<S> save(Iterable<S> entities) {
            List<S> result = new ArrayList<S>();
            if (entities == null) {
                return result;
            }
            for (S entity : entities) {
                result.add(save(entity));
            }
            return result;
        }
    • CrudRepository 中的save方法源代码
    @Transactional
        public <S extends T> S save(S entity) {
            if (entityInformation.isNew(entity)) {
                em.persist(entity);//是新的就插入
                return entity;
            } else {
                return em.merge(entity); //不是新的merge
            }
        }

    由源码可知CrudRepository 中的save方法是相当于merge+save ,它会先判断记录是否存在,如果存在则更新,不存在则插入记录

     

    参考来源:http://www.ityouknow.com/springboot/2016/08/20/springboot(%E4%BA%94)-spring-data-jpa%E7%9A%84%E4%BD%BF%E7%94%A8.html

    展开全文
  • 上篇中将本地SSH添加到... fatal: Not a git repository (or any of the parent directories): .git 提示说没有.git这样一个目录 在命令行 输入 git init 然后回车就好了 再重新执行添加文件的命令即可。 ...
  • 其中试过加@Component和@Repository注解 但是都没用 依然报required a bean of type 'com.ncusc.dms.repository.StudentRepository' that could not be found 就是扫描不到StudentRepository,求各位大佬帮帮忙
  • @Repository

    万次阅读 多人点赞 2019-03-08 20:43:03
    初学spring boot,遇到的第一个坎就是好多注解都不知道作用,即使照猫画虎把代码敲出来运行成功,也没有些许成就感。原因其实很简单,我觉得自己还没真的学会。接下来就是找资料,理解原理与过程,不求理解的深度,...
  • Github Transfer Repository (在 Github上转移 Repository) 流程全解。
  • Oracle Integration Repository

    千次阅读 2013-01-15 11:41:43
    How to access 'Integration Repository' From E-Business SuiteResponsibility : 'Integration Repository' (12.0.x) 'Integrated SOA Gateway' (12.1.x)From the Public Web Sitehttp://irep.oracle.com/(This si
  • springvmc采用经典的三层分层控制结构,在持久层,业务层和控制层分别采用@Repository、@Service、@Controller对分层中的类进行注解,而@Component对那些比较中立的类进行注解 1. @Controller控制层 @Controller...
  • 然后按照网上的配置就可以使用ElasticsearchRepository。 但是如果是spring的话 会有问题,ElasticsearchRepository 这个类的 子类 应该是不同实例化的,也就是不用给他加@Bean这些注解, 但是我发现如果...
  • Spring 为java web 开发领域提供了大量的优秀的框架,第三方包,大大解放了生产力,本文主要介绍Spring Repository在连接数据库这边做的一些封装,并以Mongo Repository为例,详细阐述下Repository实现机制,本文...
  • Repository接口

    2019-08-11 11:13:56
    Repository接口   前文我们自定义的 UserDao 实现了 Repository 接口,这个 Repository 接口是什么来头呢? 首先来看 Repository 的一个继承关系图: 可以看到,实现类不少。那么到底如何理解 Repository 呢?  ...
  • ElasticSearchRepository和ElasticSearchTemplate的使用

    万次阅读 多人点赞 2017-07-26 17:28:29
    Spring-data-elasticsearch,ElasticSearchTemplate使用,ElasticSearchRepository使用,ES的用法
  • Repository和Registry区别

    千次阅读 2017-07-05 23:46:56
    Repository:本身是一个仓库,这个仓库里面可以放具体的镜像,是指具体的某个镜像的仓库,比如Tomcat下面有很多个版本的镜像,它们共同组成了Tomcat的Repository。Registry:镜像的仓库,比如Docker Hub,Registry上...
  • 1.insert
  • maven repository

    万次阅读 热门讨论 2009-11-26 10:56:00
    什么是Maven仓库在不用Maven的时候,比如说以前我们用Ant构建项目,在项目目录下,往往会看到一个名为/lib的子目录,那里存放着各类第三方依赖jar文件,如log4j.jar,junit.jar等等。每建立一个项目,你都需要建立...
  • android_m2repository_r07

    热门讨论 2015-02-17 14:25:38
    最新的Android Support Repository下载,Android Studio需要Android Support Repository的支持,否则会出现Failed to find : com.android.support:appcompat-v7错误。解决此问题需要安装最新的资源库。 使用方法:将...
  • JpaRepository

    千次阅读 2019-07-19 16:05:44
    见:https://blog.csdn.net/fly910905/article/details/78557110
  • 在Fedora里执行:$sudo yum update Loaded plugins: langpacks, presto, refresh-packagekit Adding en_US to language ...Error: Cannot retrieve repository metadata (repomd.xml) for repository: fedora. Please v
  • @repository

    千次阅读 2018-07-12 21:58:02
    @Component是 @Service @Controller @Repository 的父注解 通过类路径扫描自动检测实现类 * Indicates that an annotated class is a "component". * Such classes are considered as candidates for ...
  • @Repository的作用?

    万次阅读 多人点赞 2018-07-09 10:32:09
    Spring的注解形式:@Repository、@Service、@Controller,它们分别对应存储层Bean,业务层Bean,和展示层Bean。@Repository、@Service、@Controller 和 @Component 将类标识为BeanSpring 自 2.0 版本开始,陆续引入...

空空如也

1 2 3 4 5 ... 20
收藏数 104,665
精华内容 41,866
关键字:

repository