Spring JPA 基础存储库
Spring JPA Base Repository
我已经创建了一个自定义存储库来覆盖持久性方法,并尝试按照 spring docs 中的描述将其连接起来。我没有收到任何错误,所有实体和存储库都在启动时找到,当我调用 repo.saveAll(entities) 时,持久性正常工作。但是,我的自定义代码从未被调用。我在我的代码中添加了日志语句甚至抛出RuntimeExceptions,只是为了看看它是否正在执行,但它肯定被忽略了。我错过了哪一步?
@Configuration
@Profile("test")
@EnableJpaRepositories(repositoryBaseClass = SetClientInfoRepositoryImpl.class,
basePackages = {"gov.penndot.hwy.apras.common.repository" },
entityManagerFactoryRef = "serviceEntityManagerFactory",
transactionManagerRef = "serviceTransactionManager")
public class TestDatabaseConfig {
@Bean(name = "serviceDataSource")
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:mem:db;DB_CLOSE_DELAY=-1");
dataSource.setUsername("sa");
dataSource.setPassword("sa");
return dataSource;
}
@Bean
public EntityManagerFactoryBuilder entityManagerFactoryBuilder() {
return new EntityManagerFactoryBuilder(new HibernateJpaVendorAdapter(), new HashMap<String, Object>(), null);
}
@Bean(name = "serviceEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean serviceEntityManagerFactory(EntityManagerFactoryBuilder builder,
@Qualifier("serviceDataSource") DataSource dataSource) {
return builder
.dataSource(dataSource)
.packages("stuff")
.persistenceUnit("service")
.build();
}
@Bean(name = "serviceTransactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("serviceEntityManagerFactory") EntityManagerFactory serviceEntityManagerFactory) {
return new JpaTransactionManager(serviceEntityManagerFactory);
}
存储库:
@NoRepositoryBean
public class SetClientInfoRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> {
private static final Logger log = LoggerFactory.getLogger(SetClientInfoRepositoryImpl.class);
private final EntityManager em;
public SetClientInfoRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager) {
super(entityInformation, entityManager);
this.em = entityManager;
}
@Transactional
@Override
public <S extends T> S save(S entity) {
setClientInfo();
return super.save(entity);
}
@Transactional
@Override
public void deleteById(ID id) {
setClientInfo();
super.deleteById(id);
}
@Transactional
@Override
public void delete(T entity) {
setClientInfo();
super.delete(entity);
}
@Transactional
@Override
public void deleteAll(Iterable<? extends T> entities) {
setClientInfo();
super.deleteAll(entities);
}
@Transactional
@Override
public void deleteInBatch(Iterable<T> entities) {
setClientInfo();
super.deleteInBatch(entities);
}
@Transactional
@Override
public void deleteAll() {
setClientInfo();
super.deleteAll();
}
@Transactional
@Override
public void deleteAllInBatch() {
setClientInfo();
super.deleteAllInBatch();
}
@Transactional
@Override
public <S extends T> S saveAndFlush(S entity) {
setClientInfo();
return super.saveAndFlush(entity);
}
@Transactional
@Override
public <S extends T> List<S> saveAll(Iterable<S> entities) {
setClientInfo();
super.saveAll(entities);
throw new RuntimeException("foo");
}
private void setClientInfo() {
log.debug("Entering setClientInfo method");
[stuff]
}
}
好吧,这是一个相当绝望的想法,但值得一试...
创建自定义存储库界面:
public interface SetClientInfoRepository<T, ID> extends JpaRepository<T, ID> {
}
通过您的自定义基础存储库实现此存储库接口:
public class SetClientInfoRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements SetClientInfoRepository<T, ID> {
}
... 最后通过您的存储库接口而不是 JpaRepository
扩展此接口
这样 Spring 必须 从您的实现中创建存储库代理,因为没有其他 类 它可以使用。此外,如果由于任何原因它无法创建存储库,您将在启动期间获得更多信息异常。
使用自定义存储库接口本身并不是一件坏事,因为您总是很有可能希望稍后将一些常用的自定义方法添加到您的存储库中,然后它会派上用场。
我已经创建了一个自定义存储库来覆盖持久性方法,并尝试按照 spring docs 中的描述将其连接起来。我没有收到任何错误,所有实体和存储库都在启动时找到,当我调用 repo.saveAll(entities) 时,持久性正常工作。但是,我的自定义代码从未被调用。我在我的代码中添加了日志语句甚至抛出RuntimeExceptions,只是为了看看它是否正在执行,但它肯定被忽略了。我错过了哪一步?
@Configuration
@Profile("test")
@EnableJpaRepositories(repositoryBaseClass = SetClientInfoRepositoryImpl.class,
basePackages = {"gov.penndot.hwy.apras.common.repository" },
entityManagerFactoryRef = "serviceEntityManagerFactory",
transactionManagerRef = "serviceTransactionManager")
public class TestDatabaseConfig {
@Bean(name = "serviceDataSource")
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:mem:db;DB_CLOSE_DELAY=-1");
dataSource.setUsername("sa");
dataSource.setPassword("sa");
return dataSource;
}
@Bean
public EntityManagerFactoryBuilder entityManagerFactoryBuilder() {
return new EntityManagerFactoryBuilder(new HibernateJpaVendorAdapter(), new HashMap<String, Object>(), null);
}
@Bean(name = "serviceEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean serviceEntityManagerFactory(EntityManagerFactoryBuilder builder,
@Qualifier("serviceDataSource") DataSource dataSource) {
return builder
.dataSource(dataSource)
.packages("stuff")
.persistenceUnit("service")
.build();
}
@Bean(name = "serviceTransactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("serviceEntityManagerFactory") EntityManagerFactory serviceEntityManagerFactory) {
return new JpaTransactionManager(serviceEntityManagerFactory);
}
存储库:
@NoRepositoryBean
public class SetClientInfoRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> {
private static final Logger log = LoggerFactory.getLogger(SetClientInfoRepositoryImpl.class);
private final EntityManager em;
public SetClientInfoRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager) {
super(entityInformation, entityManager);
this.em = entityManager;
}
@Transactional
@Override
public <S extends T> S save(S entity) {
setClientInfo();
return super.save(entity);
}
@Transactional
@Override
public void deleteById(ID id) {
setClientInfo();
super.deleteById(id);
}
@Transactional
@Override
public void delete(T entity) {
setClientInfo();
super.delete(entity);
}
@Transactional
@Override
public void deleteAll(Iterable<? extends T> entities) {
setClientInfo();
super.deleteAll(entities);
}
@Transactional
@Override
public void deleteInBatch(Iterable<T> entities) {
setClientInfo();
super.deleteInBatch(entities);
}
@Transactional
@Override
public void deleteAll() {
setClientInfo();
super.deleteAll();
}
@Transactional
@Override
public void deleteAllInBatch() {
setClientInfo();
super.deleteAllInBatch();
}
@Transactional
@Override
public <S extends T> S saveAndFlush(S entity) {
setClientInfo();
return super.saveAndFlush(entity);
}
@Transactional
@Override
public <S extends T> List<S> saveAll(Iterable<S> entities) {
setClientInfo();
super.saveAll(entities);
throw new RuntimeException("foo");
}
private void setClientInfo() {
log.debug("Entering setClientInfo method");
[stuff]
}
}
好吧,这是一个相当绝望的想法,但值得一试...
创建自定义存储库界面:
public interface SetClientInfoRepository<T, ID> extends JpaRepository<T, ID> {
}
通过您的自定义基础存储库实现此存储库接口:
public class SetClientInfoRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements SetClientInfoRepository<T, ID> {
}
... 最后通过您的存储库接口而不是 JpaRepository
这样 Spring 必须 从您的实现中创建存储库代理,因为没有其他 类 它可以使用。此外,如果由于任何原因它无法创建存储库,您将在启动期间获得更多信息异常。
使用自定义存储库接口本身并不是一件坏事,因为您总是很有可能希望稍后将一些常用的自定义方法添加到您的存储库中,然后它会派上用场。