I am clustering tweets based on a search from Twitter and trying to store the results in a database using Hibernate in Java. When I try to save the SearchResults object, I get an error like the following:
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session
What do I need to do so that both the TweetCluster.java and the SearchResults.java can point to the same table of Tweets in the database? I could change TweetCluster.java so it points to a separate table which stores the tweets again, but that seems like a waste of space.
I’ve pulled out the important code as shown below.
@Entity
@Table(name="search_results")
public class SearchResults {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long searchId;
@ManyToMany(targetEntity = Tweet.class, cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@OrderColumn(name="orderIndex")
private List<Tweet> tweets;
@OneToMany(targetEntity = TweetCluster.class, cascade=CascadeType.ALL, fetch=FetchType.EAGER, orphanRemoval=true)
@OrderColumn(name="orderIndex")
private List<TweetCluster> clusters;
public SearchResults() {
tweets = new ArrayList<Tweet>();
clusters = new ArrayList<TweetCluster>();
}
public List<Tweet> getTweets() {
return tweets;
}
public void addTweet(Tweet tweet){
tweets.add(tweet);
}
public void addCluster(TweetCluster cluster){
clusters.add(cluster);
}
public List<TweetCluster> getClusters() {
return clusters;
}
}
@Entity
@Table(name="tweet_cluster")
public class TweetCluster {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
private String name;
@ManyToMany(targetEntity = Tweet.class, fetch=FetchType.EAGER)
@OrderColumn(name="orderIndex")
private List<Tweet> tweets;
public TweetCluster(){
tweets = new ArrayList<Tweet>();
}
public TweetCluster(String name){
this();
this.name=name;
}
public long getId(){
return id;
}
public void setId(long id){
this.id = id;
}
public List<Tweet> getTweets() {
return tweets;
}
public void addTweet(Tweet tweet){
tweets.add(tweet);
}
}
@Entity
@Table(name="tweet")
public class Tweet {
@Id
@GenericGenerator(name="assigned", strategy = "assigned")
private long tweetId;
private String text;
public Tweet(){
}
public long getTweetId() {
return tweetId;
}
public void setTweetId(long id){
this.tweetId = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
EDIT:
To save the results, I run code something like the following:
SearchResults searchResult = new SearchResults();
searchResult .addCluster(new TweetCluster("cluster1"));
searchResult .addCluster(new TweetCluster("cluster2"));
searchResult.addTweet(new Tweet("Tweet 1"));
searchResult.addTweet(new Tweet("Tweet 2"));
searchResult.addTweet(new Tweet("Tweet 3"));
session.saveOrUpdate(searchResult);
The exception gets thrown at saveOrUpdate
It turns out the problem was really simple. The generator for Tweet is assigned. In my unit test I forgot to assign an id. Thus several tweets had an id of zero.