JPA与同一实体的两个单向@OneToMany关系导致重复输入

Teu*_*jst 5 java mysql persistence jpa maven

我目前正在开展一个学校项目,我们必须创建自己的"Twitter"应用程序,并且我在域对象的持久性方面遇到了一些麻烦.

我的帐户类(为便于阅读而简化):

@Entity
public class Account implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@Column(unique = true)
private String email;

@OneToMany
private final List<Account> following = new ArrayList<>();
@OneToMany(mappedBy = "tweetedBy", cascade = ALL)
private final List<Tweet> tweets = new ArrayList<>();
Run Code Online (Sandbox Code Playgroud)

我的推文类(为便于阅读而简化):

@Entity
public class Tweet implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
private String content;

@ManyToOne
private Account tweetedBy;

@OneToMany(cascade = CascadeType.PERSIST)
@JoinTable(name = "tweet_likes")
private final List<Account> likedBy = new ArrayList<>();

@OneToMany(cascade = CascadeType.PERSIST)
@JoinTable(name = "tweet_mentions")
private final List<Account> mentions = new ArrayList<>();
Run Code Online (Sandbox Code Playgroud)

持久代码(简化):

Account a1 = new Account("user1@gmail.com", "password1");
Account a2 = new Account("user2@gmail.com", "password2");
Account a3 = new Account("user3@gmail.com", "password3");

a1.addTweet("Sup mah dudes.");
a1.addTweet("yoyo");
a2.addTweet("Allo Allo #tweeting");
a2.addTweet("#testing yoyo");
a1.getTweets().get(0).addLike(a3);
a1.addFollowing(a3);

em.persist(a1);
em.persist(a2);
em.persist(a3);
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是,likedBymentions没有正确持久化.正在生成链接器表并插入数据,但我在插入用户时不断出现重复的条目错误.我相信我正确地建立了关系(单向OneToMany),因为我不希望帐户跟踪它所提到的推文.

我尝试过的:

  • @JoinColumn对于两者likesmentions(导致重复插入)
  • @JoinTable对于两者likesmentions(导致重复插入)
  • 只有@OneToMany两个likesmentions(这不会导致错误而造成两者关系的情形之一不能为空1个连接表)
  • @OneToManyfor likes和then @joinColumnfor mentionswhere nullable = true(这导致你不能在推文中提到你的情况,除非你喜欢它,这是奇怪的行为)
  • @OneToMany(cascade = CascadeType.MERGE) (导致重复插入)

Netbeans输出的重复插入错误:

Warning:   Local Exception Stack: 
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.4.qualifier): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'user6@gmail.com' for key 'EMAIL'
Error Code: 1062
Call: INSERT INTO ACCOUNT (AVATARPATH, BIO, EMAIL, ENCRYPTEDPASSWORD, LOCATION, USERNAME, USERROLE, WEBSITE) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
bind => [8 parameters bound]
Query: InsertObjectQuery(domain.Account@3c7f9d54)
Run Code Online (Sandbox Code Playgroud)

我相信这个错误的发生是因为我的JPA imlementation的流程如下:

  1. 帐户仍然存在
  2. 推文持续存在(因为它在账户内)
  3. 帐户持续存在(因为它在Tweet内)< - 重复条目

我期待的是:

  • 1个链接表,带有a tweet_id (fk)account_id (fk)代表like
  • 1个链接表,带有a tweet_id (fk)account_id (fk)表示提及

如果有人可以帮我解释注释或者解释我做错了什么,那将非常感激.

Ty提前获得任何帮助.

Teu*_*jst 1

我解决了问题,原来是 和 处的likes注释mentions@JoinTable(name = "")修复。我认为在重新部署之前不手动删除表会导致我一开始没有将其视为解决方案。

对于任何有类似问题的人,这是我的解决方案:

@OneToMany(cascade = CascadeType.PERSIST)
@JoinTable(name = "tweet_likes") //<--CREATES SEPERATE TABLE
private final List<Account> likedBy = new ArrayList<>();
@OneToMany(cascade = CascadeType.PERSIST)
@JoinTable(name = "tweet_mentions") //<--CREATES SEPERATE TABLE
private final List<Account> mentions = new ArrayList<>();
Run Code Online (Sandbox Code Playgroud)

另外,显然如果我重新启动整个项目(重新启动整个 glassfish/payara 服务器),我会收到重复条目错误,因为 EntityManager 会在删除并重新创建表之前尝试保留到数据库。因此,如果我只是取消部署并重新部署我的项目,同时保持 payara 服务器在线,它就会保持正常。我还没有找到这个问题的解决方案,但这是另一个问题。