我在我的Java应用程序中使用Hibernate作为ORM。 我有一个项目< - > person manytomany-relation和Project是映射所有者。
现在我遇到了问题,我想要更新项目。该项目有一个id,一个名字,......和一组人。执行更新时,将在Project_Person连接表中删除所有人员,控制台上的SQL语句:
Hibernate: update Project set description=?, name=? where id=?
Hibernate: delete from Project_Person where project_id=?
但我不希望删除语句被执行。
我在Java应用程序中有这个:
this.projService.updateProject(p);
其中p是项目,但是在没有人员集合的POJO方式中。所以我想,为了使它成为“Hibernate-ready”,我在一个单独的事务中创建了一个findProjectById,所以我从数据库中获取项目:
Project proj = this.projService.findProjectById(p.getId());
proj.setName(p.getName());
proj.setDescription(p.getDescription());
所以我得到了Hibernate-ready Project对象,更改了值,然后告诉他更新项目。但是Set在调试器视图中是PersistentSet,并且没有人(我认为,因为它们是延迟加载的)。 但是用
更新session.update(p);
在新事务中,我得到更新语句和不需要的删除语句。 如何避免删除语句?
我是否必须创建一个特殊的SQL语句,以便只更新我想要更新的数据库表字段?还是有其他/更好的解决方案?
最诚挚的问候。
更新 这会抛出一个LazyInitializationException:
public Project findProjectById(int projectId) {
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session sess = sessionFactory.getCurrentSession();
Transaction tx = sess.beginTransaction();
try {
Project project = (Project)sess.createQuery("from Project where id = "+projectId).list().get(0);
tx.commit();
System.out.println(project.getPersons().size());
return project;
} catch (IndexOutOfBoundsException ex) {
return null;
}
}
调试器的屏幕截图:
http://img94.imageshack.us/img94/2020/screendebugger.png
的HibernateUtil
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
// SessionFactory of Hibernate
private static final SessionFactory sessionFactory;
static {
try {
sessionFactory = new Configuration().configure("/hibernate.cfg.xml").buildSessionFactory();
}
catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed. " + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
tx.commit()
之前的屏幕截图答案 0 :(得分:2)
这意味着(如您所示)您的收藏是空的。但这不是由于延迟加载 - 调试器允许您加载集合。也许它是空的另一个原因。通过显示collection.size()
确认这一点。
问题的另一部分是级联。如果您已定义为级联delete-orphan
,则将其删除,或确保该集合实际已填充。
答案 1 :(得分:0)
您不需要拨打“更新”。
以下代码:
Project proj = this.projService.findProjectById(p.getId());
proj.setName(p.getName());
proj.setDescription(p.getDescription());
然后不需要更新,因为proj引用是持久的,并且将保存对它的任何更改。这是hibernate和其他ORM的一个特性,称为透明持久性。
有关hibernates更新方法的详细信息,请参阅here。
答案 2 :(得分:0)
如果在新事务中更新Project对象,则可能应该使用
将对象与新Session关联session.merge(project)
可能检测到未初始化的PersistentSet,将其替换为新Session中的新PersistentSet,并确保不删除Set的条目。否则Hibernate可能无法处理Set,因为创建它的事务已经关闭并假定它是空的。