JPA (EclipseLink) と Spring フレームワークを使用した Java EE アプリケーションがあります。
Spring トランザクション管理を追加するまで、永続化クラスではすべてが正常に機能していました。次のエンティティがあります(データベーステーブルに対応):
計画
@Entity @Table(name="projet") public class Projet implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="id_projet", unique=true, nullable=false) private Integer idProjet; @Column(name="nom_projet") private String nomProjet; /** The projet util droits. */ @OneToMany(mappedBy="projet", cascade={CascadeType.ALL}) private Set<ProjetUtilDroit> projetUtilDroits; public Projet() { } ... }
ユーザー
@Entity @Table(name="utilisateur") public class Utilisateur implements Serializable { /** The Constant serialVersionUID. */ private static final long serialVersionUID = 1L; /** The id utilisateur. */ @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="id_utilisateur", unique=true, nullable=false) private Integer idUtilisateur; /** The nom utilisateur. */ @Column(name="nom_utilisateur", nullable=false, length=50) private String nomUtilisateur; //bi-directional many-to-one association to ProjetUtilDroit /** The projet util droits. */ @OneToMany(mappedBy="utilisateur", cascade={CascadeType.REMOVE}) private Set<ProjetUtilDroit> projetUtilDroits; ... }
右
@Entity @Table(name="droit") public class Droit implements Serializable { /** The Constant serialVersionUID. */ private static final long serialVersionUID = 1L; /** The id droit. */ @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="id_droit", unique=true, nullable=false) private Integer idDroit; /** The type droit. */ @Column(name="type_droit", nullable=false, length=10) private String typeDroit; /** * Instantiates a new droit. */ public Droit() { } ... }
そして、ユーザーを特定の権限を持つプロジェクトにリンクする関連付け (ProjectUserRight)
@Entity @Table(name="projet_util_droit") public class ProjetUtilDroit implements Serializable { /** The Constant serialVersionUID. */ private static final long serialVersionUID = 1L; /** The id. */ @EmbeddedId private ProjetUtilDroitPK id; //bi-directional many-to-one association to Droit /** The droit. */ @ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH}) @JoinColumn(name="id_droit") private Droit droit; //bi-directional many-to-one association to Projet /** The projet. */ @MapsId("idProjet") @ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH}) @JoinColumn(name="id_projet") private Projet projet; //bi-directional many-to-one association to Utilisateur /** The utilisateur. */ @MapsId("idUtilisateur") @ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH}) @JoinColumn(name="id_utilisateur") private Utilisateur utilisateur; ... }
関連付けの埋め込み ID:
@Embeddable public class ProjetUtilDroitPK implements Serializable { //default serial version id, required for serializable classes. /** The Constant serialVersionUID. */ private static final long serialVersionUID = 1L; /** The id projet. */ @Column(name="id_projet", unique=true, nullable=false) private Integer idProjet; /** The id utilisateur. */ @Column(name="id_utilisateur", unique=true, nullable=false) private Integer idUtilisateur; ... }
その権利でプロジェクトを作成する私の方法:
public Projet createProject(String name, int idRight, int idUser) {
Projet project = new Projet();
project.setNomProjet(name);
ProjetUtilDroit pud = new ProjetUtilDroit();
Droit d = rightDao.findById(idRight);
pud.setDroit(d);
pud.setProjet(project);
Utilisateur user = userDao.findById(idUser);
pud.setUtilisateur(user);
if(user.getProjetUtilDroits() == null)
user.setProjetUtilDroits(new HashSet<ProjetUtilDroit>());
user.getProjetUtilDroits().add(pud);
Set<ProjetUtilDroit> pudSet = new HashSet<ProjetUtilDroit>();
pudSet.add(pud);
project.setProjetUtilDroits(pudSet);
project = projectDao.create(project);
return project;
}
「createProject」メソッドの上に注釈@Transactionnalを追加するまで、それは魅力のように機能しました(プロジェクトと関連するユーザー権限を保持します)...
今、私はこのエラーを受け取ります: Avertissement: StandardWrapperValve[dispatcher]: PWC1406: Servlet.service() for servlet dispatcher throwed exception java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not Marked cascade PERSIST: * * ***プロジェクトの権利* *** ユーザー名: userName 右: 読み取り。org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.discoverUnregisteredNewObjects(RepeatableWriteUnitOfWork.java:304) で org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.calculateChanges(UnitOfWorkImpl.java:702) で org.eclipse.persistence.internal org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:780) の .sessions.RepeatableWriteUnitOfWork.writeChanges(RepeatableWriteUnitOfWork.java:433) org.eclipse.persistence.internal.jpa.EJBQueryImpl.performPreQueryFlush(EJBQueryImpl) .java:1298) で org.eclipse.persistence.internal.jpa.EJBQueryImpl.executeReadQuery(EJBQueryImpl.java:434) で org.eclipse.persistence.internal.jpa.EJBQueryImpl.getResultList(EJBQueryImpl.java:742) で com. com.dao の dao.BasicDAO.findAll(BasicDAO.java:92)。
私が想像する唯一の解決策は、1 つのトランザクション内でプロジェクトを作成し、別のトランザクション内でその権利を個別に保存することです。それが唯一の解決策ですか、それとも別の提案がありますか?