私のアプリケーションには、次のエンティティがあります。
@Entity
public class Commentable implements Serializable {
...
@ElementCollection(targetClass = String.class)
protected Set<String> likers = new HashSet<String>();
...
}
ユーザーが「いいね」ボタンをクリックするたびに、ユーザー名を上記に追加してSet
、同じ投稿が2回好きにならないようにします。しかし、データベースを見ると、同じユーザー名が何度も表示されているのがわかりました。
と呼んlikers.size()
でも、からユニークないいねの数を取得できますSet
。それでも、次のクエリは常に大きな数値を返します。
Query q1 = em.createQuery("SELECT COUNT(L) FROM Commentable C JOIN C.likers L WHERE C.id = :id");
q1.setParameter("id", commentableID);
long numberOfLikes = (Long) q1.getSingleResult();
System.out.println("HERE " + numberOfLikes);
データベースには、次のようなエントリが含まれています。
# | Commentable_ID | LIKERS
1 | 1801 | Mr.James
2 | 1801 | Mr.James
3 | 1801 | Mr.James
更新1:
JMelnikによって提案されたように、私は一意の制約を設定しようとしました。
@Entity
public class Commentable implements Serializable {
...
@ElementCollection(targetClass = String.class)
@Column(unique=true)
protected Set<String> likers = new HashSet<String>();
public void addLiker(String liker) {
this.likers.add(liker);
}
...
}
「いいね」ボタンを2回クリックすると、GlassFishは次の例外をスローしました。
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'jamesboyz' for key 'LIKERS'
Error Code: 1062
Call: INSERT INTO Commentable_LIKERS (Commentable_ID, LIKERS) VALUES (?, ?)
bind => [2 parameters bound]
Query: DataModifyQuery(sql="INSERT INTO Commentable_LIKERS (Commentable_ID, LIKERS) VALUES (?, ?)")
...
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'jamesboyz' for key 'LIKERS'
更新2:
私SessionBean
の1つでは、いいねを記録するために次の方法があります。
@Override
public int like(long commentableID, String liker) {
Commentable c = em.find(Commentable.class, commentableID);
if (c == null) return STATUS_NOT_FOUND;
else {
c.addLiker(liker);
return STATUS_SUCCESSFUL;
}
}
なぜこれが発生するのか、データベース内のエントリの重複を回避する方法を教えていただければ幸いです。
よろしくお願いします、
ジェームス・トラン