3

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

}

どんな助けや批評家も大歓迎です! :-)

4

0 に答える 0