0

リストを指すエンティティ (EntityObjectContainigList) を更新しようとしています。DB からエンティティをフェッチし、デタッチし、エンティティが指すリストからいくつかの要素を削除してから、更新されたエンティティを DB に存在するエンティティとマージしようとします。

ここでの問題は、 em.merge(EntityObjectContainigList) を実行すると、リストによって参照されているオブジェクト/エンティティ(削除したもの)がまだDBに残っていることです。

@Entity
public class EntityObjectContainigList {

    @Id
//    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;

    @OneToMany(mappedBy = "eocl", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
    List<ContainerObject> list = new ArrayList<ContainerObject>();

    private String name;


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }


    public List<ContainerObject> getList() {
        return list;
    }

    public void setList(List<ContainerObject> list) {
        this.list = new ArrayList<ContainerObject>(list);
    }


}

ContainerObject は次のようになります。

@Entity
public class ContainerObject {

     @Id
     @GeneratedValue(strategy=GenerationType.IDENTITY)
     @JsonIgnore
     private Key id;

    @ManyToOne(fetch = FetchType.LAZY)
    EntityObjectContainigList eocl;


    private String s;

    private int i;


    public String getS() {
            return s;
    }

    public void setS(String s) {
        this.s = s;
    }

    public int getI() {
        return i;
    }

    public void setI(int i) {
        this.i = i;
    }


}

サーブレットは次のようになります。

@Path("/db")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class MyResourcse {

    private static final EntityManagerFactory emf = Persistence.createEntityManagerFactory("transactions-optional");

    @PUT
    public Response putInDb(EntityObjectContainigList d) {
        EntityManager em = null;
        try {
            em = emf.createEntityManager();
/*          Gson g = new Gson();
            System.out.println(g.toJson(d));*/
            em.persist(d);
            return Response.ok().build();
        } finally {
            if (em != null && em.isOpen()) em.close();
        }
    }

    @GET
    public Response getFromDb(@QueryParam("id")Long id) {
        EntityManager em = null;
        try {
            em = emf.createEntityManager();
/*          Gson g = new Gson();*/
            EntityObjectContainigList o = em.find(EntityObjectContainigList.class, id);
/*          System.out.println(g.toJson(o));*/
            return Response.ok(o).build();
        } finally {
            if (em != null && em.isOpen()) em.close();
        }
    }

    @POST
    public Response updateDb(EntityObjectContainigList d) {
        EntityManager em = null;
        try {
            em = emf.createEntityManager();
            Gson g = new Gson();
            d =  em.merge(d);
            System.out.println(g.toJson(d));
            return Response.ok().build();
        } finally {
            if (em != null && em.isOpen()) em.close();
        }
    }
}

クライアント側は次のようになります。

public class UpdateClient {

    public static void main(String[] args) {
        ClientConfig cc = new DefaultClientConfig();
        cc.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);

        Client client = Client.create(cc);

        WebResource res = client.resource("http://localhost:8888/rest/db");


        EntityObjectContainigList o = new EntityObjectContainigList();
        o.setId(12L);
        o.setName("hello");

        for (int i = 0; i < 5; i++) {
            ContainerObject c = new ContainerObject();
            c.setI(i);
            c.setS("foo" + i );
            o.getList().add(c);
        }


        res.type(MediaType.APPLICATION_JSON).put(ClientResponse.class, o);

        System.out.println("Object inserted");

        o = res.queryParam("id", "12")
                .type(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON)
                .get(ClientResponse.class)
                .getEntity(EntityObjectContainigList.class);

        System.out.println("Object fetched");


        o.getList().remove(1);
        o.getList().remove(0);
        o.setName("world");


        res.type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).post(ClientResponse.class, o);
        System.out.println("Object updated");

        System.out.println("Done.");
    }

}

JPA 2.0でGAE 1.7.2を使用しています。

どんな助けでも大歓迎です。ヴィタリー

4

1 に答える 1

0

直し方:

削除する各要素に設定eoclしますnulllist

実際に間違っていること:

双方向の関係の両面、

  1. 所有側( が指す側mappedBy)と
  2. 裏面( のあるものmappedBy)。

データベースは所有側のみの値に基づいて変更されるため、等しくありません。あなたの場合、フィールドeoclContainerObject所有関係にあります。逆側 ( list) のみを変更するため、永続化するものはありません。変更を永続化するには、変更するeocl必要があります。そうしないとメモリ内のオブジェクト グラフに一貫性がなくなるため、両側を変更することをお勧めします。

JPA 2.0仕様では、これは次の言葉で伝えられています。

関係は、双方向または単方向の場合があります。双方向の関係には、所有側と逆 (非所有) 側の両方があります。一方向の関係には、所有側しかありません。セクション 3.2.4 で説明されているように、関係の所有側がデータベース内の関係の更新を決定します。
...
管理対象エンティティ間の双方向の関係は、関係の所有側が保持する参照に基づいて永続化されます。所有側で保持されているメモリ内参照と逆側で保持されているメモリ内参照が変更された場合に、これらの参照を互いに一致させることは、開発者の責任です。

于 2012-10-21T17:22:20.827 に答える