JPA指南分为3个部分:
- jpa注解详解
- jpa继承的Repository类详解
- jpa查询指南(单体查询+多表查询)
JPA注解
@Table 标注类对应的表
若表名和类型相同时,省略@Table,比如类Users 和表 users;
若不相同时,必须有@Table,并设置name,为该类对应的表名。@Table(name=”users”) 对应的表
@Entity 标注实体
@Id 标注id
@Transient 标注该属性不做与表的映射(原因:可能表中没有该属性对应的字段)
有该注解,在执行sql语句时,就不会出现该属性,否则会有,若表中没有该字段则会报错
@Basic 默认所有属性都有该注解(主键需要单独使用@Id),所以可以省略
该注解可以放在属性上,也可以放在对应的getter方法上。
注意:要么统一将@Basic放在属性上,要么统一放在对应的getter方法上。(一般都放在属性上,可读性比较好)
@Column 类中属性名和表中对应字段名不相同时,会使用该注解,指明在类中对应的字段
@Column(name=”对应的表中字段名”)
JPA的Reposity类
- CrudRepository接口。
其中T是要操作的实体类,ID是实体类主键的类型。该接口提供了11个常用操作方法。
<S extends T> S save(S entity);//保存
<S extends T> Iterable<S> save(Iterable<S> entities);//批量保存
T findOne(ID id);//根据id 查询一个对象。返回对象本身,当对象不存在时,返回null
Iterable<T> findAll();//查询所有的对象
Iterable<T> findAll(Iterable<ID> ids);//根据id列表 查询所有的对象
boolean exists(ID id);//根据id 判断对象是否存在
long count();//计算对象的总个数
void delete(ID id);//根据id 删除
void delete(T entity);//删除一个对象
void delete(Iterable<? extends T> entities);//批量删除,集合对象(后台执行时,一条一条删除)
void deleteAll();//删除所有 (后台执行时,一条一条删除)
- PagingAndSortingRepository接口。
该接口继承了CrudRepository接口,提供了两个方法,实现了分页和排序的功能了。
Iterable<T> findAll(Sort sort);// 仅排序
Page<T> findAll(Pageable pageable);// 分页和排序
- JpaRepository接口。
该接口继承了PagingAndSortingRepository接口,同时也继承QueryByExampleExecutor接口。
List<T> findAll(); //查询所有对象,返回List
List<T> findAll(Sort sort); //查询所有对象,并排序,返回List
List<T> findAll(Iterable<ID> ids); //根据id列表 查询所有的对象,返回List
void flush(); //强制缓存与数据库同步
<S extends T> List<S> save(Iterable<S> entities); //批量保存,并返回对象List
<S extends T> S saveAndFlush(S entity); //保存并强制同步数据库
void deleteInBatch(Iterable<T> entities); //批量删除 集合对象(后台执行时,生成一条语句执行,用多个or条件)
void deleteAllInBatch();//删除所有 (执行一条语句,如:delete from user)
T getOne(ID id); //根据id 查询一个对象,返回对象的引用(区别于findOne)。当对象不存时,返回引用不是null,但各个属性值是null
<S extends T> List<S> findAll(Example<S> example); //根据实例查询
@Override
<S extends T> List<S> findAll(Example<S> example, Sort sort);//根据实例查询,并排序。
- JpaSpecificationExecutor
提供了以下方法,可以和crud一起用
public interface JpaSpecificationExecutor<T> {
T findOne(Specification<T> var1);
List<T> findAll(Specification<T> var1);
Page<T> findAll(Specification<T> var1, Pageable var2);
List<T> findAll(Specification<T> var1, Sort var2);
long count(Specification<T> var1);
}
JPA查询方法列举
- ExampleMatcher创建查询条件数据对象
Collection<User> queryByExampleMatcher() {
User user = new User();
user.setName("10010");
Example<User> userExample = Example.of(user, ExampleMatcher.matching().withMatcher("name",
/*startsWith -> 10010%
* endsWith -> %10010
* contains -> %10010%
* */
ExampleMatcher.GenericPropertyMatchers.startsWith()));
return userRepository.findAll(userExample);
}
- CriteriaBuilder条件构造查询
//查询年龄大于22岁的员工
CriteriaBuilder cb = this.getEntityManager().getCriteriaBuilder();
CriteriaQuery<Employee> criteriaQuery = criteriaBuilder.createQuery(Employee.class);
Root<Employee> employee = criteriaQuery.from(Employee.class);
//设置条件
Predicate condition = criteriaBuilder.gt(employee.get(Employee_.age), 22);
criteriaQuery.where(condition);
TypedQuery<Employee> typedQuery = em.createQuery(criteriaQuery);
List<Employee> result = typedQuery.getResultList();
@Query查询
这个应该就是比较标准的jpa查询了吧
public interface User extends JpaRepository<User, Long> {
@Query("select t from User t where t.UserName = ?1")
User findByUserName(String UserName);
}
//@Query上面的1代表的是方法参数里面的顺序
//除了写hql(就是from的是对象,要设置nativeQuery = true),我们还可以写sql语句
public interface User extends JpaRepository<User, Long> {
@Query("select * from tb_User t where t.User_name = ?1", nativeQuery = true)
User findByUserName(String UserName);
}
//在参数绑定上,我们还可以用@Param
public interface User extends JpaRepository<User, Long> {
@Query("select t from User t where t.UserName = :UserName and t.createTime = :createTime")
User findByUserName(@Param("UserName")String UserName,@Param("createTime") Date createTime);
}
//当然,在参数不多不容易错乱的情况下,我们还可以直写问号
public interface User extends JpaRepository<User, Long> {
@Query("select t from User t where t.UserName = ? and t.createTime = ?")
User findByUserName(String UserName, Date createTime);
}
//或者把表名写成动态配置的
public interface User extends JpaRepository<User, Long> {
@Query("select t from #{#entityName} t where t.UserName = ? and t.createTime = ?")
User findByUserName(String UserName, Date createTime);
}
多表查询
多表查询在spring data jpa中有两种实现方式,第一种是利用hibernate的级联查询来实现,第二种是创建一个结果集的接口来接收连表查询后的结果,建议用第二种方式。
如果查询的字段是例如user_name,那么抽象方法是String getUser_Name()这样的命名格式,而不是GetUserName()这样的驼峰命名,请注意
//首先需要定义一个结果集的接口类。
public interface HotelSummary {
City getCity();
String getName();
Double 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);