开篇广告
自己开发的淘宝领券网站:q.hayye.cn(手机打开)
要说特色,应该没有,硬要说的话就是没广告、没推送,简单好用。
前端开源地址:https://gitee.com/hayye/tbq
后端不开源……
欢迎大家加群讨论技术,不定时也会有淘宝神券发放!
正文开始
1. CrudRepository
仅提供一些相对简单的增删改查方法。
源码:
@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {
<S extends T> S save(S entity);
<S extends T> Iterable<S> saveAll(Iterable<S> entities);
Optional<T> findById(ID id);
boolean existsById(ID id);
Iterable<T> findAll();
Iterable<T> findAllById(Iterable<ID> ids);
long count();
void deleteById(ID id);
void delete(T entity);
void deleteAll(Iterable<? extends T> entities);
void deleteAll();
}
2. PagingAndSortingRepository
继承了CrudRepository,除了基本的增删改查外,还提供了排序和分页的方法。
源码:
@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
Iterable<T> findAll(Sort sort);
Page<T> findAll(Pageable pageable);
}
简单介绍用法:接口继承之后,直接使用如下方法即可完成调用。
需要注意的是,页码要从0开始…
Sort sort = new Sort(Sort.Direction.DESC,"id");
Page<Book> page = bookRepository.findAll(PageRequest.of(0,2,sort));
3. JpaRepository
前面两个接口是SpringData中比较底层的接口,兼容NoSQL,从JpaRepository开始,则对关系型数据库进行了优化,批量操作、手动刷新数据库、返回List等。
源码:
@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
List<T> findAll();
List<T> findAll(Sort sort);
List<T> findAllById(Iterable<ID> ids);
<S extends T> List<S> saveAll(Iterable<S> entities);
void flush();
<S extends T> S saveAndFlush(S entity);
void deleteInBatch(Iterable<T> entities);
void deleteAllInBatch();
T getOne(ID id);
<S extends T> List<S> findAll(Example<S> example);
<S extends T> List<S> findAll(Example<S> example, Sort sort);
}
4. SimpleJpaRepository
JpaRepository的实现类,主要通过Hibernate的EntityManager实现。
部分源码:
@Repository
@Transactional(readOnly = true)
public class SimpleJpaRepository<T, ID> implements JpaRepository<T, ID>, JpaSpecificationExecutor<T> {
private final JpaEntityInformation<T, ?> entityInformation;
private final EntityManager em;
private final PersistenceProvider provider;
//...
@Transactional
public void delete(T entity) {
Assert.notNull(entity, "The entity must not be null!");
em.remove(em.contains(entity) ? entity : em.merge(entity));
}
@Transactional
public void flush() {
em.flush();
}
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
public Optional<T> findById(ID id) {
Assert.notNull(id, ID_MUST_NOT_BE_NULL);
Class<T> domainType = getDomainClass();
if (metadata == null) {
return Optional.ofNullable(em.find(domainType, id));
}
LockModeType type = metadata.getLockModeType();
Map<String, Object> hints = getQueryHints().withFetchGraphs(em).asMap();
return Optional.ofNullable(type == null ? em.find(domainType, id, hints) : em.find(domainType, id, type, hints));
}
//...
}
具体继承哪一个接口还是根据实际业务决定的。
附:Demo源码 https://github.com/hayye/JPADemo