I’m trying to Update an Entity (EntityObjectContainigList) that points to a list. I fetch the Entity from the DB, detach it, remove some elements from the list that the Entity points to and then try to merge the updated Entity with the one residing in the DB.
Now the problem is that when I run em.merge(EntityObjectContainigList) the Objects/Entitys that where referenced by the list (the ones that I removed) are still stay in 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);
}
}
the ContainerObject looks like that:
@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;
}
}
the servlet looks like that:
@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();
}
}
}
Client side looks like that:
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.");
}
}
I’m using GAE 1.7.2 with JPA 2.0.
Any help is much appreciated.
Vitaly
How to fix:
Set
eocltonullfor each element to be removed fromlistWhat is actually wrong:
Two sides of bidirectional relationship,
mappedBy) andmappedBy).are not equal, because database is modified based to the values in owning side only. In your case Field
eoclinContainerObjectowns relationship. Because you modify only inverse side (list), there is nothing to persist. To persist changes,eoclshould be modified. It is recommended to modify both sides, because otherwise object graph in memory is inconsistent.In JPA 2.0 specification this is told with following words: