一对多实体与JPA/EclipseLink的关系已过时

一对多实体与JPA/EclipseLink的关系已过时,jpa,persistence,eclipselink,one-to-many,Jpa,Persistence,Eclipselink,One To Many,我已经与JPA/EclipseLink合作一年了,但我仍然无法理解在一对多关系中添加实体时,它如何更新托管实体 例如,在我的应用程序中,我有一些项目,其中包含多个分析。首先创建项目,然后用户可以在其中添加分析(一个接一个)。我的问题是:什么是保存新分析(以及从项目中删除一个分析的相同问题)的正确方法,以便更好地管理分析并更新项目? 以下是项目类: @Entity @Table(name="project") public class Project implements Serializable

我已经与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
}
我用于创建新分析的函数:

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检索项目对象时,我不会得到它的更新,并且新的分析不在项目中

删除分析也有同样的问题:我应该更新项目还是单独删除分析(使用“daoalysis.delete(analysis)”

为了给出所有元素,这里是我的通用DAO(daoProject和DAOPanalysis是它的实例):

公共类基本DAO实现IDao{
/**要操纵的实体的类*/
私有类实体类;
/**实体管理器工厂*/
受保护的实体管理器工厂emf;
/**
*实例化一个新的抽象dao。
*
*@param c类
*/
公共基础设施(c类){
entityClass=c;
}
/**
*获取emf。
*
*@返回emf
*/
公共实体管理器工厂getEmf(){
返回电动势;
}
/**
*设置emf。
*
*@param emf新的emf
*/
public void setEmf(EntityManagerFactory emf){
this.emf=emf;
}
公共T findById(整数id){
T结果=null;
EntityManager em=emf.createEntityManager();
if(id==null | | id<1)
抛出新的PersistenceException(“Id不能为null或负值”);
结果=em.find(entityClass,id);
em.close();
返回结果;
}
公共无效创建(T实体){
System.out.println(“创建抽象DAO”);
//首先,我们检查对象是否不在数据库中
List=findAll();
if(列表包含(实体)){
返回;
}
EntityManager em=emf.createEntityManager();
em.getTransaction().begin();
if(实体==null)
抛出新的PersistenceException(“要持久化的实体可能不为null”);//抛出持久化异常
em.persist(实体);
em.getTransaction().commit();
em.close();
}
公共作废删除(T实体){
EntityManager em=emf.createEntityManager();
em.getTransaction().begin();
if(实体==null)
抛出新的PersistenceException(“要删除的实体可能不为空”);
em.remove(em.merge(entity));
em.getTransaction().commit();
em.close();
}
公共T更新(T实体){
T结果=null;
if(实体==null){
System.out.println(“异常:要更新的实体不能为空”);
抛出新的PersistenceException(“要更新的实体可能不为空”);
}
List=findAll();
int numberquals=0;
对于(T元素:列表){
if(元素等于(实体))
numberquals++;
}
如果(numberquals>1)
返回null;
EntityManager em=emf.createEntityManager();
em.getTransaction().begin();
合并(实体);
结果=实体;
em.getTransaction().commit();
em.close();
返回结果;
}

提前感谢您的建议!

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


Persist可以直接用于新的分析,但您仍然需要合并对project所做的任何更改,以便它们显示在缓存中。因此,您可以将分析持久化,然后合并project。更多代码,但由于提供程序不需要检查合并调用中是否已存在分析,因此它可能更有效。Persist会使在托管实体中传递状态,因此它将设置ID。

如果您在更新一对多关系实体时遇到困难,请记住以下3个步骤:

  • @OneToMany
    列表中提及
    cascade=CascadeType.ALL,orphanRemoving=true
    ,示例:

    @OneToMany(mappedBy = "parentEntity",cascade = CascadeType.ALL,orphanRemoval = true)
    private List< ChildEntity > childEntityList;
    
    @OneToMany(mappedBy=“parentEntity”,cascade=CascadeType.ALL,orphanRemoving=true)
    私有列表childEntityList;
    
  • 始终从多个方面执行更新(列出子实体列表的父实体)

  • 在每次更新后调用
    getEntityManager().getEntityManagerFactory().getCache().Recit(类)
    以清除缓存

  •  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;
    }
    
    @OneToMany(mappedBy = "parentEntity",cascade = CascadeType.ALL,orphanRemoval = true)
    private List< ChildEntity > childEntityList;