Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Hibernate JavaEE6/EJB3/JPA2:如何将现有(但分离的)实体添加到manytone中的新实体?_Hibernate_Jpa 2.0_Ejb 3.0 - Fatal编程技术网

Hibernate JavaEE6/EJB3/JPA2:如何将现有(但分离的)实体添加到manytone中的新实体?

Hibernate JavaEE6/EJB3/JPA2:如何将现有(但分离的)实体添加到manytone中的新实体?,hibernate,jpa-2.0,ejb-3.0,Hibernate,Jpa 2.0,Ejb 3.0,我在将现有但分离的实体设置为多通关系时遇到问题,Hibernate抛出一个PersistentObjectException语句:“分离的实体传递给persist:model.persons.Customer” 我的用例如下所示: @Entity public class Order extends AbstractEntity implements Serializable { private static final long serialVersionUID = -8061887

我在将现有但分离的实体设置为多通关系时遇到问题,Hibernate抛出一个
PersistentObjectException
语句:“分离的实体传递给persist:model.persons.Customer”

我的用例如下所示:

@Entity
public class Order extends AbstractEntity implements Serializable {

    private static final long serialVersionUID = -8061887078955032972L;

    @ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH, CascadeType.PERSIST}, optional = false)
    private Customer customer = null;

    ... 
}

@Entity
@DiscriminatorValue("customer")
public class Customer extends Person implements Serializable {

    private static final long serialVersionUID = 2788107135840578322L;

    @OneToMany(cascade=CascadeType.ALL, mappedBy="customer")
    private List<Order> orders = null;

    ...
}
@Named
@ConversationScoped
public class OrderController implements Serializable {

    private static final long serialVersionUID = -4868506512979135651L;

    @EJB
    private OrderEJB orderBean;
    private Order order;
    ...
    public Order getOrder() {
        if (order == null) {
            if (id == null) {
                order = orderBean.create();
            } else {
                order = orderBean.findById(id);
            }
        }
        return order;
    }

    public String saveOrder() {
        order = orderBean.save(order);
        return "savedOrder";
    }
}

@Stateless
public class OrderEJB extends GenericDAO<Order> {
}

public class GenericDAO<T extends AbstractEntity> {

    public T create() {
        try {
            return getClassType().newInstance();
        } catch (Exception e) {
            logger.log(Level.SEVERE, "Error creating new instance of "+getClassType(), e);
        }
        return null;
    }

    public T save(T entity) {
        if (entity.getId() == null) {
            saveNew(entity);
        } else {
            entity = update(entity);
        }
        return entity;
    }

    private void saveNew(T entity) {
        em.persist(entity);
    }

    private T update(T entity) {
        return em.merge(entity);
    }

}
我打开了一个JSF2视图,该视图允许我通过命名bean和对无状态OrderDAO EJB的调用创建订单。在该视图中,我可以从下拉列表中选择客户。下拉列表使用另一个无状态CustomerDAO EJB填充,该EJB从数据库中获取客户列表。我选择了客户,客户被设置为订单。当我使用无状态OrderDAO EJB保存订单时,会引发上述异常

我的实体如下所示:

@Entity
public class Order extends AbstractEntity implements Serializable {

    private static final long serialVersionUID = -8061887078955032972L;

    @ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH, CascadeType.PERSIST}, optional = false)
    private Customer customer = null;

    ... 
}

@Entity
@DiscriminatorValue("customer")
public class Customer extends Person implements Serializable {

    private static final long serialVersionUID = 2788107135840578322L;

    @OneToMany(cascade=CascadeType.ALL, mappedBy="customer")
    private List<Order> orders = null;

    ...
}
@Named
@ConversationScoped
public class OrderController implements Serializable {

    private static final long serialVersionUID = -4868506512979135651L;

    @EJB
    private OrderEJB orderBean;
    private Order order;
    ...
    public Order getOrder() {
        if (order == null) {
            if (id == null) {
                order = orderBean.create();
            } else {
                order = orderBean.findById(id);
            }
        }
        return order;
    }

    public String saveOrder() {
        order = orderBean.save(order);
        return "savedOrder";
    }
}

@Stateless
public class OrderEJB extends GenericDAO<Order> {
}

public class GenericDAO<T extends AbstractEntity> {

    public T create() {
        try {
            return getClassType().newInstance();
        } catch (Exception e) {
            logger.log(Level.SEVERE, "Error creating new instance of "+getClassType(), e);
        }
        return null;
    }

    public T save(T entity) {
        if (entity.getId() == null) {
            saveNew(entity);
        } else {
            entity = update(entity);
        }
        return entity;
    }

    private void saveNew(T entity) {
        em.persist(entity);
    }

