Spring/Hibernate:保存后是不是必须加载实体才能使用它?

Posted

技术标签:

【中文标题】Spring/Hibernate:保存后是不是必须加载实体才能使用它?【英文标题】:Spring/Hibernate: Do you have to load entities to use it after saving?Spring/Hibernate:保存后是否必须加载实体才能使用它? 【发布时间】:2010-09-01 07:53:07 【问题描述】:

我有一个包含两个表的数据库模型:Session 和 ScriptExecution,它们与一对多关系相关联:

public class ScriptExecution implements Serializable 

 @ManyToOne
 @PrimaryKeyJoinColumn
 private Session session;

...


public class Session implements Serializable 

 @OneToMany(fetch=FetchType.EAGER, mappedBy="session")
 private Set<ScriptExecution> scriptExecutions;

...

如果我创建一个会话,加载它并将其分配给脚本执行,一切正常:

Session session = new Session();
sessionDao.save(session);

session = sessionDao.load(1);

ScriptExecution scriptExecution = new ScriptExecution();
ScriptExecution.setSession(session);
scriptExecutionDao.save(scriptExecution);

如果我直接使用创建的会话将其分配给 ScriptExecution,如下所示:

Session session = new Session();
sessionDao.save(session);

ScriptExecution scriptExecution = new ScriptExecution();
ScriptExecution.setSession(session);
scriptExecutionDao.save(scriptExecution);

Hibernate 失败并出现以下错误:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: Could not execute JDBC batch update; SQL [insert into script_execution (end, session_id, start, id) values (?, ?, ?, ?)]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
 org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:656)
 org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
 javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
 javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

root cause

org.springframework.dao.DataIntegrityViolationException: Could not execute JDBC batch update; SQL [insert into script_execution (end, session_id, start, id) values (?, ?, ?, ?)]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
 org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:637)
 org.springframework.orm.hibernate3.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:793)
 org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:664)
 org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
 org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
 org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:147)
 com.sc2.web.controller.MainController.handleRequest(MainController.java:45)
 org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
 org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:774)
 org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
 org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
 org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
 javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
 javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

root cause

org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
 org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:94)
 org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
 org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
 org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
 org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
 org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
 org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
 org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1028)
 org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:366)
 org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
 org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656)
 org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
 org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
 org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:147)
 com.sc2.web.controller.MainController.handleRequest(MainController.java:45)
 org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
 org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:774)
 org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
 org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
 org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
 javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
 javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

root cause

java.sql.BatchUpdateException: Cannot add or update a child row: a foreign key constraint fails (`sc2`.`script_execution`, CONSTRAINT `fk_script_execution_session1` FOREIGN KEY (`session_id`) REFERENCES `session` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION)
 com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2020)
 com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1451)
 org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
 org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
 org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
 org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
 org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
 org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
 org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1028)
 org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:366)
 org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
 org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656)
 org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
 org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
 org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:147)
 com.sc2.web.controller.MainController.handleRequest(MainController.java:45)
 org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
 org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:774)
 org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
 org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
 org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
 javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
 javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

我也尝试将代码放入事务中,但代码失败并出现同样的错误。

TransactionTemplate template = new TransactionTemplate(transactionManager);
template.execute(new TransactionCallbackWithoutResult() 

   @Override
   protected void doInTransactionWithoutResult(TransactionStatus arg0) 
    Session session = new Session();
    sessionDao.save(session);

    ScriptExecution scriptExecution = new ScriptExecution();
    scriptExecution.setSession(session);
    scriptExecutionDao.save(scriptExecution);

   
  );

你有什么想法吗?我不敢相信我必须在创建实体后加载它们。

【问题讨论】:

【参考方案1】:

我能够解决问题: 表示实体中的 id 并在数据库模式中设置为自动递增的 @Id 注释属性也必须使用 @GeneratedValue 进行注释,例如

@Id
@GeneratedValue
private int id;

而不仅仅是。

@Id
private int id;

【讨论】:

你应该知道,这只有两天时间。

以上是关于Spring/Hibernate:保存后是不是必须加载实体才能使用它?的主要内容,如果未能解决你的问题,请参考以下文章

Spring/Hibernate GenerationType.AUTO 的数据库备份问题

atitit.spring hibernate的事务机制 spring不能保存对象的解决

使用一对多映射保存对象时出现 Spring + Hibernate id 问题

Spring Hibernate Validation

Spring,Hibernate:尝试保存图像时出现无效的 UTF-8 起始字节 0x80 错误

重复条目异常:Spring Hibernate/JPA 级联保存多对一