3

次のように、 @ManyToMany 関係を持つ User と Projects として2つのエンティティがあります。

エンティティ クラス

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column (name = "id")
    private int id;
    @Column (name = "email")
    private String email;
    @Column (name = "password")
        private String password;
    @Column (name = "last_login")
    private Date lastLogInDate; 
    @ManyToMany(fetch = FetchType.EAGER)
        @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
        @JoinTable(name = "project_assigned", joinColumns = { @JoinColumn(name = "fk_user_id")  }, inverseJoinColumns = { @JoinColumn(name = "fk_project_id") } )
    private Set<Projects> projects = new HashSet<Projects>(0);  

    // setter and getter methods.
}

@Entity
@Table(name = "projects")
public class Projects {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;
    @Column (name = "name")
    private String name;    
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "user_projects", joinColumns = { @JoinColumn(name = "fk_project_id") }, inverseJoinColumns = { @JoinColumn(name = "fk_user_id") })
    private Set<User> userSet = new HashSet<User>(0);   

}

DAO クラス

@Repository
public class UserDAO {

    public User findByCredentials(String email, String password) {
        String queryString = " from User u where u.email = ? and u.password = ?";
        Query query = sessionFactory.getCurrentSession().createQuery(queryString);
        query.setString(0, email);
        query.setString(1, password);       
        return (User) query.uniqueResult();     
    }

    public boolean updateUser(User user) {
        boolean result = true;
        Session session = null;
        try {
            session = sessionFactory.getCurrentSession();
            session.update(user);
        } catch (HibernateException e) {
            result = false;
            logger.error("Can not Update User"+e);
            e.printStackTrace();
        } 
        return result;
    }           
}

サービス クラス

@Service
@Transactional(readOnly = true,propagation=Propagation.SUPPORTS)
public class UserService {

    @Autowired
    private UserDAO userDAO;

    public User findByCredentials(String userName, String lastName) {
        return userDAO.findByCredentials(userName, lastName);   
    }

    @Transactional(readOnly = false,propagation=Propagation.REQUIRED)
    public boolean updateUser(User user) {
        return userDAO.updateUser(user);
    }
}

その他のコード

User user = userService.findByCredentials("xyz@pqr.com", "abc");
user.setLastLogInDate(new Date());
userService.updateUser(user);

私の問題は、ユーザーの 'LastLogInDate' を更新しているときに、そのユーザーに割り当てられたすべてのプロジェクト エンティティが更新されていることです (不要な更新ステートメントを発行する) ため、アプリケーションのパフォーマンスが低下します。どうすればこの問題を解決できますか。どうすればこれをより良い方法で行うことができますか。ご協力いただきありがとうございます。

ここに私のSQLログがあります

DEBUG org.hibernate.SQL#log  - update users set email=?, password=?, last_login=? where id=?
DEBUG org.hibernate.SQL#log  - update user_projects set name=? where id=?
DEBUG org.hibernate.SQL#log  - update user_projects set name=? where id=?
DEBUG org.hibernate.SQL#log  - update user_projects set name=? where id=?
DEBUG org.hibernate.SQL#log  - update user_projects set name=? where id=?
DEBUG org.hibernate.SQL#log  - update user_projects set name=? where id=?
4

2 に答える 2

2

カスケードは実行時 (保存) に設定できないため、カスケードを設定する必要があります。

@Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})

少なくとも を削除する必要がありますCascadeType.MERGE。MERGE は、「保存」に近い複雑なものを意味しますが、「この切り離されたエンティティを管理対象の状態に戻し、その状態の変更を保存する」に似ているためです。カスケードとは、関連付けられているすべてのエンティティが同じ方法でプッシュバックされ、.merge() から返されるマネージド エンティティ ハンドルにすべてのマネージド エンティティが関連付けられていることを意味します。

于 2013-07-25T23:17:15.097 に答える
-1

すべてのカスケード オプションを削除します。これで問題が解決します

1 ソリューション:

解決策 1:

ユーザークラス:

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "user_projects", joinColumns = { @JoinColumn(name = "fk_project_id") }, inverseJoinColumns = { @JoinColumn(name = "fk_user_id") })
private Set<Projects> projects;

プロジェクトクラス

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "user_projects", joinColumns = { @JoinColumn(name = "fk_project_id") }, inverseJoinColumns = { @JoinColumn(name = "fk_user_id") })
private Set<User> userSet; 
于 2014-01-20T18:27:16.093 に答える