Spring Data JPA中CrudRepository常用方法及其底层源码解读
使用Spring Data JPA,Dao层对象实际上是SimpleJpaRepository的代理对象,我们可以去这个类里看各个方法是如何实现的。
1.save(S entity)
@Transactional
public <S extends T> S save(S entity) {
if(this.entityInformation.isNew(entity)) {
this.em.persist(entity);
return entity;
} else {
return this.em.merge(entity);
}
}
save()方法包含插入和更新两个功能,根据传入实体entity的主键ID是否为空,来判断执行哪个操作,这个在之前的博客中有说明。
在这里需要关注下该方法上的事务注解@Transactional。我们在调用完save()方法后,从日志里可以看出有commit,这说明save方法会自动完成事务提交,而不依赖于所在方法的事务,其原因就是save方法本身就是一个事务。
2.save(Iterable entities)
Iterable其实就是我们常用的集合List,List继承了Iterable,如下所示
public interface List<E> extends Collection<E> {}
public interface Collection<E> extends Iterable<E> {)
@Transactional
public <S extends T> List<S> save(Iterable<S> entities) {
List<S> result = new ArrayList();
if(entities == null) {
return result;
} else {
Iterator var3 = entities.iterator();
while(var3.hasNext()) {
S entity = var3.next();
result.add(this.save(entity));
}
return result;
}
}
使用save方法保存集合,save方法会先判断该集合是否为空,不为空,就迭代获取每一个实体,再对实体进行保存或者更新操作,同样该方法是自带事务的。
save(S entity)和save(Iterable entities)方法都有返回值,返回的都是被操作的实体对象或者实体对象的集合。
3.findOne(ID id)
public T findOne(ID id) {
Assert.notNull(id, "The given id must not be null!");
Class<T> domainType = this.getDomainClass();
if(this.metadata == null) {
return this.em.find(domainType, id);
} else {
LockModeType type = this.metadata.getLockModeType();
Map<String, Object> hints = this.metadata.getQueryHints();
return type == null?this.em.find(domainType, id, hints):this.em.find(domainType, id, type, hints);
}
}
public static void notNull(Object object, String message) {
if(object == null) {
throw new IllegalArgumentException(message);
}
}
findOne根据主键ID查询,首先会判断ID是否为空,为空,则会抛出IllegalArgumentException非法参数异常,接着获取当前实体类对象,通过反射去查询数据。
4.delete(ID id)
@Transactional
public void delete(ID id) {
Assert.notNull(id, "The given id must not be null!");
T entity = this.findOne(id);
if(entity == null) {
throw new EmptyResultDataAccessException(String.format("No %s entity with id %s exists!", new Object[]{this.entityInformation.getJavaType(), id}), 1);
} else {
this.delete(entity);
}
}
按主键ID进行删除,首先判断ID是否为空,接着调用findOne去根据ID查询实体,若返回null,则抛出对应实体不存在的异常,若实体存在,则进行删除。该方法被@Transactional修饰,会自动完成事务提交。
5.delete(Iterable extends T> entities)
@Transactional
public void delete(Iterable<? extends T> entities) {
Assert.notNull(entities, "The given Iterable of entities not be null!");
Iterator var2 = entities.iterator();
while(var2.hasNext()) {
T entity = var2.next();
this.delete(entity);
}
}
删除多个实体,首先判断集合是否为空,不为空则遍历集合进行删除,同样会自动完成事务提交。