Java 使用hibernate/JPA进行持久化

Java 使用hibernate/JPA进行持久化,java,hibernate,jpa,Java,Hibernate,Jpa,我已经在JBoss上使用hibernate/JPA几个月了,有一个问题我找不到答案或解决方案 似乎在创建新实体bean时,在至少调用EntityManager.persist(entityBean)之前,我无法执行查询,否则会出现以下错误: transientObject异常:对象引用未保存的临时实例-在刷新之前保存临时实例 例如: Job job = new Job(); Collection<Task> tasks = job.getTasks(); //entityManage

我已经在JBoss上使用hibernate/JPA几个月了,有一个问题我找不到答案或解决方案

似乎在创建新实体bean时,在至少调用EntityManager.persist(entityBean)之前,我无法执行查询,否则会出现以下错误:

transientObject异常:对象引用未保存的临时实例-在刷新之前保存临时实例

例如:

Job job = new Job();
Collection<Task> tasks = job.getTasks();
//entityManager.persist(job);
ActionPlan actionPlan = (ActionPlan) entityManager.createNamedQuery("ActionPlan.findByCommand").
                setParameter("type", RunOperation.Install).getSingleResult();
Task task = Task.getTask(actionPlan);
task.setActionPlan(actionPlan);
tasks.add(task);
task.setJob(job);
Job Job=新作业();
收集任务=job.getTasks();
//entityManager.persist(作业);
ActionPlan ActionPlan=(ActionPlan)entityManager.createNamedQuery(“ActionPlan.findByCommand”)。
setParameter(“type”,RunOperation.Install).getSingleResult();
Task=Task.getTask(actionPlan);
任务。设置行动计划(行动计划);
任务。添加(任务);
task.setJob(job);
我的问题是,如果不先持久化“job”(注释掉的行),就无法调用createNamedQuery。ActionPlan与作业有关系,但NamedQuery(findByCommand)未加入作业。困扰我的是,当新创建的作业在此上下文中甚至不感兴趣时,我需要持久化作业以查询数据库。
将对persist()的调用移动到代码段的末尾会产生上述错误

我知道我正在处理的对象不是持久化的,但是如果发生错误,持久化会使回滚变得不可能


我相信这是有解决办法的,所以如果有人知道答案,我会非常感激。我遗漏了什么?

您不能查询数据库中还没有的内容似乎是合乎逻辑的,不是吗?您可以做的是开始使用事务。在一个简单的情况下,您的会话将有一个事务,该事务将一直打开,直到您关闭会话为止。此时事务将被提交,您的所有更改都将被持久化。您所需要的只是在发生错误时回滚事务

另外,你可以发现“典型的交易应该使用以下习惯用语”


我知道我不能质疑什么还没有被持久化——事实也并非如此。我想找到的是其他实体bean。不仅仅是同一类型,而是我拥有的任何类型的实体bean。然后我得到TransientObject异常

我提到我使用JBoss了吗?我相信使用J2EE和JPA服务器可以控制我的事务,我最不想做的就是干扰它?!所以对我来说,除了使用requiresNew等,我不会处理事务——服务器会处理事务


也许我应该移动hibernate标签,因为实际上我正在使用JPA-JBoss使用hibernate。所以请在任何代码示例中与之相关。

即使您持久化对象,您仍然可以回滚它。只有在EntityManager上调用flush之后,案例才会同步到底层数据库。

我认为答案和阅读Java EE 5教程中的一些内容给了我正确的答案

与我的想法相反,persist()不会刷新到数据库,它只会将实体bean移动到持久状态。欺骗我的是,我注意到在调用persist之后,实体实际上被持久化到了数据库中(可能还有错误消息中的“save”一词)。我将此视为flush被称为结束我的事务,但是如果我正确地使用了alkolm,我仍然能够回滚—由我自己或由服务器在异常情况下回滚

所以我的结论是,;只要创建了一个新实体,只要它与另一个已持久化的实体无关,就应该调用persist。
然后事务被维护,服务器会更喜欢您;)


给她留下的是,我仍然不明白为什么我不能在所有内容都处于持久状态的情况下进行查询。

我真的想帮助您,但我无法理解您要求的是哪种代码示例。下面是我们可以做的:一步一步地描述您正在做什么,提供一些代码并给出堆栈跟踪。我认为这真的不是这个网站的格式(Q&A),所以填写免费发送意味着电子邮件。gmail.com的bolyuba。但我现在可以告诉你的一件事是:“我不会搞乱事务——服务器会搞乱。”这是一种糟糕的方法。即使您确实使用了声明性事务划分,您也应该确切地知道发生了什么。Georgy,我真的很感谢您的帮助-不要误解我的意思。我想我的问题已经很简单了,所以我添加了一个例子。如果你仍然不清楚我的意思,让我们进入第二个层次:)不幸的是,上面的链接断了。
Session sess = factory.openSession();
Transaction tx;
try {
tx = sess.beginTransaction();
    //do some work
    ...
    tx.commit();
}
catch (Exception e) {
    if (tx!=null) tx.rollback();
    throw e;
}
finally {
    sess.close();
}