PostgreSQL データベースと通信する EclipseLink/JPA エンティティを含む Java EE アプリケーションがあります。すべてが正常に動作しているように見えましたが、最近、エンティティの奇妙な動作が増えていることに気付いたので、どの設定やコードが間違っているかを理解するためにあなたの助けが必要です...
主な問題が 1 つあります。Web アプリを使用してオブジェクトを削除すると、データベースでオブジェクトが適切に削除されることがありますが (表示されます)、アプリを更新すると、削除されたオブジェクトが突然再表示されます。 (アプリ内+データベース内に!)表示されるので、この背後に管理対象エンティティの問題があると思いますか?
たとえば、「分析」のリストを持つエンティティ「プロジェクト」があり、プロジェクトから分析を削除するときにこの問題が発生しました。最初に削除されますが(DBでも)、プロジェクトを再度開くと、分析が再び表示されます。
ここに私のクラスのプロジェクトがあります:
/**
* The persistent class for the projet database table.
*
*/
@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", nullable=false, length=50)
@OrderAttribute(lang=Language.BOTH)
@ShowParameter(position=10)
@IdentifierName(lang=Language.BOTH)
private String nomProjet;
@Column(name="projet_public", nullable=false)
private Boolean projetPublic;
//bi-directional many-to-one association to Analyse
@OneToMany(mappedBy="projet", cascade={CascadeType.ALL})//orphanRemoval=true,
private Set<Analyse> analyses;
//bi-directional many-to-one association to Utilisateur the creator of the project
@ManyToOne
@JoinColumn(name="id_utilisateur", nullable=false)
@ShowParameter(position=20)
private Utilisateur utilisateur;
//bi-directional many-to-one association to ProjetUtilDroit
@OneToMany(mappedBy="projet", cascade={CascadeType.ALL})
private Set<ProjetUtilDroit> projetUtilDroits;
public Projet() {
}
public Integer getIdProjet() {
return this.idProjet;
}
public void setIdProjet(Integer idProjet) {
this.idProjet = idProjet;
}
public String getNomProjet() {
return this.nomProjet;
}
public void setNomProjet(String nomProjet) {
this.nomProjet = nomProjet;
}
public Boolean getProjetPublic() {
return projetPublic;
}
public void setProjetPublic(Boolean projetPublic) {
this.projetPublic = projetPublic;
}
public Set<Analyse> getAnalyses() {
return this.analyses;
}
public void setAnalyses(Set<Analyse> analyses) {
this.analyses = analyses;
}
public Utilisateur getUtilisateur() {
return this.utilisateur;
}
public void setUtilisateur(Utilisateur utilisateur) {
this.utilisateur = utilisateur;
}
public Set<ProjetUtilDroit> getProjetUtilDroits() {
return this.projetUtilDroits;
}
public void setProjetUtilDroits(Set<ProjetUtilDroit> projetUtilDroits) {
this.projetUtilDroits = projetUtilDroits;
}
@Override
public boolean equals(Object o){
if(o instanceof Projet){
Projet project = (Projet) o;
return (project.idProjet == this.idProjet) || (project.nomProjet.equalsIgnoreCase(this.nomProjet));
}
return false;
}
}
これが私のクラスの分析です(フランス語で分析):
/**
* The persistent class for the analyz database table.
*
*/
@Entity
@Table(name="analyz")
public class Analyse implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id_analyse", unique=true, nullable=false)
private Integer idAnalyse;
@Column(name="nom_analyse", nullable=false, length=50)
@OrderAttribute(lang = Language.BOTH)
private String nomAnalyse;
//bi-directional many-to-one association to Projet
@ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH})
@JoinColumn(name="id_projet", nullable=false)
private Projet projet;
//bi-directional many-to-one association to Scenario
@OneToMany(mappedBy="analyse", cascade={CascadeType.ALL})//orphanRemoval=true,
private Set<Scenario> scenarios;
public Analyse() {
}
public Integer getIdAnalyse() {
return this.idAnalyse;
}
public void setIdAnalyse(Integer idAnalyse) {
this.idAnalyse = idAnalyse;
}
public String getNomAnalyse() {
return this.nomAnalyse;
}
public void setNomAnalyse(String nomAnalyse) {
this.nomAnalyse = nomAnalyse;
}
public Projet getProjet() {
return this.projet;
}
public void setProjet(Projet projet) {
this.projet = projet;
}
public Set<Scenario> getScenarios() {
return this.scenarios;
}
public void setScenarios(Set<Scenario> scenarios) {
this.scenarios = scenarios;
}
@Override
public boolean equals(Object o){
if(o instanceof Analyse){
Analyse a = (Analyse) o;
return (this.idAnalyse == a.idAnalyse) || (a.getProjet().equals(this.getProjet()) && (this.nomAnalyse.equalsIgnoreCase(a.nomAnalyse)));
}
return false;
}
}
そして、作成/更新/削除などのすべての従来の関数に対して汎用 DAO をコーディングしました。これが私のコードです:
public class BasicDAO<T extends Serializable> implements IDao<T> {
/** The entity class. */
private Class<T> entityClass;
/**
* The entity manager factory
*/
protected EntityManagerFactory emf;
/**
* Instantiates a new abstract dao.
*/
public BasicDAO(Class<T> c) {
entityClass = c;
}
/**
* Gets the emf.
*
* @return the emf
*/
public EntityManagerFactory getEmf() {
return emf;
}
/**
* Sets the emf.
*
* @param em the new emf
*/
public void setEmf(EntityManagerFactory emf) {
this.emf = emf;
}
public T findById(Integer id){
T result = null;
EntityManager em = emf.createEntityManager();
if (id == null || id < 1)
throw new PersistenceException("Id may not be null or negative");
result = em.find(entityClass, id);
em.refresh(result);
em.close();
return result;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public List<T> findAll(){
List<T> result = null;
EntityManager em = emf.createEntityManager();
CriteriaQuery<Object> cq = em.getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
result = (List)em.createQuery(cq).getResultList();
em.close();
return result;
}
public void create(T entity){
System.out.println("Create de AbstractDAO");
//First we check that the object is not alreadt in database
List<T> list = findAll();
if(list.contains(entity)){
return;
}
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
if(entity == null)
throw new PersistenceException("Entity to persist may not be null");//throw Persistence exception
em.persist(entity);
em.getTransaction().commit();
em.close();
}
public void delete(T entity){
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
if (entity == null)
throw new PersistenceException("Entity to delete may not be null");
em.remove(em.merge(entity));
em.getTransaction().commit();
em.close();
}
public T update(T entity){
T result = null;
if (entity == null){
System.out.println("Exception : entity to update may not be null");
throw new PersistenceException("Entity to update may not be null");
}
List<T> list = findAll();
int numberEquals = 0;
for(T elem : list){
if(elem.equals(entity))
numberEquals++;
}
if(numberEquals>1)
return null;
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.merge(entity);
result = entity;
em.getTransaction().commit();
em.close();
return result;
}
}
どんな助けや批評家も大歓迎です! :-)