0

我已经使用 JPA/EclipseLink 一年了,但是当您在一对多关系中添加实体时,我仍然无法理解它如何更新托管实体。

例如,在我的应用程序中,我的项目里面有几个分析。首先创建项目,然后用户可以在里面添加分析(一个一个)。我的问题是:坚持新分析的正确方法是什么(以及从项目中删除分析的相同问题)以便分析得到妥善管理并更新项目?

这是项目类:

@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(分析)”)?

为了给出所有元素,这是我的通用 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

我假设您的更新方法在项目上使用合并。合并获取对象并返回包含更改的托管实例。如果对象是新的,它将创建一个新的托管实例以反映数据 - 这可能是您的分析版本没有设置其 ID 的原因。您需要使用合并过程中返回的托管实例而不是传入的实例。

Persist 可以直接用于新的分析,但您仍然需要合并对项目所做的任何更改,以便它们显示在缓存中。所以你会坚持分析,然后合并项目。更多代码,但它可以更有效,因为提供者不需要检查合并调用中是否已经存在分析。Persist 使实例在托管实体中传递,因此它将设置 ID。

于 2013-05-23T11:44:23.293 回答
0

如果您在更新一对多关系实体时遇到困难,请记住以下 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 回答