SpringData Jpa笔记
一、简介
Spring data JPA是Spring在ORM框架,以及JPA规范的基础上,封装的一套JPA应用框架,并提供了一整套的数据访问层解决方案。
Spring data JPA提供给用户的主要有以下几个接口:
Repository:
仅仅是一个标识,表明任何继承它的均为仓库接口类,方便Spring自动扫描识别
CrudRepository:
继承Repository,实现了一组CRUD相关的方法
PagingAndSortingRepository:
继承CrudRepository,实现了一组分页排序相关的方法
JpaRepository:
继承PagingAndSortingRepository,实现一组JPA规范相关的方法
JpaSpecificationExecutor:
比较特殊,不属于Repository体系,实现一组JPA Criteria查询相关的方法
这么说直接继承JpaRepository接口,不就拥有所有功能了吗?
规则
Jpa通过对方法名称命名,将其转化成sql语句,具体规则如下:
And | findByNameAndPwd | where name= ? and pwd =? |
---|---|---|
Or | findByNameOrSex | where name= ? or sex=? |
Is,Equal | findById, | findByIdEquals |
Between | findByIdBetween | where id between ? and ? |
LessThan | findByIdLessThan | where id < ? |
LessThanEqual | findByIdLessThanEquals | where id <= ? |
GreaterThan | findByIdGreaterThan | where id > ? |
GreaterThanEqual | findByIdGreaterThanEquals | where id > = ? |
After | findByIdAfter | where id > ? |
Before | findByIdBefore | where id < ? |
IsNull | findByNameIsNull | where name is null |
isNotNull,Not Null | findByNameNotNull | where name is not |
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(?) |
示例
实体类
@Component
@Entity //实体类注解
public class Student {
@Id //主键
@GeneratedValue//主键生成策略
private int s_id;
private String s_name;
private String S_sex;
..........其他略去
}
jpa接口
使用接口继承jpa提供的接口,以此拥有jpa提供的功能
public interface StuJpa extends JpaRepository<Student,Integer> {
//继承接口,泛型中是实体类类型和主键类型
}
服务类
在服务类中调用jpa方法:
@Service
public class StuService {
@Autowired
StuJpa stuJpa;
public List<Student> getStus(){
System.out.println("----------调用jpa");
List<Student> all = stuJpa.findAll();
return all;
}
}
二、详细方法
查看一下主要的三个 Repository中的方法:
@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);
}
@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
Iterable<T> findAll(Sort var1);
Page<T> findAll(Pageable var1);
}
@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {
<S extends T> S save(S var1);
<S extends T> Iterable<S> saveAll(Iterable<S> var1);
Optional<T> findById(ID var1);
boolean existsById(ID var1);
Iterable<T> findAll();
Iterable<T> findAllById(Iterable<ID> var1);
long count();
void deleteById(ID var1);
void delete(T var1);
void deleteAll(Iterable<? extends T> var1);
void deleteAll();
}
分页查询、插入示例
提供的接口也有分页、排序的功能。
@Transactional注解在某些操作中需要添加,如删除、更新等。
@Service
@Transactional
public class StuService {
@Autowired
StuJpa stuJpa;
//分页
public void page(Integer o,Integer l) throws Exception{
//Sort sort = new Sort(Sort.Direction.DESC, "createTime");
Pageable page = PageRequest.of(o, l);
Page<Student> all = stuJpa.findAll(page);
System.out.println("TotalElement: "+all.getTotalElements());
System.out.println("TotalPages: "+all.getTotalPages());
System.out.println("NumberOfElements: "+all.getNumberOfElements());
System.out.println("Size: "+all.getSize());
System.out.println("Content: "+all.getContent());
all.forEach(System.out::println);
}
//保存
public void saveStu(Student student){
stuJpa.save(student);
}
}
对应的sql语句如下:
select * from ( select row_.*, rownum rownum_ from ( select student0_.s_id as s_id1_2_, student0_.s_sex as s_sex2_2_, student0_.s_name as s_name3_2_ from student student0_ ) row_ where rownum <= ?) where rownum_ > ?
三、注解
@GeneratedValue注解
主键生成策略:
TABLE: 使用一个特定的数据库表格来保存主键
SEQUENCE: 根据底层数据库的序列来生成主键,条件是数据库支持序列。这个值要与generator一起使用,generator 指定生成主键使用的生成器(可能是orcale中自己编写的序列)
IDENTITY: 主键由数据库自动生成(主要是支持自动增长的数据库,如mysql)
AUTO: 主键由程序控制,也是GenerationType的默认值
@Query注解
sql查询:在某些复杂查询中,方法命名无能为力时,使用注解进行sql语句的编写。
Query注解使用jpql语句,jpql语句是sql的变种,查询关键字都是一样的。
唯一的区别是:JPQL是面向对象的
JPA的查询语言,类似于sql
1.里面不能出现表名,列名,只能出现java的类名,属性名,区分大小写
2.出现的sql关键字是一样的意思,不区分大小写
3.不能写select * 要写select 别名
Query具体使用示例:
public interface StuJpa extends JpaRepository<Student, Integer> {
/**
* 命名参数
* 描述:推荐使用这种方法,可以不用管参数的位置
*/
@Query("select u from Student u where u.s_name = :name")
User findStudentByName(@Param("name") String name);
/**
* 索引参数
* 描述:使用?占位符
*/
@Query("select u from Student u where u.s_name = ?1")// 1表示第一个参数
User findStudentByName(String name);
/**
* 描述:可以通过@Modifying和@Query来实现更新
* 注意:Modifying queries的返回值只能为void或者是int/Integer
*/
@Modifying
@Query("update Student u set u.s_name = :name where u.s_id = :id")
int updateStudentById(@Param("name") String name, @Param("id") int id);
}