- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个用于测试 @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/
我有一个带有名为“doAudit”的@PostPersist 方法的监听器来审核创建操作。在调试时我看到此方法被调用并且审核记录是在 JAVA 端创建的。但是当我验证数据库时,我没有看到记录。 pub
我有一个持久化实体对象的方法 persistData() 。我有另一个方法 findData() ,它对同一实体类执行 find() 操作以获取持久的主键值。当我在实体类的@PostPersist中调
我已经阅读了有关生命周期事件的文档,以及关于在生命周期事件期间更改或保留新实体的几个问题。调用EnitityManager::flush()似乎是个问题。 好的,但是 looking carefull
我想在实体上添加新的 Feed 项并持续更新。我写了这个事件监听器(postUpdate 是一样的): public function postPersist(LifecycleEventArgs $
我正在尝试在创建另一个实体的基础上创建一个新实体。示例:我有一段关系 Sale Payment 现在,当我坚持销售时,您必须创建一个初始付款,但我不知 Prop 体该怎么做。 我尝试过: 使用@OR
我在使用手动事务时插入/更新 3 个表。我想在事务提交后立即插入到历史表中。这意味着有 3 em.persist操作(对于每个表),并且只有在提交它们之后我才想调用一个方法。 这是我的代码: @Res
Doctrine 的事件监听类中的 postUpdate 和 postPersist 事件有什么区别?以我的理解,更新和插入都必须坚持下去。那么当可以在 postPersist 事件中处理它时,拥有
我正在尝试设置我的 hibernate 应用程序以在每次创建 Activity 实体时都保留一个新的 Notification 实体 - 目前,我已经尝试了 通知只是无法静默地持续存在(日志中没有错误
假设我有实体 Account: @Entity(name = "ACCOUNT") @EntityListeners(Listener.class) public class AccountEntit
我在数据库中出现双重插入的奇怪错误。我有以下类(class): TestEntity - 具有@PrePersist 和@PostPersist 方法的实体。 Auditoria - 审计实体 Dat
我目前正在使用 @PostPersist 和 @PostUpdate,在这些触发器中我正在持久化其他实体。问题是,这些触发器是否在同一事务中,如果不是,是否可以强制执行? 对我来说,它是这样工作的。当
我正在使用监听器来坚持和根据 Doctrine 进行更新。 唯一的问题是,当调用监听器时,它会创建并更新新的/当前的实体,因此它再次调用自身,从而创建两个实体。 我认为阻止这种情况的唯一方法是拥有一个
在 Symfony 中创建 Doctrine postPersist EventListener 后,我的 IDE 指向 $args->getEntity() 行;由于已被弃用,我不知道如何解决这个问
我有一个 JPA @Entity 类,它使用 @PrePersist 已经有一段时间了。今天我想在需要该实体 ID 的地方添加一些功能。此 ID 由数据库中的 HIBERNATE_SEQUENCE 持
我有一个用于测试 @EntityListeners 功能的小型测试应用程序。当我运行应用程序时,我得到以下堆栈跟踪 Exception in thread "main" org.springframe
我有下一个 ER 图 我想在每次保存 Score 实体时更新 PlayerStat 实体。所以我尝试使用 @PostPersist 注释。当我保存 Score 实体时,调用该注释的函数,但我在此函数中
每当在管理员中完成持久化或更新等操作时,我想创建一个静态 Twig 文件。我在想的是创建一个名为 GenerateStaticListener 的监听器。监听器将监听事件 postPersist 或
我是一名优秀的程序员,十分优秀!