gpt4 book ai didi

java - Spring 的 @EntityListeners 在使用 @Postpersist 时抛出异常

转载 作者:太空宇宙 更新时间:2023-11-04 11:09:35 27 4
gpt4 key购买 nike

我有一个用于测试 @EntityListeners 功能的小型测试应用程序。当我运行应用程序时,我得到以下堆栈跟踪

Exception in thread "main" org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:526)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:504)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:292)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy67.save(Unknown Source)
at com.example.hibernate_envers_test.HibernateEnversTestApplication.main(HibernateEnversTestApplication.java:32)
Caused by: javax.persistence.RollbackException: Error while committing the transaction
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:87)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517)
... 17 more
Caused by: java.lang.NullPointerException
at com.example.hibernate_envers_test.AccountListener.crudLogger(AccountListener.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.hibernate.jpa.event.internal.jpa.ListenerCallback.performCallback(ListenerCallback.java:35)
at org.hibernate.jpa.event.internal.jpa.CallbackRegistryImpl.callback(CallbackRegistryImpl.java:94)
at org.hibernate.jpa.event.internal.jpa.CallbackRegistryImpl.postCreate(CallbackRegistryImpl.java:63)
at org.hibernate.jpa.event.internal.core.JpaPostInsertEventListener.onPostInsert(JpaPostInsertEventListener.java:38)
at org.hibernate.action.internal.EntityInsertAction.postInsert(EntityInsertAction.java:164)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:131)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:582)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:456)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1282)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:465)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2963)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2339)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:147)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65)
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:61)
... 18 more

正如您所看到的,它提示无法提交 jpa 事务。每当我尝试使用我的 accountHistoryRepo spring jpa 存储库接口(interface)时,都会出现空指针异常。我已经检查过帐户 pojo 参数或存储库实例是否为空,但事实并非如此。当我用 @PrePersist 替换 @PostPersist 时,TransactionSystemException 不再出现,但我仍然有那个神秘的空指针异常需要处理。除此之外,我更喜欢使用 PostPersist,因为当历史对象所基于的实际对象未正确保留时,我不想保留历史对象。谁能帮我?以下是我的测试应用程序的代码:

帐户监听器

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.example.hibernate_envers_test;

import com.example.pojo.Account;
import com.example.pojo.AccountHistory;
import javax.persistence.PostPersist;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
*
* @author maurice
*/
@Component
public class AccountListener {

@Autowired
AccountHistoryRepo accountHistoryRepo;


@PostPersist
public void crudLogger(Account account){
System.out.println("is account null?: " + account == null);
System.out.println("is account null?: " + account.getJabberId());
System.out.println("is accountHistoryrRepo null?: " + accountHistoryRepo);
if (accountHistoryRepo.count()>=10) accountHistoryRepo.deleteOldestEntry();
accountHistoryRepo.save(new AccountHistory(account));
}
}

账户pojo

