复杂的JPA持久化订单问题

发布于 10-08 14:19 字数 886 浏览 8 评论 0原文

我正在开发一个具有一些不寻常的实体关系的项目,我在使用 JPA 时遇到了持续存在的问题。有两个相关的对象;用户,让我们称之为另一个X。用户与X有一对多和两个一对一的关系。它基本上看起来像这样

[用户实体]

@OneToMany(mappedBy="user", cascade=CascadeType.ALL, orphanRemoval=true)  
private List<X> xList;

@OneToOne  
@JoinColumn(name = "active_x1_id")  
private X activeX1;  

@OneToOne  
@JoinColumn(name = "active_x2_id")  
private X activeX2;

[X实体]

@ManyToOne()  
@JoinColumn(name="user_id")  
private User user;

当持久化一个新用户时,我也想在单个事务中保留两个 x 实体(一个用于 activeX1,一个用于 activeX2)。 Jpa 处理这个有点奇怪,日志看起来像这样:

INSERT INTO X VALUES (...) // x1  
INSERT INTO USERS VALUES (...)  
INSERT INTO X() VALUES (...) // x2  
UPDATE USERS SET ...  
UPDATE X VALUES (...) // updates x1  

这使得不可能在数据库中使用 NOT NULL 约束。有没有更好的方法来处理这些多重关系?或者控制 JPA 持久化对象的顺序的方法? JPA 似乎确实明确地试图在这次操作中对我不利。任何帮助将不胜感激。

I'm working on a project with some unusual entity relations which i'm having problems persisting with JPA. There are two relevant objects; User and let's call the other X. User has a one-to-many AND two one-to-one relations to X. It basicly looks like this

[User entity]

@OneToMany(mappedBy="user", cascade=CascadeType.ALL, orphanRemoval=true)  
private List<X> xList;

@OneToOne  
@JoinColumn(name = "active_x1_id")  
private X activeX1;  

@OneToOne  
@JoinColumn(name = "active_x2_id")  
private X activeX2;

[X entity]

@ManyToOne()  
@JoinColumn(name="user_id")  
private User user;

When persisting a new user, I also want to persist two x entities (one for activeX1 and one for activeX2) in a single transaction. Jpa handles this abit weird, the log looks like this:

INSERT INTO X VALUES (...) // x1  
INSERT INTO USERS VALUES (...)  
INSERT INTO X() VALUES (...) // x2  
UPDATE USERS SET ...  
UPDATE X VALUES (...) // updates x1  

This makes it impossible to use NOT NULL constraints in the database. Is there any better way to handle these multiple relationships? Or a way to control which order JPA persists objects? JPA really seems to explicitly try to work against me in this operation. Any help would be appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

没有伤那来痛2024-10-15 14:19:41

为什么不直接使用@NotNull注释呢?我认为没有办法改变持久顺序。你必须手动完成。像这样的事情,

User user = ...;

if ( user.getActiveX1().getId() == null ) {
      entityManager.persist( user.getActiveX1() );
} else {
      entityManager.merge( user.getActiveX1() );
}

if ( user.getActiveX2().getId() == null ) {
      entityManager.persist( user.getActiveX2() );
} else {
      entityManager.merge( user.getActiveX2() );
}

if ( user.getId() == null ) {
      entityManager.persist( user );
} else {
      entityManager.merge( user );
}

Why don't you just use @NotNull annotation? I don't think there is a way to change persist order. You have to do it manually. Something like this,

User user = ...;

if ( user.getActiveX1().getId() == null ) {
      entityManager.persist( user.getActiveX1() );
} else {
      entityManager.merge( user.getActiveX1() );
}

if ( user.getActiveX2().getId() == null ) {
      entityManager.persist( user.getActiveX2() );
} else {
      entityManager.merge( user.getActiveX2() );
}

if ( user.getId() == null ) {
      entityManager.persist( user );
} else {
      entityManager.merge( user );
}
幽梦紫曦~2024-10-15 14:19:41

通过使用 EntityManager.flush 方法解决,强制 JPA 首先保留用户。

user.setProperties(属性);
em.persist(用户);
em.flush();

X x1 = 新X(用户);
user.setActiveX1(x1);
X x2 = 新 X(用户);
user.setActiveX2(x2);

我仍然必须允许用户的 activeX 列上有空值,但这没关系,因为我至少可以强制 X 上不为空。

Solved with the use of EntityManager.flush method, forcing JPA to persist the user first.

user.setProperties(properties);
em.persist(user);
em.flush();

X x1 = new X(user);
user.setActiveX1(x1);
X x2 = new X(user);
user.setActiveX2(x2);

I still have to allow null values on the activeX-column of user, but that is alright as I can at least force not null on X.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文