JPA实践&多种场景应用集锦

JPA官方地址


JPA语法规则:
JPA框架在进行方法名解析时,会先把方法名多余的前缀截取掉,比如 find、findBy、read、readBy、get、getBy,然后对剩下部分进行解析。并且如果方法的最后一个参数是 Sort 或者 Pageable 类型,也会提取相关的信息,以便按规则进行排序或者分页查询。 
And — 等价于 SQL 中的 and 关键字,比如 findByUsernameAndPassword(String user, Striang pwd); 
Or — 等价于 SQL 中的 or 关键字,比如 findByUsernameOrAddress(String user, String addr); 
Between — 等价于 SQL 中的 between 关键字,比如 findBySalaryBetween(int max, int min); 
LessThan — 等价于 SQL 中的 “<”,比如 findBySalaryLessThan(int max); 
GreaterThan — 等价于 SQL 中的”>”,比如 findBySalaryGreaterThan(int min); 
IsNull — 等价于 SQL 中的 “is null”,比如 findByUsernameIsNull(); 
IsNotNull — 等价于 SQL 中的 “is not null”,比如 findByUsernameIsNotNull(); 
NotNull — 与 IsNotNull 等价; 
Like — 等价于 SQL 中的 “like”,比如 findByUsernameLike(String user); 
NotLike — 等价于 SQL 中的 “not like”,比如 findByUsernameNotLike(String user); 
OrderBy — 等价于 SQL 中的 “order by”,比如 findByUsernameOrderBySalaryAsc(String user); 
Not — 等价于 SQL 中的 “! =”,比如 findByUsernameNot(String user); 
In — 等价于 SQL 中的 “in”,比如 findByUsernameIn(Collection userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数; 
NotIn — 等价于 SQL 中的 “not in”,比如 findByUsernameNotIn(Collection userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;


Entity - 设定递增列UUID:
@Id
@GenericGenerator(name = "PKUUID", strategy = "uuid2")
@GeneratedValue(generator = "PKUUID")
@Column(length = 36)
protected String id;

在Entity添加1:n 或m:n映射:

示例:
Floor类:
@OneToMany (fetch =  FetchType.LAZY ,mappedBy =  "floor" )  
private  List<FloorContent>  floorContents ;  

FloorContent类:
@ManyToOne   
@JoinColumn (name =  "floor_id" ,foreignKey =  @ForeignKey (name =  "fk_floor_fc" ))  
private  Floor  floor

连接查询 方法:
public   interface  FloorContentRepos  extends  JpaRepository<FloorContent,String>{  
public  Page<FloorContent>  findByFloor_IdAndIsDeleteOrderByShowIndexAsc (String floorId, boolean  b, Pageable pageable);  
}  

注意:在findBy后面添加要关联的实体类,然后在 实体类后面写上“_”,"_"符号后面是添加关联表的字段而不是本身表的字段。
And+表名字+“_”+表中要查询的字段。


生成关联表
不希望生成: @OneToMany( mappedBy = "a" )  


Like写法:
@Query ( "SELECT u.username FROM User u WHERE u.username LIKE CONCAT('%',:username,'%')" )

使用@Query注解实现复杂查询:
方式一:
@Query("select a from AccountInfo a where a.accountId = ?1") public AccountInfo findByAccountId(Long accountId);

方式二:
@Query("from AccountInfo a where a.accountId = :id") public AccountInfo findByAccountId(@Param("id")Long accountId);

//使用 @Modifying 将查询标识为修改 @Modifying @Query("update AccountInfo a set a.salary = ?1 where a.salary < ?2") public int increaseSalary(int after, int before);


SpringMVC中JPA(含分页功能)的使用:
    @RequestMapping(value = { "list", "" }) 
    public String list(Model model, HttpServletRequest request) { 
        int page = 0; 
        int pageSize = 10; 
        Pageable pager =new PageRequest(page, pageSize); 
        Page<Employee> employeesPage = manager.getPageEmployee(pager); 
        model.addAttribute("employees", employeesPage.getContent()); 
        model.addAttribute("resultTotal", employeesPage.getTotalElements()); 
        return "employee/queryEmployee"; 
    }

Demo参考:
(包括注入EntityManagerFactory的方式)

findAll(pageable) 查询:
public Page<Task> getUserTask(Long userId, Map<String, Object> searchParams, int pageNumber, int pageSize,
            String sortType) {
        PageRequest pageRequest = buildPageRequest(pageNumber, pageSize, sortType);
        Specification<Task> spec = buildSpecification(userId, searchParams);
  
        return taskDao.findAll(spec, pageRequest);
    }
  
    /**
     * 创建分页请求.
     */
    private PageRequest buildPageRequest(int pageNumber, int pagzSize, String sortType) {
        Sort sort = null;
        if ("auto".equals(sortType)) {
            sort = new Sort(Direction.DESC, "id");
        } else if ("title".equals(sortType)) {
            sort = new Sort(Direction.ASC, "title");
        }
  
        return new PageRequest(pageNumber - 1, pagzSize, sort);
    }
  
    /**
     * 创建动态查询条件组合:https://github.com/springside/springside4
     */
    private Specification<Task> buildSpecification(Long userId, Map<String, Object> searchParams) {
        Map<String, SearchFilter> filters = SearchFilter.parse(searchParams);
        filters.put("user.id", new SearchFilter("user.id", Operator.EQ, userId));
        Specification<Task> spec = DynamicSpecifications.bySearchFilter(filters.values(), Task.class);
        return spec;
    }



使用传统的EnitityManager来查询单条记录:
@Autowired
private EnitityManager em;

em.createQuery(query).setFirstResult(start).setMaxResults(max).getResultList();

添加查询条件:
使用 Specification<T>或 Criteria<T>
Criteria<UserInfo> criteria = new Criteria<>();criteria.add(Restrictions.eq("id",10)).add(Restrictions.like("name","abc"));
 criteria.add(Restrictions.hasMembers("address.name", "北京"));
criteria.add(Restrictions.hasMembers("provinces", "110000", "120000"));List<UserInfo> users = userInfoService.findAll(criteria);
Page page = userRepository.findAll(criteria, new PageRequest(0, 10));


处理一对多的查询:
@Override
    @SuppressWarnings({"rawtypes", "unchecked"})
    public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query,
                                 CriteriaBuilder builder) {
        Path expression;

        //此处是表关联数据,注意仅限一层关联,如user.address,
        //查询user的address集合中,address的name为某个值
        if (fieldName.contains(".")) {
            String[] names = StringUtils.split(fieldName, ".");
            //获取该属性的类型,Set?List?Map?
            expression = root.get(names[0]);
            Class clazz = expression.getJavaType();
            if (clazz.equals(Set.class)) {
                SetJoin setJoin = root.joinSet(names[0]);
                expression = setJoin.get(names[1]);
            } else if (clazz.equals(List.class)) {
                ListJoin listJoin = root.joinList(names[0]);
                expression = listJoin.get(names[1]);
            } else if (clazz.equals(Map.class)) {
                MapJoin mapJoin = root.joinMap(names[0]);
                expression = mapJoin.get(names[1]);
            } else {
                //是many to one时
                expression = expression.get(names[1]);
            }

        } else {
            //单表查询
            expression = root.get(fieldName);
        }

FetchType应用:
fetch = FetchType.EAGER 作用
如果是EAGER,那么表示取出这条数据时,它关联的数据也同时取出放入内存中
如果是LAZY,那么取出这条数据时,它关联的数据并不取出来,在同一个session中,什么时候要用,就什么时候取(再次访问数据库)。
但是,在session外,就不能再取了。用EAGER时,因为在内存里,所以在session外也可以取。
一般只在一边设Eager,JPA接口默认为一对多为Lazy,多对一为Eager,但是Hibernate反向工程生成Entity时,多对一为Lazy, 需要手动改为Eager



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值