【问题标题】:Java JPA Hibernate Spring @EntityListeners throws org.springframework.dao.DataIntegrityViolationExceptionJava JPA Hibernate Spring @EntityListeners 抛出 org.springframework.dao.DataIntegrityViolationException
【发布时间】:2014-08-19 09:35:44
【问题描述】:

我正在使用 Spring 3 和 Hibernate 3。我想在更新实体时自动更新上次修改日期。下面是示例代码:

休眠配置:

@Configuration
public class HibernateConfig {

    @Bean
    public DataSource dataSource() throws Exception {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        Properties properties = new Properties();
        properties.load(ClassLoader.getSystemResourceAsStream(new String("hibernate.properties")));
        dataSource.setUrl(properties.getProperty(new String("jdbc.url")));
        dataSource.setUsername(properties.getProperty(new String("jdbc.username")));
        dataSource.setPassword(properties.getProperty(new String("jdbc.password")));
        dataSource.setDriverClassName(properties.getProperty(new String("jdbc.driverClassName")));
        return dataSource;
    }

    @Bean
    public AnnotationSessionFactoryBean sessionFactory() throws Exception {
        AnnotationSessionFactoryBean sessionFactory = new AnnotationSessionFactoryBean();
        Properties hibernateProperties = new Properties();
        Properties properties = new Properties();
        properties.load(ClassLoader.getSystemResourceAsStream(new String("hibernate.properties")));

        // set the Hibernate Properties
        hibernateProperties.setProperty(new String("hibernate.dialect"), properties.getProperty(new String("hibernate.dialect")));
        hibernateProperties.setProperty(new String("hibernate.show_sql"), properties.getProperty(new String("hibernate.show_sql")));
        hibernateProperties.setProperty(new String("hibernate.hbm2ddl.auto"), properties.getProperty(new String("hibernate.hbm2ddl.auto")));
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setHibernateProperties(hibernateProperties);
        sessionFactory.setAnnotatedClasses(new Class[]{Message.class})
        return sessionFactory;
    }

    @Bean
    public HibernateTemplate hibernateTemplate() throws Exception {
        HibernateTemplate hibernateTemplate = new HibernateTemplate();
        hibernateTemplate.setSessionFactory(sessionFactory().getObject());
        return hibernateTemplate;
    }
}

DAO配置:

@Configuration
public class DAOConfig {

    @Autowired
    private HibernateConfig hibernateConfig;

    @Bean
    public MessageDAO messageDAO() throws Exception {
        MessageDAO messageDAO = new MessageHibernateDAO(hibernateConfig.hibernateTemplate());
        return messageDAO;
    }
}

消息:

import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
@Table
@EntityListeners(value = MessageListener.class)
public class Message implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column
    private int id;
    @Column(nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date lastMod;

    public Message() {

    }

    public int getId() {
       return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Date getLastMod() {
        return lastMod;
    }

    public void setLastMod(Date lastMod) {
        this.lastMod = lastMod;
    }
}

消息监听器:

import java.util.Date;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import org.springframework.stereotype.Component;

@Component
public class MessageListener {


    @PrePersist
    @PreUpdate
    public void setLastMod(Message message) {
        message.setLastMod(new Date());
    }
}

运行此消息时,不会调用 MessageListener。我使用 DAO 设计模式,当调用 dao.update(Message) 时会抛出以下异常:

org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value: com.persistence.entities.MessageStatus.lastMod; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value: com.persistence.entities.Message.lastMod
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:665)
at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.save(HibernateTemplate.java:683)
at com.persistence.dao.hibernate.GenericHibernateDAO.save(GenericHibernateDAO.java:38)

查看了许多网站,似乎没有解决方案。

【问题讨论】:

    标签: java spring hibernate entitylisteners


    【解决方案1】:

    您似乎没有使用EntityManager,而是直接使用Hibernate SessionFactory。另一个答案 Hibernate/JPA - Entity listener not being called properly 似乎表明如果不手动设置侦听器,这将不起作用。

    【讨论】:

      【解决方案2】:

      为了让 JPA 侦听器使用 SessionFactory 与 Hibernate 一起工作,从而能够使用注解(@PostPersist@PostUpdate、...), 我不得不使用JPAIntegrator 类做以下丑陋的事情。

      这是我的 Spring bean:

      @Autowired
      private LocalSessionFactoryBean sessionFactoryBean;
      
      @PostConstruct
      public void init() throws ClassNotFoundException {
          SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) sessionFactoryBean.getObject();
          SessionFactoryServiceRegistry serviceRegistry = (SessionFactoryServiceRegistry)sessionFactory.getServiceRegistry();
      
          Configuration configuration = sessionFactoryBean.getConfiguration();
      
          new JpaIntegrator().integrate(configuration, sessionFactory, serviceRegistry);
      }
      

      如果只是为了更新日期字段,您应该查看JPA @Version annotation。它的主要目的是提供乐观锁定来管理数据的并发更新。

      【讨论】:

      • 不需要那个黑客,马特。只需按照here 的描述创建文件。通常,您只需在 src/main/resources 目录下创建它即可将其打包并放在类路径中。
      猜你喜欢
      • 1970-01-01
      • 2014-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-03
      • 2020-12-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多