当前位置: 首页 > 面试题库 >

错误:传递了分离的实体以保留-尝试保留复杂数据(Play-Framework)

白丁雨
2023-03-14
问题内容

我在通过播放框架持久保存数据时遇到问题。也许不可能达到这个结果,但是如果可行的话,那将是非常好的。

简单 :我有一个复杂的模型(带地址的商店),我想立即更改带地址的商店,并以相同的方式存储它们(shop.save())。但是detached entity passed to persist会发生错误。

宇date历史 05.11

  • 05.11

    • 使用属性更新模型商店 mappedBy="shop"
    • 更新指向Google用户组的链接
    • 09.11

    • 找到一种解决方法,但这是通用的

    • 16.11

    • 更新示例html表单,感谢@Pavel

    • 感谢@ mericano1,将变通方法(更新09.11)更新为通用方法
    • 21.11
    • 我放弃尝试寻找解决方案,等待播放2.0 …

Dateil :我尝试将问题减少到最低程度:
Model

@Entity
public class Shop extends Model {

    @Required(message = "Shopname is required")
    public String shopname;

    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER, mappedBy="shop")
    public List<Address> addresses;

}






@Entity
public class Address extends Model {

    @Required
    public String location;

    @ManyToOne
    public Shop shop;
}

现在我的 Frontendcode

#{extends 'main.html' /}

#{form @save(shop?.id)}

    <input type="hidden" name="shop.id" value="${shop?.id}"/>

    #{field 'shop.shopname'}
        <label for="shopName">Shop name:</label>
        <input type="text" name="${field.name}" 
            value="${shop?.shopname}" class="${field.errorClass}" />
    #{/field}

    <legend>Addressen</legend>
    #{list items: shop.addresses, as: "address"}
        <input type="hidden" name="shop.addresses[${address_index - 1}].id" value="${address.id}"/>
        <label>Location</label>
        <input name="shop.addresses[${address_index - 1}].location" type="text" value="${address.location}"/>
    #{/list}

     <input type="submit" class="btn primary" value="Save changes" />
#{/form}

我只有商店本身的ID和商店名称,可以通过POST传递,例如: ?shop.shopname=foo

有趣的是地址列表,在那里我有Id和地址中的位置,结果将是somthin,如:?shop.shopname=foo&shop.addresses[0].id=1&shop.addresses[0].location=bar

现在, 控制器 部分用于数据:

public class Shops extends CRUD {

public static void form(Long id) {

    if (id != null) {
        Shop shop = Shop.findById(id);
        render(shop);
    }
    render();
}

public static void save(Long id, Shop shop) {

    // set owner manually (dont edit from FE)
    User user = User.find("byEmail", Security.connected()).first();
    shop.owner = user;

    // Validate
    validation.valid(shop);
    if (validation.hasErrors()) 
        render("@form", shop);

    shop.save();
    index();
}

现在的 问题是
:当我更改地址数据时,代码到达shop.save();对象商店,里面充满了所有数据,并且一切看起来都很好,但是当hibernate尝试持久化数据时,detached entity passed to persist就会发生错误:(

我尝试更改获取模式,级联类型,并且还尝试了以下操作:

Shop shop1 = shop.merge();
shop1.save();

不幸的是,没有任何结果,或者发生了错误,或者没有地址数据将被存储。有没有办法以这种方式存储数据?

如果有不清楚的地方,请给我写信,我很乐意提供尽可能多的信息。

更新1 我也把问题放在谷歌用户组上

更新2 + 3 在用户组的帮助下(感谢bryan w。)和mericano1的回答,我在这里找到了通用的解决方法。

首先,您必须cascade=CascadeType.ALLaddressesshop.class的属性中删除。然后,您必须save在shops.class中更改方法。

public static void save(Long id, Shop shop) {

    // set owner manually (dont edit from FE)
    User user = User.find("byEmail", Security.connected()).first();
    shop.owner = user;

    // store complex data within shop
    storeData(shop.addresses, "shop.addresses");
    storeData(shop.links, "shop.links");

    // Validate
    validation.valid(shop);
    if (validation.hasErrors()) 
        render("@form", shop);

    shop.save();
    index();
}

存储数据的通用方法如下所示:

private static <T extends Model> void  storeData(List<T> list, String parameterName) {
    for(int i=0; i<list.size(); i++) {
        T relation = list.get(i);

        if (relation == null)
            continue;

        if (relation.id != null) {
            relation = (T)Model.Manager.factoryFor(relation.getClass()).findById(relation.id);
            StringBuffer buf = new StringBuffer(parameterName);
            buf.append('[').append(i).append(']');
            Binder.bind(relation, buf.toString(), request.params.all());
        }

        // try to set bidiritional relation (you need an interface or smth)
        //relation.shop = shop;
        relation.save();
    }
}

我在Shop.class中html" target="_blank">添加了 Links 列表,但是我不会更新其他代码段,因此如果发生编译错误,请注意。


问题答案:

当您在Hibernate中更新复杂实例时,您需要确保它来自数据库(首先获取它,然后更新同一实例),以避免出现“分离实例”问题。

通常,我通常总是先获取,然后仅更新期望从UI中获得的特定字段。

您可以使用以下代码使代码更通用

(T)Model.Manager.factoryFor(relation.getClass()).findById(relation.id);


 类似资料:
  • 问题内容: 我有一个JPA持久对象模型,其中包含多对一关系:一个具有许多。A 有一个。 这是一段代码: 我能够创建一个对象,向其中添加事务,并正确地持久保存该对象。但是,当我 使用现有的已经持久化的Account 创建一个事务并持久化 该Transaction时 ,出现一个异常: 引起原因:org.hibernate.PersistentObjectException:传递给持久对象的分离实体:c

  • 问题内容: 提交表单时出现此错误: org.hibernate.PersistentObjectException:分离的实体传递给持久化:com.project.pmet.model.Account; 嵌套异常是javax.persistence.PersistenceException:org.hibernate.PersistentObjectException:传递给持久对象的分离实体:c

  • 问题内容: 我有2个实体:和。 。 问题出在我从数据库中获取accountRole并尝试保留我的。 至此,我刚刚创建了我的帐户,并且角色已经存在于db中。 仍然出现错误。 问题答案: 只需更换 与: 并允许合并级联: 因为合并会这样做: 如果您的实体是新实体,则与persist()相同。但是,如果您的实体已经存在,它将对其进行更新。

  • 我在提交表单时遇到以下错误: org.hibernate.PersistentObjectException:传递给Persisted的分离实体:com.project.pmet.model.Account;嵌套异常为javax.persistence.persistenceException:org.hibernate.persistentObjectException:传递到persist的分

  • 问题内容: 我的应用程序的Web UI层中有一个JPA实体实例。我想随时知道此实体是否已经保存在数据库中或仅存在于用户会话中。 它将在业务层中,我将使用entitymanager.contains(Entity)方法,但是在我的UI层中,我认为我需要一个额外的属性来指示实体是否已保存。如何实施?我目前正在考虑以下选择: 由数据库设置默认值的JPA属性,但是每次更新后是否会强制进行新的读取? 在我的

  • 问题内容: 我和之间有关系 所以当我尝试持久化对象时 我懂了 如您所见,它尝试插入正确的值,但是以某种方式将其标记为语法错误。我认为它缺少左右的单引号,但是由于它是在后台进行查询的,所以我不知道如何解决它。请注意,我对同一项目中的其他实体执行了完全相同的操作,并且工作正常。太沮丧了!! 问题答案: GROUP确实是保留的关键字,您必须对其进行转义。在JPA 2.0中,有一种标准化的方法来指定分隔标