Reputation: 1009
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:
@JoinColumn
for both likes
and mentions
(results in duplicate insert)@JoinTable
for both likes
and mentions
(results in duplicate insert)@OneToMany
for both likes
and mentions
(this does not result in an error but creates 1 linker table for both relationships where either cannot be null)@OneToMany
for likes
and then @joinColumn
for mentions
where nullable = true
(this results in the scenario where u cannot be mentioned in a tweet unless you like it, which is odd behaviour)@OneToMany(cascade = CascadeType.MERGE)
(results in duplicate insert)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:
What I expect:
tweet_id (fk)
and an account_id (fk)
representing likestweet_id (fk)
and an account_id (fk)
representing mentionsIf 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
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