@Entity
@EntityListeners(AccountListener.class)
public class Account implements Serializable {

@Id
@GeneratedValue(generator = "ID_GENERATOR")
private Long accountId;

private String name;

private boolean isEnabled;

private boolean isSmartsuppEnabled;

private String jabberId;

private double budgetWarningPercentage;

private boolean isSentBudgetWarning;

private double budgetAmount;

private int departmentLevel;

private int contactId;

public Long getAccountId() {
return accountId;
}

public Account setAccountId(Long accountId) {
this.accountId = accountId;
return this;
}

public String getName() {
return name;
}

public Account setName(String name) {
this.name = name;
return this;
}

public boolean isIsEnabled() {
return isEnabled;
}

public Account setIsEnabled(boolean isEnabled) {
this.isEnabled = isEnabled;
return this;
}

public boolean isIsSmartsuppEnabled() {
return isSmartsuppEnabled;
}

public Account setIsSmartsuppEnabled(boolean isSmartsuppEnabled) {
this.isSmartsuppEnabled = isSmartsuppEnabled;
return this;
}

public String getJabberId() {
return jabberId;
}

public Account setJabberId(String jabberId) {
this.jabberId = jabberId;
return this;
}

public double getBudgetWarningPercentage() {
return budgetWarningPercentage;
}

public Account setBudgetWarningPercentage(double budgetWarningPercentage) {
this.budgetWarningPercentage = budgetWarningPercentage;
return this;
}

public boolean isIsSentBudgetWarning() {
return isSentBudgetWarning;
}

public Account setIsSentBudgetWarning(boolean isSentBudgetWarning) {
this.isSentBudgetWarning = isSentBudgetWarning;
return this;
}

public double getBudgetAmount() {
return budgetAmount;
}

账户历史pojo

@Entity(name = "account_history")
public class AccountHistory implements Serializable {
@Id
@GeneratedValue(generator = "ID_GENERATOR")
private Long accountHistoryId;

private Long accountId;

private String name;

private boolean isEnabled;

private boolean isSmartsuppEnabled;

private String jabberId;

private double budgetWarningPercentage;

private boolean isSentBudgetWarning;

private double budgetAmount;

private int departmentLevel;

private int contactId;

public AccountHistory(){}

public AccountHistory(Account account){
this.accountId = account.getAccountId();
this.name = account.getName();
this.isEnabled = account.isIsEnabled();
this.isSmartsuppEnabled = account.isIsSmartsuppEnabled();
this.jabberId = account.getJabberId();
this.budgetWarningPercentage = account.getBudgetWarningPercentage();
this.isSentBudgetWarning = account.isIsSentBudgetWarning();
this.budgetAmount = account.getBudgetAmount();
this.departmentLevel = account.getDepartmentLevel();
this.contactId = account.getContactId();
}

public Long getAccountId() {
return accountId;
}

public AccountHistory setAccountId(Long accountId) {
this.accountId = accountId;
return this;
}

public String getName() {
return name;
}

public AccountHistory setName(String name) {
this.name = name;
return this;
}

public boolean isIsEnabled() {
return isEnabled;
}

public AccountHistory setIsEnabled(boolean isEnabled) {
this.isEnabled = isEnabled;
return this;
}

public boolean isIsSmartsuppEnabled() {
return isSmartsuppEnabled;
}

public AccountHistory setIsSmartsuppEnabled(boolean isSmartsuppEnabled) {
this.isSmartsuppEnabled = isSmartsuppEnabled;
return this;
}

public String getJabberId() {
return jabberId;
}

public AccountHistory setJabberId(String jabberId) {
this.jabberId = jabberId;
return this;
}

public double getBudgetWarningPercentage() {
return budgetWarningPercentage;
}

public AccountHistory setBudgetWarningPercentage(double budgetWarningPercentage) {
this.budgetWarningPercentage = budgetWarningPercentage;
return this;
}

public boolean isIsSentBudgetWarning() {
return isSentBudgetWarning;
}

public AccountHistory setIsSentBudgetWarning(boolean isSentBudgetWarning) {
this.isSentBudgetWarning = isSentBudgetWarning;
return this;
}

public double getBudgetAmount() {
return budgetAmount;
}

public AccountHistory setBudgetAmount(double budgetAmount) {
this.budgetAmount = budgetAmount;
return this;
}

public int getDepartmentLevel() {
return departmentLevel;
}

public AccountHistory setDepartmentLevel(int departmentLevel) {
this.departmentLevel = departmentLevel;
return this;
}

public int getContactId() {
return contactId;
}

public AccountHistory setContactId(int contactId) {
this.contactId = contactId;
return this;
}
}



public Account setBudgetAmount(double budgetAmount) {
this.budgetAmount = budgetAmount;
return this;
}

public int getDepartmentLevel() {
return departmentLevel;
}

public Account setDepartmentLevel(int departmentLevel) {
this.departmentLevel = departmentLevel;
return this;
}

public int getContactId() {
return contactId;
}

public Account setContactId(int contactId) {
this.contactId = contactId;
return this;
}
}

AccountHistoryRepo

