@Test public void shouldPersistEntityProxyEvenIfNotInWritableEmContext() { EntityManager readOnlyEm = newReadOnlyEntityManager(); EntityManager writeableEm = newEntityManager(); readOnlyEntityManagerDelegator.setDelegate(readOnlyEm); writeableEntityManagerDelegator.setDelegate(writeableEm); EntityWithLazySubentity entityWithLazy = new EntityWithLazySubentity(); entityWithLazy.setSubentity(new SimpleEntity()); writeableEm.getTransaction().begin(); readOnlyEm.joinTransaction(); EntityWithLazySubentity writtenEntity = entityWriter.write(entityWithLazy); writeableEm.getTransaction().commit(); readOnlyEm.clear(); writeableEm.clear(); writeableEm.getTransaction().begin(); readOnlyEm.joinTransaction(); writtenEntity = readOnlyEm.find(EntityWithLazySubentity.class, writtenEntity.getId()); assertThat(writtenEntity).isNotNull(); SimpleEntity proxy = writtenEntity.getSubentity(); assertThat(proxy).isNotNull(); SimpleEntity writeResult = entityWriter.write(proxy); assertThat(writeResult).isNotNull(); assertThat(writeResult instanceof HibernateProxy).isFalse(); }
@SuppressWarnings({"unchecked"}) public <T extends Identifiable<?>> T write(T entity) { if (readOnlyEm.contains(entity)) { readOnlyEm.detach(entity); } else if (entity.getId() != null) { Class<T> entityTargetClass = (Class<T>) getTargetClassIfProxied(entity.getClass()); readOnlyEm.detach(readOnlyEm.find(entityTargetClass, entity.getId())); } T writtenEntity = writeableEm.merge(entity); writeableEm.flush(); return (T) readOnlyEm.find(getTargetClassIfProxied(writtenEntity.getClass()), writtenEntity.getId()); }
EntityWriter { @SuppressWarnings({"unchecked"}) public <T extends Identifiable<?>> T write(T entity) { if (readOnlyEm.contains(entity)) { readOnlyEm.detach(entity); } else if (entity.getId() != null) { Class<T> entityTargetClass = (Class<T>) getTargetClassIfProxied(entity.getClass()); readOnlyEm.detach(readOnlyEm.find(entityTargetClass, entity.getId())); } T writtenEntity = writeableEm.merge(entity); writeableEm.flush(); return (T) readOnlyEm.find(getTargetClassIfProxied(writtenEntity.getClass()), writtenEntity.getId()); } }
EntityWriter { @SuppressWarnings({"unchecked"}) public <T extends Identifiable<?>> T write(T entity) { if (readOnlyEm.contains(entity)) { readOnlyEm.detach(entity); } else if (entity.getId() != null) { Class<T> entityTargetClass = (Class<T>) getTargetClassIfProxied(entity.getClass()); readOnlyEm.detach(readOnlyEm.find(entityTargetClass, entity.getId())); } T writtenEntity = writeableEm.merge(entity); writeableEm.flush(); return (T) readOnlyEm.find(getTargetClassIfProxied(writtenEntity.getClass()), writtenEntity.getId()); }  }
EntityWriter { @SuppressWarnings({"unchecked"}) public <T extends Identifiable<?>> T write(T entity) { if (readOnlyEm.contains(entity)) { readOnlyEm.detach(entity); } else if (entity.getId() != null) { Class<T> entityTargetClass = (Class<T>) getTargetClassIfProxied(entity.getClass()); readOnlyEm.detach(readOnlyEm.find(entityTargetClass, entity.getId())); } T writtenEntity = writeableEm.merge(entity); writeableEm.flush(); return (T) readOnlyEm.find(getTargetClassIfProxied(writtenEntity.getClass()), writtenEntity.getId()); }  @SuppressWarnings({"unchecked"}) /** * Stores changes made to an entity. All entites must have {@code DETACH} cascade enabled on all associations! * @param entity The entity to be written. * @return The written entity. */ T write(T entity); int executeUpdate(QueryCreator queryCreator); @SuppressWarnings({"unchecked"}) void delete(T entity); }
EntityWriter { @SuppressWarnings({"unchecked"}) public <T extends Identifiable<?>> T write(T entity) { if (readOnlyEm.contains(entity)) { readOnlyEm.detach(entity); } else if (entity.getId() != null) { Class<T> entityTargetClass = (Class<T>) getTargetClassIfProxied(entity.getClass()); readOnlyEm.detach(readOnlyEm.find(entityTargetClass, entity.getId())); } T writtenEntity = writeableEm.merge(entity); writeableEm.flush(); return (T) readOnlyEm.find(getTargetClassIfProxied(writtenEntity.getClass()), writtenEntity.getId()); }  @SuppressWarnings({"unchecked"}) /** * Stores changes made to an entity. All entites must have {@code DETACH} cascade enabled on all associations! * @param entity The entity to be written. * @return The written entity. */ T write(T entity); int executeUpdate(QueryCreator queryCreator); @SuppressWarnings({"unchecked"}) void delete(T entity);  }