Teun van der Wijst
Teun van der Wijst

Reputation: 1009

JPA two unidirectional @OneToMany relationships to the same entity resulting in duplicate entry

I'm currently working on a school project where we have to create our own 'Twitter' application and I'm having some trouble with the persistence of the domain objects.

My Account class (simplified for readability):

@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<>();

My Tweet class (simplified for readability):

@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<>();

The persist code (simplified):

Account a1 = new Account("[email protected]", "password1");
Account a2 = new Account("[email protected]", "password2");
Account a3 = new Account("[email protected]", "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);

The problem I'm having is that the likedBy and mentions aren't being persisted correctly. The linker tables are being generated and the data gets inserted but I keep getting a duplicate entry error on the insert of a user. I believe I modeled the relationship correctly (unidirectional OneToMany), because I don't want an Account to keep track of Tweets it was mentioned in.

What I have tried:

Netbeans output of duplicate insert error:

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 '[email protected]' 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)

I believe this error occurs because of the folowing flow of my JPA imlementation:

  1. Account persisted
  2. Tweet persisted (because it is inside Account)
  3. Account persisted (because it is inside Tweet) <-- duplicate entry

What I expect:

If someone could help me with the annotations or explain what else I'm doing wrong that would be very much appreciated.

Ty in advance for any help.

Upvotes: 6

Views: 1251

Answers (1)

Teun van der Wijst
Teun van der Wijst

Reputation: 1009

I solved the problem, it turns out it was the annotations at the likes and mentions. @JoinTable(name = "") fixed it. I think not dropping the tables manually before redeploying caused that I did not see this as the solution at first.

for anyone with a similar problem, this is my solution:

@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<>();

Also, apearently if I restart my entire project (restart the entire glassfish/payara server) I get the duplicate entry error because the EntityManager tries to persist to the database before the tables have been dropped and recreated. So if I just undeploy and redeploy my project while keeping the payara server online, it persists just fine. I have not yet been able to find a solution to this problem but thats for another question.

Upvotes: 1

Related Questions