java - 断言失败 : null id sometimes thrown when Hibernate query objects

标签 java spring postgresql hibernate

我有一个在 Tomcat v2.2.0 EC2 服务器上运行的 Spring 4.2.4/Hibernate 5.0.6。

我遇到的问题是在运行服务器一段时间(超过一天)后,我开始偶尔出现以下异常

org.hibernate.AssertionFailure: null id in com.app.core.models.User entry (don't flush the Session after an exception occurs)
org.hibernate.event.internal.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:60)
org.hibernate.event.internal.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:175)
org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:135)
org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:216)
org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:85)
org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:44)
org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1251)
org.hibernate.internal.SessionImpl.list(SessionImpl.java:1767)
org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:363)
com.app.core.dao.AbstractDao.queryBy(AbstractDao.java:57)
com.app.business.MainController.surveryPage(MainController.java:41)
sun.reflect.GeneratedMethodAccessor65.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:178)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:444)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:432)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)

对象Survery对象有一个User类型的owner字段,异常表明id为null,检查Datebase,id不为null。并且实际重新启动服务器会使错误消失一段时间。

@Entity
@Table(indexes={@Index(columnList = "OWNER_ID", name = "OWNER_ID_INDEX")})
public class Survey extends Persistable{
...
@JsonIgnore
@ManyToOne
@JoinColumn(name = "OWNER_ID", nullable = true)
private User owner;
...
}

我正在做的查询操作是:

public List<T> queryBy(String field, Object val) {
    Session session = sessionFactory.getCurrentSession();
    Transaction transaction = session.beginTransaction();
    Criteria criteria = session.createCriteria(persistentClass);
    criteria.add(Restrictions.eq(field, val));
    @SuppressWarnings("unchecked")
    List<T> l = criteria.list();
    transaction.commit();
    return l;
}

实际上我担心我在 session 配置中做错了什么, hibernate 的配置如下:

import org.apache.commons.dbcp2.BasicDataSource;
import org.hibernate.SessionFactory;
import org.reflections.Reflections;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.orm.hibernate5.HibernateTemplate;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBuilder;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import com.app.core.db.PersistableInterceptor;
import com.app.core.db.Persistable;
@Configuration 
@EnableTransactionManagement
@Profile("dev")
public class Config {
    ..... 

    @Bean
    public HibernateTemplate hibernateTemplate() {
        return new HibernateTemplate(sessionFactory());
    }

    @Bean
    public SessionFactory sessionFactory() {
        if (sessionFactory!= null){
            return sessionFactory;
        }
        Properties p = new Properties();
        p.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
        p.put("connection_pool_size", "10");
        p.put("hibernate.current_session_context_class", "thread");
        p.put("show_sql", "true");
        p.put("hibernate.hbm2ddl.auto", "update");
        p.put("hibernate.default_schema", "app");
        p.put("hibernate.jdbc.batch_size", BATCH_SIZE);

        SessionFactory sessionFactory = new LocalSessionFactoryBuilder(getDataSource())
           .addAnnotatedClasses(ANNOTATED_CLASSES)
           .addProperties(p)
           .setInterceptor(new PersistableInterceptor())
           .buildSessionFactory();
        Config.sessionFactory = sessionFactory;
        return sessionFactory;
    }

    @Bean
    public HibernateTransactionManager hibTransMan(){
        return new HibernateTransactionManager(sessionFactory());
    }

    ..... 

}

有什么想法或建议吗?

最佳答案

您正在将 Hibernate 管理的事务与 Spring 管理的事务混合在一起。当您使用 Spring 事务管理抽象时,您不必使用特定于资源的事务

您已通过 @EnableTransactionManagenent 启用了 Spring 事务。如果您的 bean 有 @Transactional 注释,那么将您的代码重构为

public List<T> queryBy(String field, Object val) {
    Session session = sessionFactory.getCurrentSession();
    Criteria criteria = session.createCriteria(persistentClass);
    criteria.add(Restrictions.eq(field, val));
    @SuppressWarnings("unchecked")
    List<T> l = criteria.list();
    return l;
}

还要更改 SessionFactory bean 定义以使用 Spring 提供的 LocalSessionFactoryBean。这为使用 Spring 抽象的事务管理提供了钩子(Hook)。示例

 @Bean
   public LocalSessionFactoryBean sessionFactory() {
      LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
      sessionFactory.setDataSource(dataSource());
      sessionFactory.setPackagesToScan(new String[] { "package.to.your.entity.classes" });
      sessionFactory.setHibernateProperties(hibernateProperties());

      return sessionFactory;
   }

@Bean
public DataSource dataSource(){
   //define datasource
}

private  Properties hibernateProperties() {
   //hibernate props
}

关于java - 断言失败 : null id sometimes thrown when Hibernate query objects,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40148016/

相关文章:

java - 模拟一个抽象方法,而不是类构造函数

java - WebSphere 服务器未接受 EAR 中的新更改

sql - 如何选择多列,但只显示唯一/非重复的结果(基于一个特定列)?

java - Spring 4.1.2 更新后找不到资源

java - Spring autowire byName 没有按预期工作

postgresql - 尽管之前有 "SET client_min_messages TO WARNING"信息输出

postgresql - 根据 postgres 中的条件进行部分更新

java - RSA加密Javascript和解密Java

java - 在我的 HTC Evo 上使用 Eclipse 进行 Android 调试 : Augh!

spring - Hibernate 与 Spring 的集成在 hippo cms 站点项目中不起作用