@Repository
public interface AccountHistoryRepo extends JpaRepository<AccountHistory,Long> {
@Query("DELETE FROM account_history p WHERE p.accountHistoryId = (SELECT MIN(p.accountHistoryId) FROM account_history p)")
public void deleteOldestEntry();
}

AccountRepo

@Repository
public interface AccountRepository extends JpaRepository<Account,Long> {

}

主类

@SpringBootApplication
public class HibernateEnversTestApplication implements ApplicationContextAware {

private static ApplicationContext ac;

// @Autowired
// AccountRepository accountRepo;
public static void main(String[] args) {
SpringApplication.run(HibernateEnversTestApplication.class, args);
AccountRepository accountRepo = ac.getBean(AccountRepository.class);
//Account account = accountRepo.findOne(1003L);
Account account = new Account();
account.setBudgetAmount(6666.4)
.setBudgetWarningPercentage(66666.2)
.setContactId(3333)
.setDepartmentLevel(44444)
.setIsEnabled(true)
.setIsSentBudgetWarning(false)
.setIsSmartsuppEnabled(true)
.setJabberId("en dit is aanpassing 4")
.setName("henk");
accountRepo.save(account);
}

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.ac = applicationContext;
}
}

根配置

@Configuration
@PropertySources(value = {@PropertySource("classpath:application.properties")})
@ComponentScan//(basePackages={"repository"})
@EnableJpaRepositories//(basePackages={"repository"})
@EnableTransactionManagement
public class RootConfig {

@Value("${spring.datasource.url}")
private String dataBaseUrl;
@Value("${spring.datasource.driver}")
private String driver;
@Value("${spring.datasource.username}")
private String userName;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.strategy}")
private String strategy;

@Bean(destroyMethod = "close")
public DataSource seedDataSource(){
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setDriverClassName(driver);
hikariConfig.setJdbcUrl(dataBaseUrl);
hikariConfig.setUsername(userName);
hikariConfig.setPassword(password);

hikariConfig.setMaximumPoolSize(5);
hikariConfig.setConnectionTestQuery("SELECT 1");
hikariConfig.setPoolName("springHikariCP");

hikariConfig.addDataSourceProperty("dataSource.cachePrepStmts", "true");
hikariConfig.addDataSourceProperty("dataSource.prepStmtCacheSize", "250");
hikariConfig.addDataSourceProperty("dataSource.prepStmtCacheSqlLimit", "2048");
hikariConfig.addDataSourceProperty("dataSource.useServerPrepStmts", "true");

HikariDataSource dataSource = new HikariDataSource(hikariConfig);

return dataSource;
}

@Bean
JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
JpaVendorAdapter jpaVendorAdapter){
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
Properties props = new Properties();
props.put("org.hibernate.envers.audit_strategy","org.hibernate.envers.strategy.ValidityAuditStrategy");
props.put("org.hibernate.envers.audit_strategy_validity_store_revend_timestamp", "true");
props.put("org.hibernate.envers.track_entities_changed_in_revision","true");
props.put("org.hibernate.envers.global_with_modified_flag","true");
props.put("org.hibernate.envers.store_data_at_delete", "true");
props.put("hibernate.listeners.envers.autoRegister", "true");

entityManagerFactory.setDataSource(dataSource);
entityManagerFactory.setJpaVendorAdapter(jpaVendorAdapter);
entityManagerFactory.setPackagesToScan("com.example.pojo");
entityManagerFactory.setJpaProperties(props);
return entityManagerFactory;
}

@Bean
public JpaVendorAdapter jpaVendorAdapter(){
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setDatabase(Database.MYSQL);
adapter.setShowSql(false);
adapter.setGenerateDdl(true);
adapter.setDatabasePlatform("org.hibernate.dialect.MySQLDialect");
return adapter;
}

}

最佳答案

即使您将实体监听器设置为 @Component,JPA 使用的实际上只是该类的实例,而不是 Spring 托管 bean。这就是您收到 NullPointerException 的原因。 accountHistoryRepo 将始终为 null。

关于java - Spring 的 @EntityListeners 在使用 @Postpersist 时抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46171297/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com