SpringDataJPA 是springdata 项目下的一个模块。提供了一套基于JPA 标准操作数据库的简化方案。底层默认的是依赖 HibernateJPA 来实现的。
SpringDataJPA 的技术特点:我们只需要定义接口并集成 Spring DataJPA 中所提供的接 口就可以了。不需要编写接口实现类
spring-data-jpa接口继承关系
Repository 接口
Repository 接口是 SpringDataJPA 中为我我们提供的所有接口中的顶层接口
Repository 提供了两种查询方式的支持
1).基于方法名称命名规则查询
2).基于@Query 注解查询
1.方法名称命名规则查询
规则:findBy(关键字)+属性名称(属性名称的首字母大写)+查询条件(首字母大写)
关键字 | 方法命名 | sql where字句 |
And | findByNameAndPwd | where name= ? and pwd =? |
Or | findByNameOrSex | where name= ? or sex=? |
Is,Equal | findById,findByIdEquals | where id= ? |
Between | findByIdBetween | where id between ? and ? |
LessThan | findByIdLessThan | where id < ? |
LessThanEqual | findByIdLessThanEqual | where id <=? |
GreaterThan | findByIdGreaterThan | where id > ? |
GreaterThanEqual | findByIdGreaterThanEqual | 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(Collect ion<?> c) | where id not in (?) |
True | findByAaaTue | where aaa = true |
False | findByAaaFalse | where aaa = false |
IgnoreCase | findByNameIgnoreCase | where UPPER(name)=UPPER(?) |
我们在dao接口中可以这样玩 (注意 dao继承 extends JpaRepository<Book,Integer> book是具体的查询类型)
JpaRepository 接口是我们开发时使用的最多的接口。其特点是可以帮助我们将其他接口 的方法的返回值做适配处理。可以使得我们在开发时更方便的使用这些方法
Book实体类
/**
* 类与表建立映射关系
* book 实体
* @author xz
*/
@Entity
@Table(name="books") //对应的哪个表
public class Book implements Serializable {
@Id //指定为id
@GeneratedValue(strategy=GenerationType.IDENTITY) //主键策略
@Column(name="bid") //字段名
private int bid;
@Column(name="name")
private String name;
@Column(name="credate")
private Date credate;
@Column(name="note")
private String note;
public Book() {
}
public Book(int bid, String name, Date credate, String note) {
this.bid = bid;
this.name = name;
this.credate = credate;
this.note = note;
}
public int getBid() {
return bid;
}
public void setBid(int bid) {
this.bid = bid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCredate() {
return credate;
}
public void setCredate(Date credate) {
this.credate = credate;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
@Override
public String toString() {
return "Book{" +
"bid=" + bid +
", name='" + name + '\'' +
", credate=" + credate +
", note='" + note + '\'' +
'}';
}
}
dao我们这样写
public interface BookDao1 extends JpaRepository<Book,Integer> {
//根据id查询 where bid >= bid
List<Book> findByBidGreaterThanEqual(Integer bid);
//根据id查询 where bid > bid
List<Book> findByBidLessThanEqual(Integer bid);
//根据名字模糊查询 where name like "%name"
List<Book> findByNoteStartingWith(String name);
//根据名字模糊查询 where name like "name%"
List<Book> findByNoteEndingWith(String name);
}
2.基于@Query 注解的查询
通过 JPQL 语句查询
JPQL:通过 Hibernate 的 HQL 演变过来的。他和 HQL 语法及其相似
在dao中可以这样实现
@Query(value = "from Book where name like ?")
Book queryBookByNameUseJPQL(String name);
@Query(value="select * from books where name like ?",nativeQuery = true)
List<Book> queryBooksByNameUseJPQL(String name);
需要注意的是,nativeQuery默认的是 false.表示不开启 sql 查询。是否对 value 中的语句做转义
还能通过 @Query 做update操作 使用@Modifying表示 当前语句是一个更新语句
@Query(value="update Book set name =? where bid = ?")
@Modifying
void updateBook(String name,Integer bid);
CrudRepository 接口
/**
* 继承CrudRepository接口
*/
public interface BookDao extends CrudRepository<Book,Integer> {
}
测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class SsmbootApplicationTests {
@Resource
private BookDao bookDao;
/**
* 插入数据
*/
@Test
public void test1() {
Book book = new Book();
book.setName("java 入门到精通");
book.setCredate(new Date());
book.setNote("java指导大全");
bookDao.save(book);
}
/**
* 批量添加
*/
@Test
public void test2(){
Book book = new Book();
book.setName("oracle 入门到精通");
book.setCredate(new Date());
book.setNote("oracle 指导大全");
Book book2 = new Book();
book2.setName("spring 入门到精通");
book2.setCredate(new Date());
book2.setNote("spring 指导大全");
List<Book> list = new ArrayList<>();
list.add(book);
list.add(book2);
bookDao.save(list);
}
/**
* 根据id查找
*/
@Test
public void test3(){
Book booke = bookDao.findOne(3);
System.out.println(booke);
}
/**
* 查询全部
*/
@Test
public void test4(){
System.out.println(bookDao.findAll());
}
/**
* 删除数据
*/
@Test
public void test5(){
bookDao.delete(9);
}
/**
* 更改数据
*/
@Test
public void test6(){
Book book = bookDao.findOne(10);
book.setCredate(new Date());
//bookDao.save(book);
}
}
PagingAndSortingRepository 接口
1.分页处理
dao接口
/**
* 支持分页 和 排序操作
* Spring Data JPA操作
*/
public interface BookDao extends PagingAndSortingRepository<Book,Integer> {
}
测试类
@Test
public void test1(){
int page = 2; //page:当前页的索引。注意索引都是从 0 开始的。
int size = 3;// size:每页显示 3 条数据
Pageable pageable = new PageRequest(page,size);
Page<Book> pages = bookDao.findAll(pageable);
System.out.println( "总条数:"+pages.getTotalElements());//总条数
System.out.println("总页数:"+pages.getTotalPages());//总页数
List<Book> list = pages.getContent();
for (Book b: list) {
System.out.println(b);
}
}
2.排序处理
测试类
单列排序
/**
* 单列排序
*/
@Test
public void test2(){
// Sort:该对象封装了排序规则以及指定的排序字段(对象的属性来表示)
// direction:排序规则 asc 升序 desc 降序
// properties:指定做排序的属性
Sort sort = new Sort(Sort.Direction.DESC,"bid");
List<Book> list=(List<Book>)bookDao.findAll(sort);
for (Book book:list) {
System.out.println(book);
}
}
多列排序
/**
* 多列排序
*/
@Test
public void test3(){
// Sort:该对象封装了排序规则以及指定的排序字段(对象的属性来表示)
// direction:排序规则 asc 升序 desc 降序
// properties:指定做排序的属性
Sort.Order order = new Sort.Order(Sort.Direction.DESC,"name");
Sort.Order order1 = new Sort.Order(Sort.Direction.DESC,"bid");
Sort sort = new Sort(order,order1);
List<Book> list=(List<Book>)bookDao.findAll(sort);
for (Book book:list) {
System.out.println(book);
}
}
JpaSpecificationExecutor 接口
完成多条件查询,并且支持分页与排序
需要注意的是这个接口不能单独使用,需要配合着 jpa 中的 其他接口一起使用
dao类
/**
* 完成多条件查询,并且支持分页与排序
* Spring Data JPA操作
*/
public interface BookDao extends JpaRepository<Book,Integer>, JpaSpecificationExecutor<Book> {
}
测试代码
单条件查询
/**
* 根据书名模糊查询
*/
@Test
public void test1(){
Specification<Book> spec = new Specification<Book>() {
/**
* @param Root<Users> root:根对象。封装了查询条件的对象
* @param CriteriaQuery<?> query:定义了一个基本的查询.一般不使用
* @param CriteriaBuilder cb:创建一个查询条件
* @return Predicate:定义了查询条件 * @param Root<Book> root:根对象。封装了查询条件的对象
* */
@Override
public Predicate toPredicate(Root<Book> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Predicate pre = cb.like(root.get("name"),"%入门到精通%");
return pre;
}
};
List<Book> list = bookDao.findAll(spec);
for (Book book:list) {
System.out.println(book);
}
}
多条件查询
/**
* 使用编号或书名查询
*/
@Test
public void test2(){
Specification spec = new Specification() {
/**
* @param Root<Users> root:根对象。封装了查询条件的对象
* @param CriteriaQuery<?> query:定义了一个基本的查询.一般不使用
* @param CriteriaBuilder cb:创建一个查询条件
* @return Predicate:定义了查询条件 * @param Root<Book> root:根对象。封装了查询条件的对象
* */
@Override
public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
return cb.or(cb.like(root.get("name"),"%入门到精通%"),cb.equal(root.get("bid"),"8"));
}
};
List<Book> list = bookDao.findAll(spec);
for (Book book:list) {
System.out.println(book);
}
}
模糊查询,分页,并排序
/**
* 根据书名模糊查询,并且分页 按照 bid 进行排序
*/
@Test
public void test3() {
//排序定义
Sort sort = new Sort(Sort.Direction.DESC, "bid");
//分页定义 并且给定排序规则
Pageable pageable = new PageRequest(2, 2, sort);
//查询条件
Specification spec = new Specification() {
/**
* @param Root<Users> root:根对象。封装了查询条件的对象
* @param CriteriaQuery<?> query:定义了一个基本的查询.一般不使用
* @param CriteriaBuilder cb:创建一个查询条件
* @return Predicate:定义了查询条件 * @param Root<Book> root:根对象。封装了查询条件的对象
* */
@Override
public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
return criteriaBuilder.like(root.get("note"), "%呀%");
}
};
//获取查询结果封装到page
Page<Book> page = bookDao.findAll(spec, pageable);
System.out.println("总条数:" + page.getTotalElements());
System.out.println("总页数:" + page.getTotalPages());
List<Book> list = page.getContent();
for (Book book : list) {
System.out.println(book);
}
}