前言:用Spring全家桶,大家常用的应该是jpa,上次我看过一次调查统计,歪果人使用持久化框架jpa比较多,目前国内已知互联网公司mybatis会比较多,可能大家都觉得mybatis的查询效率更高。 SpringData JPA只是SpringData中的一个子模块,JPA是一套标准接口,而Hibernate是JPA的实现,SpringData JPA 底层默认实现是使用Hibernate,SpringDataJPA 的首个接口就是Repository,它是一个标记接口。只要我们的接口实现这个接口,那么我们就相当于在使用SpringDataJPA了。
Spring Data存储库抽象中的中央接口是Repository
。它将域类以及域类的ID类型作为类型参数进行管理。此接口主要用作标记接口,用于捕获要使用的类型,并帮助您发现扩展此接口的接口。该CrudRepository
规定对于正在管理的实体类复杂的CRUD功能。
public interface CrudRepository<T, ID extends Serializable>
extends Repository<T, ID> {
//保存给定的实体
<S extends T> S save(S entity);
//返回指定ID的实体
Optional<T> findById(ID primaryKey);
//返回所有的实体
Iterable<T> findAll();
//返回实体数量
long count();
//删除
void delete(T entity);
//查询是否存在某一个数据
boolean existsById(ID primaryKey);
// … more functionality omitted.
}
最重要的是CrudRepository
,有一个PagingAndSortingRepository
抽象添加了额外的方法来简化对实体的分页访问
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
//排序
Iterable<T> findAll(Sort sort);
//分页加查询
Page<T> findAll(Pageable pageable);
}
一般我们自己的jpa接口会继承 jpa,因为jpa既继承了page分页和 query查询的接口。
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);
}
jpa常用的关键词
关键词
样品
JPQL代码段
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
(附加参数绑定%
)
EndingWith
findByFirstnameEndingWith
… where x.firstname like ?1
(与前置绑定的参数%
)
Containing
findByFirstnameContaining
… where x.firstname like ?1
(包含参数绑定%
)
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)
我们自定义hql语句
public interface UserRepository extends JpaRepository<User, Long> {
@Query("select u from User u where u.emailAddress = ?1")
User findByEmailAddress(String emailAddress);
}
我们自定义的原生sql语句
public interface UserRepository extends JpaRepository<User, Long> {
@Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?1", nativeQuery = true)
User findByEmailAddress(String emailAddress);
}
占位符 ?用下标来
占位符 :name 用参数名来占位 用@Param(“name”) 来替换
增删改语句 必须用@Modifying注解
@Modifying
@Query("update User u set u.firstname = ?1 where u.lastname = ?2")
int setFixedFirstnameFor(String firstname, String lastname);
CrudRepository里有个findById该方法的返回值是一个Optional
/**
* Retrieves an entity by its id.
*
* @param id must not be {@literal null}.
* @return the entity with the given id or {@literal Optional#empty()} if none found
* @throws IllegalArgumentException if {@code id} is {@literal null}.
*/
Optional<T> findById(ID id);
JpaRepository里有个getOne()方法返回的是实体对象的代理对象(a reference)
如果不开启事务 会抛出org.hibernate.LazyInitializationException: could not initialize proxy - no Session的异常
/**
* Returns a reference to the entity with the given identifier. Depending on how the JPA persistence provider is
* implemented this is very likely to always return an instance and throw an
* {@link javax.persistence.EntityNotFoundException} on first access. Some of them will reject invalid identifiers
* immediately.
*
* @param id must not be {@literal null}.
* @return a reference to the entity with the given identifier.
* @see EntityManager#getReference(Class, Object) for details on when an exception is thrown.
*/
T getOne(ID id);
QueryByExampleExecutor里有个findOne 查询不到数据会 throw new NoSuchElementException("No value present");
/**
* Returns a single entity matching the given {@link Example} or {@literal null} if none was found.
*
* @param example must not be {@literal null}.
* @return a single entity matching the given {@link Example} or {@link Optional#empty()} if none was found.
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if the Example yields more than one result.
*/
<S extends T> Optional<S> findOne(Example<S> example);
持续更新中。。。。