(五)spring-boot教程,开发个人博客:创建博客dao(spring-boot-data-jpa)一个相当牛逼的东西

avatar

实体类创建好了,这一节来说一下spring-boot-starter-data-jpa这个相当牛逼的东西

它的原理我就不说了,我自己也没弄太明白,目前只是会用,在这把用法告诉大家

spring-boot-starter-data-jpa 底层还是 hibernate 通过约定方法名的定义来实现功能,举个例子,用户表里有 username 字段,想根据 username 来查询一个用户,就可以定义一个接口,然后在service里直接调用即可

User findByUsername(String username);

它就是这么简单,下面来说一下它的规则

继承 JpaRepository

spring-boot-starter-data-jpa 内置的几个接口名称都有 Repository ,下面就用repository来代替,定义一个repository,首先要继承一下 JpaRepository 它有两个范型 <T, ID> ,T是实体类,ID是实体类的ID类型

UserRepository.java

import com.example.demo.model.User;

import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Integer> {

}

上面例子中,就是一个 repository 的定义写法 注意 repository是接口,不是类

至于为什么要继承 JpaRepository 而不是其它的 repository ,因为 JpaRepository 同时继承了其它所有的 repository, 所以只需要继承 JpaRepository 方法就够用了,下面来看看 JpaRepository 都继承了哪些接口

JpaRepository
  |--PagingAndSortingRepository
      |--CrudRepository
          |--Repository
  • Repository: 最基础的 repository
  • CrudRepository: 带有CRUD的repository
  • PagingAndSortingRepository: 带有CRUD和分页的repository

所以只需要继承 JpaRepository 就可以了

自定义方法

在网上找了一篇比较全的规则表

关键字 方法命名 sql where字句
And findByNameAndPwd where name= ? and pwd =?
Or findByNameOrSex where name= ? or sex=?
Is,Equals findById,findByIdEquals where id= ?
Between findByIdBetween where id between ? and ?
LessThan findByIdLessThan where id < ?
LessThanEquals findByIdLessThanEquals where id <= ?
GreaterThan findByIdGreaterThan where id > ?
GreaterThanEquals findByIdGreaterThanEquals where id > = ?
After findByIdAfter where id > ?
Before findByIdBefore where id < ?
IsNull findByNameIsNull where name is null
isNotNull,NotNull findByNameNotNull where name is not null
Like findByNameLike where name like ?
NotLike findByNameNotLike where name not like ?
StartingWith findByNameStartingWith where name like '?%'
EndingWith findByNameEndingWith where name like '%?'
Containing findByNameContaining where name like '%?%'
OrderBy findByIdOrderByXDesc where id=? order by x desc
Not findByNameNot where name <> ?
In findByIdIn(Collection<?> c) where id in (?)
NotIn findByIdNotIn(Collection<?> c) where id not in (?)
True findByAaaTue where aaa = true
False findByAaaFalse where aaa = false
IgnoreCase findByNameIgnoreCase where UPPER(name)=UPPER(?)

举例说明

public interface UserRepository extends JpaRepository<User, Integer> {

  // 根据用户名和密码查询用户
  User findByUsernameAndPassword(String username, String password);

}

复杂查询

@Query

通过定义接口的方式可以实现一些简单的查询,当然如果要涉及到联查,可以通过hibernate里的关联来查,但是如果没有做关联,还可以通过写 HQL 或者 SQL 来查

通过注解 @Query 来定义方法

public interface UserRepository extends JpaRepository<User, Integer> {

  User findByUsernameAndPassword(String username, String password);

  @Query(nativeQuery = true, value = "select * from user where username = ?1")
  User findByUsername1(String username);

  @Query(value = "from User where username = ?1")
  User findByUsername1(String username);
}
  • nativeQuery : 表明是原生sql还是hibernate的hql,默认是false,也就是用hql来查询,如果是hql来查询的话,就要用hql的语法
  • ?1 : 表示方法的第几个参数,它会自动填充,从1开始,如果还有参数,可以在后面继续写上 ?2 它会自动去找方法里的第二个参数

Example

除了写sql/hql来查询外,还可以用Example这个类来查询,比如现在有个需求,要查询博客的列表,条件是博客标题和用户,标题跟用户有可能为空,这时候定义方法就不好定了,可以用Example轻松解决

public List<Post> findPostByTitleAndUser(String title, Integer userId) {
  Post post = new Post();
  if (userId != null) {
    post.setUserId(userId);
  }
  if (!StringUtils.isEmpty(title)) {
    post.setTitle(title);
  }
  return postRepository.findAll(Example.of(post));
}

这时候就不怕用户有没有输入title和userId了,有它就加上这个条件,没有它就不加

但这里有个坑,用到Example的时候,它会自动过滤掉为null的字段,所以像int,boolean等这类有默认值的字段就要用它们的包装型 Integer, Boolean等

JpaSpecificationExecutor

这货可以说就是一个大boss了,基本上项目开发中会用到的联查,多条件查询它都能轻松解决,只不过如果要用联查,就要用hibernate里的关联类似 @ManyToOne

这里就不给例子了,写博客根本用不到这东西,如果你有兴趣,可以在下方评论或者发布问答

最后放一下博客的代码

UserRepository.java

public interface UserRepository extends JpaRepository<User, Integer> {

  User findByUsernameAndPassword(String username, String password);

}

CommentRepository.java

public interface CommentRepository extends JpaRepository<Comment, Integer> {

  List<Comment> findByPostId(Integer id);

}

PostRepository.java

public interface PostRepository extends JpaRepository<Post, Integer> {

}
目前还没有回答,快来帮帮TA吧!
添加一条评论 请尽量发布对他人有帮助的评论

登录后可发布评论

登录 | Github登录