[英]AssertionFailure: null id sometimes thrown when Hibernate query objects
I have a Spring 4.2.4/Hibernate 5.0.6 running on Tomcat v2.2.0 EC2 servers. 我在Tomcat v2.2.0 EC2服务器上运行了Spring 4.2.4 / Hibernate 5.0.6。
The issue I have is after running server for sometime (more than one day) I start to get the following exception occasionally 我遇到的问题是服务器运行了一段时间(超过一天)后,我偶尔会收到以下异常消息
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)
The object Survery object have an owner field of type User, as the exception states that the id is null, checking the Datebase, the id is not not null. 对象Survery对象的所有者字段类型为User,因为异常指出id为null,检查Datebase,则id不为null。 And actually restarting the server make the error disappear for a while. 并实际上重新启动服务器会使错误消失一段时间。
@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;
...
}
The query operation I'm doing is: 我正在执行的查询操作是:
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;
}
Actually I'm worrying if I did something wrong in the session configuration, the configuration for hibernate are below: 实际上,我担心如果在会话配置中做错了什么,用于休眠的配置如下:
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());
}
.....
}
Any thoughts or suggestion? 有什么想法或建议吗?
You are mixing Hibernate managed transactions with Spring managed transactions. 您正在将Hibernate托管事务与Spring托管事务混合在一起。 When you are using Spring transaction management abstraction you don`t have to use resource specific transactions 使用Spring事务管理抽象时,您不必使用特定于资源的事务
You have Spring transactions enabled via @EnableTransactionManagenent. 您已经通过@EnableTransactionManagenent启用了Spring事务。 If your beans have a @Transactional annotation then refactor your code to be 如果您的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;
}
Also change your SessionFactory bean definition to make use of LocalSessionFactoryBean provided by Spring. 还要更改您的SessionFactory bean定义,以利用Spring提供的LocalSessionFactoryBean。 This provides hooks for transaction management using Spring abstraction. 这为使用Spring抽象的事务管理提供了挂钩。 Example 例
@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
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.