0

私のアプリケーションには、次のエンティティがあります。

@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;
    }
}

なぜこれが発生するのか、データベース内のエントリの重複を回避する方法を教えていただければ幸いです。

よろしくお願いします、

ジェームス・トラン

4

1 に答える 1

0

私の推測では、 addLiker メソッドを次のように変更すると、

public void addLiker(String liker) {
    this.likers.size();
    this.likers.add(liker);
}

それはうまくいくでしょう。これが問題だったことを覚えていますが、修正されたと思いました。2.4 マイルストーン ビルドを試すことができますか。それ以外の場合は、バグを記録するか、既存のものを見つけて投票してください。

また、関係を EAGER にするか、エンティティで @ChangeTracking(DEFERRED) を使用して修正できるはずです。また、

public void addLiker(String liker) {
    if (!this.likers.contains(liker)) {
        this.likers.add(liker);
    }
}
于 2012-05-28T13:38:45.617 に答える