Spring-data-jpa
1.背景介绍
什么是jpa?
JPA本质上就是一种ORM规范,注意不是ORM框架——因为JPA并未提供ORM实现,它只是制订了一些规范,提供了一些编程的API接口,但具体实现则由服务厂商来提供实现,JBoss应用服务器底层就以Hibernate作为JPA的实现。 既然JPA作为一种规范——也就说JPA规范中提供的只是一些接口,显然接口不能直接拿来使用。虽然应用程序可以面向接口编程,但JPA底层一定需要某种JPA实现,否则JPA依然无法使用。
2.知识剖析
Spring Data JPA与JPA规范的关系
实现应用程序的数据访问层已经很麻烦了好一阵子。太多的样板代码必须被写入。Domain classes,并没有被设计成面向一个真正的对象或领域驱动的方式。 使用spring data jpa能够使丰富的Domain classes的持久性开发变得轻松很多,即使样板代码来实现存储库量特别还是相当高的。所以Spring data jpa的目标是简化关于各种持久存储数据访问层而努力。 备注:Domain classes 指的是POJO类,例如数据库中有一张表:Student,那么我们会在程序中定义与之对应的Student.java,而这个Student.java就是属于Domain classes。
Spring Data JPA 是在JPA规范的基础下提供了Repository层的实现,但是使用那一款ORM需要你自己去决定。 我的理解是:虽然ORM框架都实现了JPA规范,但是在不同ORM框架之间切换是需要编写的代码有一些差异,而通过使用Spring Data Jpa能够方便大家在不同的ORM框架中间进行切换而不要更改代码。并且Spring Data Jpa对Repository层封装的很好,可以省去不少的麻烦
3.常见问题
Spring data Jpa 都能干什么?
4.解决方案
(1)基本CRUD
@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
List<T> findAll();
List<T> findAll(Sort var1);
List<T> findAllById(Iterable<ID> var1);
<S extends T> List<S> saveAll(Iterable<S> var1);
void flush();
<S extends T> S saveAndFlush(S var1);
void deleteInBatch(Iterable<T> var1);
void deleteAllInBatch();
T getOne(ID var1);
<S extends T> List<S> findAll(Example<S> var1);
<S extends T> List<S> findAll(Example<S> var1, Sort var2);
}
Api中已经封装好,我们可以直接用
(2)分页查询
通过传递pageable对象
(3)动态查询
@Override
public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
List<Predicate> predicates = new ArrayList<Predicate>();
// 标题
if(StringUtils.hasLength(videoDTO.getTitle())){
// criteriaBuilder.ge() 是大于的意思
predicates.add(criteriaBuilder.like(root.<String>get("title"),videoDTO.getTitle()));
}
// 类型
if(videoDTO.getType()!=null){
predicates.add(criteriaBuilder.equal(root.<Integer>get("type"),videoDTO.getType()));
}
// 所属年级
if(videoDTO.getGrade()!=null){
predicates.add(criteriaBuilder.equal(root.<Integer>get("grade"),videoDTO.getGrade()));
}
// 科目
if(videoDTO.getSubject()!= null){
predicates.add(criteriaBuilder.equal(root.<Integer>get("subject"),videoDTO.getSubject()));
}
//点赞数区间
if(videoDTO.getMinLike()!=null && videoDTO.getMaxLike()!=null){
predicates.add(criteriaBuilder.between(root.<Integer>get("userLike"),videoDTO.getMinLike(),videoDTO.getMaxLike()));
}
// 收藏数区间
if(videoDTO.getMinCollection()!=null && videoDTO.getMaxCollection()!=null){
predicates.add(criteriaBuilder.between(root.<Integer>get("collection"),videoDTO.getMinCollection(),videoDTO.getMaxCollection()));
}
//老师id
if(videoDTO.getTid() != null){
predicates.add(criteriaBuilder.equal(root.<Long>get("teacherId"),videoDTO.getTid()));
}
// if(StringUtils.hasLength(person.getCreateAt()+"")){ where id = id and name = name;
// // criteriaBuilder.ge() 是大于等于的意思
// predicates.add(criteriaBuilder.ge(root.<Long>get("createAt"),person.getCreateAt()));
// }
//状态
if(videoDTO.getStatus()!=null){
predicates.add(criteriaBuilder.equal(root.<Integer>get("status"),videoDTO.getStatus()));
}
其他功能有待发现
5.编码实战
6.扩展思考
用JPA实现连表查询
原生方式和注解方式
7.参考文献
https://docs.spring.io/spring-data/jpa/docs/2.0.8.RELEASE/reference/html/
https://blog.youkuaiyun.com/u014421556/article/details/52635000
8.更多讨论
1.如何用Spring-data-jpa实现多表联查?
答:可以用@quary注解写原生sql语句实现。
2.@@DynamicUpdate@DynamicInsert作用?
答:标注支持动态查询。没有以上注解是,jpa默认将 一个类所有字段insert或update,即使该字段为空也insert一个null。加上后只insert不为null的字段,更新是将只更新值被改变的字段。
3.Jpa如何使用外键?
实例:
@ManyToMany(cascade = { CascadeType.REFRESH }, fetch = FetchType.LAZY)
@JoinTable(name = "tb_user_role", joinColumns = { @JoinColumn(name = "user_id") }, inverseJoinColumns = { @JoinColumn(name = "role_id") })
private java.util.Set<Role> roles;
public Integer getId() {
return id;
}
实体与实体的关系有一对多、多对多、多对一。对应使用jpa注解@ManyToMang、@ManyToOne、@OneToMany。
以及通过fetch = FetchType.LAZY开启懒加载模式。
感谢观看,如有出错,恳请指正
BY : LittleSong