上一篇介绍了Mybatis的配置和基本用法《SpringBoot入门建站全系列(五)使用Spring-data-jpa操作数据库CRUD》
这一篇在此基础上进阶使用Spring-data-jpa。
所以,这里就不说怎么怎么配置了,直接写Spring-data-jpa的写法,至于调用,dao层的自己用service调就可以了,需要service配合的会写出来部分逻辑。
Spring-data-jpa支持继承接口中的所有方法直接调用,同时也支持以下几种简便使用方法:
findBy的Spring-data-jpa官方示例:
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 | findByFirstname,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<Age> ages) | … where x.age in ?1 |
NotIn | findByAgeNotIn(Collection<Age> ages) | … 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) |
JPQL写法:
public interface UserRepository extends JpaRepository<User, Long> {
@Query("select u from User u where u.emailAddress = ?1")
User findByEmailAddress(String emailAddress);
@Query("select u from User u where u.firstname like %?1")
List<User> findByFirstnameEndsWith(String firstname);
@Modifying
@Query("update User u set u.firstname = ?1 where u.lastname = ?2")
int setFixedFirstnameFor(String firstname, String lastname);
@Modifying
@Query("delete from User u where user.role.id = ?1")
void deleteInBulkByRoleId(long roleId);
}
原生SQL写法:
无它,就是SQL语句。需要注意的是,返回的实体要是表对应实体。
public interface UserRepository extends JpaRepository<User, Long> {
@Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?1", nativeQuery = true)
User findByEmailAddress(String emailAddress);
}
可以使用Sort传参。
public interface UserRepository extends JpaRepository<User, Long> {
@Query("select u from User u where u.lastname like ?1%")
List<User> findByAndSort(String lastname, Sort sort);
}
也可以通过方法名称来进行排序。
public interface UserRepository extends JpaRepository<User, Long> {
@Query("select u from User u where u.lastname like ?1%")
List<User> findByAndSort(String lastname, Sort sort);
List<User> findByLastnameOrderByFirstnameAsc(String lastname);
List<User> findByLastnameOrderByFirstnameDesc(String lastname);
}
通过传递Pageable参数进行分页,切记,分页页码是从0开始的。
Pageable也可以进行排序。
public interface UserRepository extends JpaRepository<User, Long> {
Page<User> findByLastname(String lastname, Pageable pageable);
}
Spring-data-jpa已经很方便了,但是有时候我们有的参数为空,这时我们不想让这些参数作为条件查询,笨办法就是去写n个方法,当然也有好办法了,那就是JpaSpecificationExecutor:
@Repository
public interface RdTaskDao extends JpaRepository<RdTask, Integer>, JpaSpecificationExecutor<RdTask> {
}
使用以下sql组装Specification,然后调用findAll进行查询。
Specification<RdTask> querySpecifi = new Specification<RdTask>() {
private static final long serialVersionUID = 1L;
@Override
public Predicate toPredicate(Root<RdTask> root, CriteriaQuery<?> criteriaQuery,
CriteriaBuilder criteriaBuilder) {
List<Predicate> predicates = new ArrayList<>();
//未删除标识
predicates.add(criteriaBuilder.equal(root.get("deleteFlag"), 0));
if (!StringUtils.isEmpty(rdTaskListReq.getCreator())) {
predicates.add(criteriaBuilder.equal(root.get("creator"), rdTaskListReq.getCreator()));
}
if (!StringUtils.isEmpty(rdTaskListReq.getDesignater())) {
predicates.add(criteriaBuilder.equal(root.get("designater"), rdTaskListReq.getDesignater()));
}
if (null != rdTaskListReq.getType()) {
predicates.add(criteriaBuilder.equal(root.get("type"), rdTaskListReq.getType()));
}
if (null != rdTaskListReq.getStatus()) {
if (rdTaskListReq.getStatus().equals("doing")) {
predicates.add(criteriaBuilder.equal(root.get("status"), "doing"));
} else if (rdTaskListReq.getStatus().equals("closed")) {
predicates.add(criteriaBuilder.equal(root.get("status"), "closed"));
}
}
return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
}
};
Pageable pageable = PageRequest.of(rdTaskListReq.getPage(), rdTaskListReq.getPageSize(), Direction.DESC, "createTime");
Page<RdTask> page = rdTaskDao.findAll(querySpecifi, pageable);
详细完整代码,可以访问品茗IT-博客《SpringBoot入门建站全系列(六)Spring-data-jpa进阶使用》,也可以在Spring组件化构建中选择查看,并下载。
@Transactional注解开启事务。可以注解在类上,也可以注解在方法上。Spring对更新删除操作强制要求加上@Transactional注解。
@Transactional使用没多少注意的事情,除非是要求特别严格的系统,那就别看乱七八糟的博客,去看官方文档,博客只能带你入门,知道有哪些东西。
@Transactional一般配置下异常的捕获rollbackFor属性,默认情况下只捕获RuntimeException,可以将注解在方法上的@Transactional改为:
@Transactional(rollbackFor=Exception.class)
这样就会捕获所有异常。
mysql的MyISAM引擎不支持事务,切记。
喜欢这篇文章么,喜欢就加入我们一起讨论SpringBoot技术吧!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。