扯蛋部分

spring data jpa中官方提供有类似JpaSpecificationExecutorPagingAndSortingRepositoryCrudRepository等之类的一些基础接口,但很多时候无法满足一些需求,需自己扩展一些接口。以一个批量删除为例子写一个BaseRepository,官方虽有提供void delete(Iterable<? extends T> entities);这样的接口,但是看他的实现:

1
2
3
4
5
6
7
@Transactional
public void delete(Iterable<? extends T> entities) {
Assert.notNull(entities, "The given Iterable of entities not be null!");
for (T entity : entities) {
delete(entity);
}
}

实际也就是遍历entities来一个个删除,我们需要进行大量数据删除的时候,这样的模式明显不如where id in(xxx1,xxx2)或者where id = 'xxx1' or id = 'xxx2'

代码部分

BaseRepository.java 接口

1
2
3
4
5
6
7
8
9
10
@NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T> {

Integer deleteIds(Collection<ID> ids);
}


BaseCustomRepository.java 接口的实现,直接调用jpa的EntityManager来完成你需要的一些功能,entityInformation里面提供了一些此次查询的类的一些信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@NoRepositoryBean
public class BaseCustomRepository<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements BaseRepository<T, ID> {
private final EntityManager em;

private JpaEntityInformation<T, ?> entityInformation;


public BaseCustomRepository(JpaEntityInformation<T, ?> entityInformation, EntityManager em) {
super(entityInformation, em);
this.em = em;
this.entityInformation = entityInformation;
}

@SuppressWarnings("unchecked")
@Transactional(readOnly = false)
@Override
public Integer deleteIds(Collection<ID> ids) {
Assert.notNull(ids);
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaDelete<T> delete = cb.createCriteriaDelete(getDomainClass());
delete.where(delete.from(getDomainClass()).get("id").in(ids));
return em.createQuery(delete).executeUpdate();
}
}


BaseRepositoryFactory.java 接口工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class BaseRepositoryFactory extends JpaRepositoryFactory {

public BaseRepositoryFactory(EntityManager entityManager) {
super(entityManager);
}


@Override
@SuppressWarnings({"unchecked", "rawtypes"})
protected <T, ID extends Serializable> SimpleJpaRepository<?, ?> getTargetRepository(RepositoryMetadata metadata, EntityManager entityManager) {
JpaEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainType());
return new BaseCustomRepository(entityInformation, entityManager);
}


@Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
return BaseCustomRepository.class;
}
}


BaseRepositoryFactoryBean.java 接口工厂bean

1
2
3
4
5
6
7
8
9
10
11
12
public class BaseRepositoryFactoryBean<T extends JpaRepository<Object, Serializable>> extends JpaRepositoryFactoryBean<T, Object, Serializable> {

@Override
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
return new BaseRepositoryFactory(entityManager);
}
}

配置部分

在spring的jpa配置中加入:factory-class="xxxx.repository.BaseRepositoryFactoryBean"

1
2
3
4
<jpa:repositories base-package="com.chinamedcom"
factory-class="xxxx.repository.BaseRepositoryFactoryBean"
transaction-manager-ref="transactionManager"
entity-manager-factory-ref="entityManagerFactory"/>

参考资料