Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.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 JPA更新相关实体_Java_Jpa - Fatal编程技术网

JAVA JPA更新相关实体

JAVA JPA更新相关实体,java,jpa,Java,Jpa,我在更新相关实体时遇到问题 让我从一个简单的例子开始。 假设我有一个用户1:1配置文件关系 如何更新(替换)属于用户的配置文件实体 我尝试了以下方法但未成功(两个OneToOne关系都具有CascadeType=ALL属性) 我完全搞不懂JPA,有一些有用的例子,但它们不是关于更新实体的(只是更新单个值,提高工资等…) 我希望建议的方法在1:N关系的情况下也能起作用。我总是做em.merge(user)更新实体后。如果您有适当的级联选项,这也将更新所有相关的实体 现在,我知道(听说)实体应该在事

我在更新相关实体时遇到问题

让我从一个简单的例子开始。 假设我有一个用户1:1配置文件关系

如何更新(替换)属于用户的配置文件实体

我尝试了以下方法但未成功(两个OneToOne关系都具有CascadeType=ALL属性)

我完全搞不懂JPA,有一些有用的例子,但它们不是关于更新实体的(只是更新单个值,提高工资等…)

我希望建议的方法在1:N关系的情况下也能起作用。

我总是做
em.merge(user)更新实体后。如果您有适当的级联选项,这也将更新所有相关的实体


现在,我知道(听说)实体应该在事务结束时更新数据库本身,但我更喜欢直接调用。坦率地说,我发现整个“自动更新实体”模式在现实世界的开发中与其说是优势,不如说是问题。

这取决于您想做什么。如果用户和概要文件真的是一对一的,那么用不同的概要文件对象替换整个概要文件对象的想法就有点多余了。如果您使用的框架在整个操作中保留持久性上下文,那么您可以只更新Profile对象和flush中的值,因为创建新对象会因为级联而有点混乱

但是,如果您的框架没有保留持久性上下文,那么您将分离已修改的实体,您必须使用
em.merge()
,或者您可以获取原始实体(
em.find
)并在中复制属性。在我看来,考虑到一个正确使用JPA的框架,这是乏味、容易出错和不必要的。最好在持久性上下文中修改对象,让“自动更新实体”来完成它的工作(显然我非常喜欢它)。习惯需要一点时间,但一旦习惯了,你就再也不想回去了

在任何情况下,当调用
em.flush()
时,所有更改都将写入JDBC连接,并且连接中挂起的更改将在事务完成时提交

如何更新(替换)属于用户的配置文件实体

由于您的关联是双向的,因此您必须管理
用户
配置文件
之间链接的两侧。因此,“更改”用户的配置文件需要以下内容:

User user = em.find(User.class, key);

Profile profile = new Profile();
...
user.setProfile(profile);
profile.setUser(user);

em.getTransaction().commit(); 
在我使用的JPA实现中,对上述代码执行了以下查询:

INSERT INTO CPROFILE (ID) VALUES (?)
    bind => [2]
UPDATE CUSER SET CPROFILE_ID = ? WHERE (ID = ?)
    bind => [2, 1]

我删除了CascadeType ALL,一切都如我们所期望的那样工作,下面是代码

。。。。。。。。。。。。。。。。。。。。。。。。。库塞尔 @实体 公共类CUser{ @身份证 @GeneratedValue(策略=GenerationType.IDENTITY) 私钥id; 私人字符串电子邮件

        em.persist(Profile_);

        em.getTransaction().commit();
    }
    catch(Exception e){GAEHelper.getLogger().warning("Exception:"+e.getMessage()+" "+e.getCause());}        
    finally {
        if (em.getTransaction().isActive()) {
            em.getTransaction().rollback();
        }
    }

    em.close();

    return true;
}
更新
... CUser User=em.find(CUser.class,UserId_389;); ... em.getTransaction().begin(); 尝试 { em.remove(User.getProfile())

谢谢大家


cscsaba

除非您已分离实体,否则您不需要使用
em.merge()
。当实体管理器被“刷新”时,持久性上下文中的所有实体将自动更新,这是某些(IMO不灵活的)框架在每个事务结束时强制执行的。您是指这个吗?Profile.setUser(User);User.setProfile(配置文件);em.merge(用户);或User.setProfile(配置文件);em.merge(用户);它们也不起作用…新配置文件已保存,但无法替换旧配置文件。我做错了什么?检查它们的行为是否如我所说,新配置文件已创建但无法替换旧配置文件@cscsaba242请显示您的实体映射。我想我需要在internet上的某个位置提供一个示例。我在GAE上使用JPA(我想用:)你提到的几个术语在实践中不太清楚,这将是一个很好的例子。我复制粘贴在我实体的源代码上方。你好,帕斯卡,我尝试过你提到的这种方式,但没有成功,我不知道怎么回事。我将再试一次,谢谢大家!@CSCSSABA242:这很奇怪。但我不是GAE/J JPA的专家“支持”,可能有一些我不知道的行为的具体细节。我想知道你是否可以这样做。找到配置文件obj并为其分配一个新对象。配置文件=新配置文件(…)

......................... CPROFILE
@Entity
public class CProfile {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Key id;
        private String phone;

    @OneToOne(mappedBy="profile")
    private CUser User;
@OneToMany(mappedBy="user")
private List<CPossibility> Possibilities = new ArrayList<CPossibility>();

@OneToOne 
@JoinColumn(name="cprofile_id") 
private CProfile profile;   
        em.persist(Profile_);

        em.getTransaction().commit();
    }
    catch(Exception e){GAEHelper.getLogger().warning("Exception:"+e.getMessage()+" "+e.getCause());}        
    finally {
        if (em.getTransaction().isActive()) {
            em.getTransaction().rollback();
        }
    }

    em.close();

    return true;
}
        Profile_.setUser(User);             
        User.setProfile(Profile_);

        em.persist(Profile_);
        em.getTransaction().commit();
    }