JPA:回滚后刷新分离的实体并重新附加它 - java

我有一个方法可以接收JPA Entity及其相关的EntityManager作为参数。 Entity实例不是在类内部创建的,它很可能与其他类(如GUI等)共享。

该方法启动事务,对实体进行一些更改,最后提交事务。

万一提交失败,将调用EntityTransaction.rollback():根据JPA规范,然后将实体与管理器分离。

万一发生故障,应用程序需要丢弃待处理的更改,恢复实体e中的原始值,然后将其重新附加到EntityManager,以便对e对象的各种分散引用将保持有效。问题出在这里:据我了解,这不是使用EntityManager的API进行的简单操作:

由于EntityManager.refresh(e)已分离,因此无法调用e
执行e = EntityManager.merge(e)会为e创建一个新实例:在运行时程序中对原始e的所有其他引用都不会更新为新实例。这是主要问题。
此外(实际上对此还不太确定),EntityManager.merge(e)将使用e当前持有的值(即可能导致提交失败的值)更新新托管实例的值。相反,我需要重置它们。

样例代码:

public void method(EntityManager em, Entity e) {
    EntityTransaction et = em.getTransaction();
    et.begin();
    ...
    // apply some modifications to the entity's fields
    ...
    try {
        et.commit();
    } catch (Exception e) {
        et.rollback();

        // now that 'e' is detached from the EntityManager, how can I:
        // - refresh 'e', discarding all pending changes
        // - without instantiating a copy (i.e. without using merge())
        // - reattach it
    }
}

在这种情况下最好的方法是什么?

参考方案

可能的解决方案是:

public class YourClass {
    private EntityManager em = ...; // local entity manager

    public void method(Entity e) { // only entity given here
        Entity localEntity = em.find(Entity.class, e.getId());
        EntityTransaction et = em.getTransaction();
        et.begin();
        ...
        // apply some modifications to the local entity's fields
        applyChanges(localEntity);
        ...
        try {
            et.commit();
            // Changes were successfully commited to the database. Also apply
            // the changes on the original entity, so they are visible in GUI.
            applyChanges(e);
        } catch (Exception ex) {
            et.rollback();
            // original entity e remains unchanged
        }
    }

    private void applyChanges(Entity e) { 
        ... 
    }
}

从实体获取或创建插入语句 - java

是否存在具有值的现有实体类生成插入语句的可能性?编辑:我的意思是为实体类的实例生成一个插入语句,以单独执行该语句。提前致谢 java大神给出的解决方案 使用Fastnate,您可以为没有连接数据库的实体创建SQL语句:public String createSQL() { // Create your entity TestEntity entity = n…

JAVA:字节码和二进制有什么区别? - java

java字节代码(已编译的语言,也称为目标代码)与机器代码(当前计算机的本机代码)之间有什么区别?我读过一些书,他们将字节码称为二进制指令,但我不知道为什么。 参考方案 字节码是独立于平台的,在Windows中运行的编译器编译的字节码仍将在linux / unix / mac中运行。机器代码是特定于平台的,如果在Windows x86中编译,则它将仅在Win…

java:继承 - java

有哪些替代继承的方法? java大神给出的解决方案 有效的Java:偏重于继承而不是继承。 (这实际上也来自“四人帮”)。他提出的理由是,如果扩展类未明确设计为继承,则继承会引起很多不正常的副作用。例如,对super.someMethod()的任何调用都可以引导您通过未知代码的意外路径。取而代之的是,持有对本来应该扩展的类的引用,然后委托给它。这是与Eric…

如何获取查询中实体嵌套列表的总大小? - java

我正在使用JPA,并且具有这样的数据结构:class ContainerA { long id; List<ContainerB> bs; } class ContainerB { long id; List<ContainerC> cs; } class ContainerC { long id; List<Device>…

Java:BigInteger,如何通过OutputStream编写它 - java

我想将BigInteger写入文件。做这个的最好方式是什么。当然,我想从输入流中读取(使用程序,而不是人工)。我必须使用ObjectOutputStream还是有更好的方法?目的是使用尽可能少的字节。谢谢马丁 参考方案 Java序列化(ObjectOutputStream / ObjectInputStream)是将对象序列化为八位字节序列的一种通用方法。但…