0

JPA/EclipseLink を 1 年間使用してきましたが、1 対多の関係でエンティティを追加するときに管理エンティティを更新する方法を理解するのにまだ問題があります。

たとえば、私のアプリケーションには、内部にいくつかの分析があるプロジェクトがあります。プロジェクトが最初に作成され、ユーザーは内部に分析を追加できます (1 つずつ)。私の問題は、分析が適切に管理され、プロジェクトが更新されるように、新しい分析を永続化する適切な方法 (およびプロジェクトから分析を削除するための同じ質問) は何ですか?

プロジェクトクラスは次のとおりです。

@Entity
@Table(name="project")
public class Project implements Serializable {


/** The Constant serialVersionUID. */
private static final long serialVersionUID = 1L;

/** The id project. */
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id_project", unique=true, nullable=false)
private Integer idProject;

/** The project name. */
@Column(name="project_name", nullable=false, length=50)
private String projectName;

//bi-directional many-to-one association to Analysis
/** The analysis. */
@OneToMany(mappedBy="project", cascade={CascadeType.ALL})
private Set<Analysis> analysis;

    ... other stuff
}

分析クラス:

@Entity
@Table(name="analyz")
public class Analysis implements Serializable{

/** The Constant serialVersionUID. */
private static final long serialVersionUID = 1L;

/** The id analysis. */
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id_analysis", unique=true, nullable=false)
private Integer idAnalysis;

/** The analysis name. */
@Column(name="analysis_name", nullable=false, length=50)
private String analysisName;

//bi-directional many-to-one association to Project
/** The project. */
@ManyToOne
@JoinColumn(name="id_project", nullable=false)
private Project project;

   ... other stuff
}

新しい分析を作成するために使用する関数:

public void createAnalysis(String name, int projectId) {

    Project project = daoProject.findById(projectId);

    Analysis analysis = new Analysis();
    analysis.setProject(project);

    analysis.setNameAnalysis(name);
    project.getAnalysis().add(analysis);
    daoProject.update(project);// I also tried daoAnalysis.create(analysis)
}

プロジェクトを更新すると、プロジェクト オブジェクトは新しい分析で最新になりますが、分析オブジェクトには ID がありません... 分析を単独で永続化すると、後でプロジェクト オブジェクトを取得するときに、その ID を使用して、私はそれに関する更新を取得せず、新しい分析はプロジェクトにありません。

分析を削除する場合と同じ問題: プロジェクトを更新するか、分析だけを削除する必要がありますか (「daoAnalysis.delete(analysis)」を使用)。

すべての要素を提供するために、ここに私の汎用 DAO を示します (daoProject と daoAnalysis はそのインスタンスです)。

 public class BasicDAO<T extends Serializable> implements IDao<T> {

/** The class of the entity to be manipulated. */
private Class<T> entityClass;

/** The entity manager factory. */
protected EntityManagerFactory emf;

/**
 * Instantiates a new abstract dao.
 *
 * @param c the class
 */
public BasicDAO(Class<T> c) {
    entityClass = c;
}

/**
 * Gets the emf.
 *
 * @return the emf
 */
public EntityManagerFactory getEmf() {
    return emf;
}

/**
 * Sets the emf.
 *
 * @param emf 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.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

2 に答える 2

2

あなたの更新方法はプロジェクトのマージを使用していると思います。Merge はオブジェクトを取得し、変更がマージされたマネージド インスタンスを返します。オブジェクトが新しい場合、データを反映するために新しいマネージド インスタンスが作成されます。これが、解析のバージョンに ID が設定されていない理由である可能性があります。渡されたものではなく、マージ プロセスで返されたマネージド インスタンスを使用する必要があります。

Persist は新しい分析で直接使用できますが、プロジェクトに加えられた変更をマージしてキャッシュに表示する必要があります。したがって、分析を永続化してからプロジェクトをマージします。コードは増えますが、プロバイダーはマージ呼び出しで分析が既に存在するかどうかを確認する必要がないため、より効率的です。Persist はインスタンスをマネージド エンティティに渡すため、ID が設定されます。

于 2013-05-23T11:44:23.293 に答える
0

1 対多の関連付けエンティティを更新する際に問題が発生した場合は、次の 3 つの手順に注意してください。

  1. リストで言及cascade = CascadeType.ALL,orphanRemoval = true、例:@OneToMany

    @OneToMany(mappedBy = "parentEntity",cascade = CascadeType.ALL,orphanRemoval = true)
    private List< ChildEntity > childEntityList;
    
  2. 常に多くの側 (子エンティティのリストがリストされている親エンティティ) から更新を実行します。

  3. getEntityManager().getEntityManagerFactory().getCache().evict(Class)更新ごとに呼び出してキャッシュをクリアします。

于 2015-11-10T17:10:01.693 に答える