    private T update(T entity) {
        return em.merge(entity);
    }

}
@实体
公共类顺序扩展抽象实体实现可序列化{
私有静态最终长serialVersionUID=-8061887078955032972L;
@manytone(cascade={CascadeType.MERGE,CascadeType.REFRESH,CascadeType.PERSIST},可选=false)
私人客户=空;
... 
}
@实体
@鉴别器价值(“客户”)
公共类Customer extends Person实现可序列化{
私有静态最终长serialVersionUID=2788107135840578322L;
@OneToMany(cascade=CascadeType.ALL,mappedBy=“客户”)
私有列表顺序=空;
...
}
所涉及的代码如下所示:

@Entity
public class Order extends AbstractEntity implements Serializable {

    private static final long serialVersionUID = -8061887078955032972L;

    @ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH, CascadeType.PERSIST}, optional = false)
    private Customer customer = null;

    ... 
}

@Entity
@DiscriminatorValue("customer")
public class Customer extends Person implements Serializable {

    private static final long serialVersionUID = 2788107135840578322L;

    @OneToMany(cascade=CascadeType.ALL, mappedBy="customer")
    private List<Order> orders = null;

    ...
}
@Named
@ConversationScoped
public class OrderController implements Serializable {

    private static final long serialVersionUID = -4868506512979135651L;

    @EJB
    private OrderEJB orderBean;
    private Order order;
    ...
    public Order getOrder() {
        if (order == null) {
            if (id == null) {
                order = orderBean.create();
            } else {
                order = orderBean.findById(id);
            }
        }
        return order;
    }

    public String saveOrder() {
        order = orderBean.save(order);
        return "savedOrder";
    }
}

@Stateless
public class OrderEJB extends GenericDAO<Order> {
}

public class GenericDAO<T extends AbstractEntity> {

    public T create() {
        try {
            return getClassType().newInstance();
        } catch (Exception e) {
            logger.log(Level.SEVERE, "Error creating new instance of "+getClassType(), e);
        }
        return null;
    }

    public T save(T entity) {
        if (entity.getId() == null) {
            saveNew(entity);
        } else {
            entity = update(entity);
        }
        return entity;
    }

    private void saveNew(T entity) {
        em.persist(entity);
    }

    private T update(T entity) {
        return em.merge(entity);
    }

}
@Named
@会话范围
公共类OrderController实现可序列化{
私有静态最终长serialVersionUID=-4868506512979135651L;
@EJB
私有OrderEJB orderBean;
私人秩序;
...
公共秩序{
if(order==null){
if(id==null){
order=orderBean.create();
}否则{
order=orderBean.findById(id);
}
}
退货单;
}
公共字符串存储顺序(){
order=orderBean.save(订单);
返回“savedOrder”;
}
}
@无国籍
公共类OrderEJB扩展了GenericDAO{
}
公共类GenericDAO{
公共文件不能创建(){
试一试{
返回getClassType().newInstance();
}捕获(例外e){
logger.log(Level.severy,“创建“+getClassType(),e”的新实例时出错);
}
返回null;
}
公共T保存(T实体){
if(entity.getId()==null){
saveNew(实体);
}否则{
实体=更新(实体);
}
返回实体;
}
私有void saveNew(T实体){
em.persist(实体);
}
私有T更新(T实体){
返回em.merge(实体);
}
}

我使用两个不同的EJB,一个用于订单,另一个用于客户,这是一个问题吗

问题在于,您保存(持久化)一个新实体,其中引用了一个分离实体,该实体启用了cascade,以便在该关系上持久化(通过cascade all)

这是一个不受支持的组合

JPA希望此关系中的整个链都是新对象。如果已经有一个持久标识(附加或分离),它将无法工作

有两种解决方案:

删除从客户到订单关系的级联。客户仍将获得对现有订单的引用,但JPA不会尝试保留订单本身。您将失去一次性为新客户提供新订单的能力,但如果这种情况从未发生,那么这可能是一个很好的解决方案

第二种解决方案有点违反直觉,但确实有效;为具有现有订单的新客户调用em.merge()而不是em.persist()


Merge实际上具有“saveOrUpdate”语义,因此执行save时不考虑对象是否为新对象

当我阅读有关类似主题的整个互联网时:)这可能是完整状态EJB和PersistenceContextType.EXTENDED的一个用例吗?在GenericDAO中,创建时最好只传播/a异常,而不是返回null。将空值作为“失败值”而不是缺少数据的指示器返回是一种不好的做法(参见示例Clean Code)。不幸的是,我希望新客户和新订单也能一次性保留下来。是的,我已经试过合并了,而且效果很好。这让我思考为什么坚持存在:)@joysn好吧,为什么坚持存在?好问题。也许这是一个不错的新问题;)我认为这是为了验证图形中的所有对象都是新的,这样在添加时就不会意外地更新。奇怪的是,没有纯粹的更新方法,只更新而从不添加。