Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 休眠:更新对象->;还将执行不需要的delete语句_Java_Hibernate - Fatal编程技术网

Java 休眠:更新对象->;还将执行不需要的delete语句

Java 休眠:更新对象->;还将执行不需要的delete语句,java,hibernate,Java,Hibernate,我在Java应用程序中使用Hibernate作为ORM。 我有一个项目人员很多关系,该项目是地图所有者 现在我有一个问题,我想更新项目。项目有一个id,一个名称。。。和一组人。在执行更新时,将删除Project_Person join表中的所有人员,控制台上的SQL语句: Hibernate: update Project set description=?, name=? where id=? Hibernate: delete from Project_Person where projec

我在Java应用程序中使用Hibernate作为ORM。 我有一个项目人员很多关系,该项目是地图所有者

现在我有一个问题,我想更新项目。项目有一个id,一个名称。。。和一组人。在执行更新时,将删除Project_Person join表中的所有人员,控制台上的SQL语句:

Hibernate: update Project set description=?, name=? where id=?
Hibernate: delete from Project_Person where project_id=?
但我不希望执行delete语句

我的Java应用程序中有:

this.projService.updateProject(p);
其中p是项目,但以POJO方式,没有人员集。所以我想,为了让它“Hibernate就绪”,我在一个单独的事务中将其设置为findProjectById,因此我从数据库中获取项目:

Project proj = this.projService.findProjectById(p.getId());
proj.setName(p.getName());
proj.setDescription(p.getDescription());
所以我得到Hibernate就绪的项目对象,更改值,然后告诉他更新项目。但是,该集在调试器视图中是一个PersistentSet,其中没有人(我认为,因为他们是延迟加载的)。 但是用一个

session.update(p);
在新事务中,我得到update语句和不需要的delete语句。 如何避免delete语句

我是否必须创建一个特殊的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;
    }
}
调试器的屏幕截图

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;
    }
}
发送前的屏幕截图。提交()

这意味着(正如您所建议的)您的收藏是空的。但这并不是由于延迟加载——调试器将允许您加载集合。也许它是空的,因为另一个原因。通过显示
collection.size()
来确认这一点

问题的另一部分是级联。如果您已定义级联
删除孤立项
,请将其删除,或确保集合已实际填充。

您不需要调用“更新”

以下代码:

Project proj = this.projService.findProjectById(p.getId());
proj.setName(p.getName());
proj.setDescription(p.getDescription());
然后不需要更新,因为项目引用是持久的,对它的任何更改都将被保存。这是hibernate和其他ORM的一个特性,称为透明持久性


有关hibernates更新方法的更多信息,请参阅。

如果在新事务中更新项目对象,则可能应该使用

session.merge(project)

这可能会检测到未初始化的PersistentSet,用新会话中的新PersistentSet替换它,并确保该集合的条目不会被删除。否则,Hibernate可能无法处理该集合,因为创建该集合的事务已经关闭,并且假定该集合为空。

我没有定义像delete orphan这样的级联。我更深入地研究了该项目的人员:没有人员。集合的size()总是会返回LazyInitialization错误。我在问题中举了一个例子,它引发了LazyInit异常。然后将断点放在会话尚未关闭的方法中。我不太确定,如果我理解正确,但我放了一个指向我问题的屏幕截图的链接,因此,您可以看到调试器视图和带有断点的源代码。@Tim-在返回对象之前,将断点放在
projectService
中。会话在那里是可用的(并且在控制器中是关闭的,也许您的服务层周围有一个事务管理器)非常奇怪。尝试在提交事务之前打印大小。我将调试器的屏幕截图放在tx.commit()行之前。更新:把这里放在tx.commit()行前面getPersons().size(),我明白了!因此,会话在提交后关闭。那么,对于不需要的SQL delete语句,我能做些什么来解决这个问题呢?是的,但是我的模型关闭了事务,所以我需要tzo在我的例子中调用它。你的链接是好的,但我不使用它在这种情况下。