5

I have a customer which has an association to a customerBudget entity. A CustomerEntityListener will create a customerBudget entity.

I get the following error:

IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: de.company.entity.Customer-c4775b5b-413b-0567-3612-e0860bca9300 [new,managed].

the code in onAfterInsert(Customer entity)

    LoadContext<Customer> loadContext = LoadContext.create(Customer.class);
    loadContext.setId(entity.getId());
    Customer customer = dataManager.load(loadContext);

    CustomerBudget customerBudget = new CustomerBudget();
    customerBudget.setCustomer(customer);

    CommitContext commitContext = new CommitContext(customerBudget);
    dataManager.commit(commitContext);

How can I create and persist Entites in an EntityListener?

Matthias Hamann
  • 719
  • 8
  • 27

1 Answers1

5

You can implement BeforeInsertEntityListener interface and create a new entity in the current persistence context via EntityManager.

The listener may look as follows:

@Component("demo_CustomerEntityListener")
public class CustomerEntityListener implements BeforeInsertEntityListener<Customer> {

  @Inject
  private Metadata metadata;

  @Inject
  private Persistence persistence;

  @Override
  public void onBeforeInsert(Customer entity) {
    CustomerBudget customerBudget = metadata.create(CustomerBudget.class);
    customerBudget.setCustomer(entity);
    persistence.getEntityManager().persist(customerBudget);
  }
}

The new entity will be saved to the database on the transaction commit together with the Customer.

The Metadata.create() method is the preferred way to instantiate entities - for entities with integer identifiers it assigns an ID from a sequence; it also handles entity extension if needed.

Entity listeners work in the transaction that saves the entity, which allows you to make atomic changes in your data - everything will be either saved or discarded together with the entity the listener is invoked on.

Unlike EntityManager, DataManager always creates a new transaction. So you should use it in an entity listener only if you really want to load or save entities in a separate transaction. I'm not sure why you get this particular exception, but your code looks weird: you load an instance of Customer which is in the database instead of using the instance which is passed to the listener. When I tried to run your code on HSQLDB, the server went to infinite lock - the new transaction inside DataManager waits until the current transaction saving the Customer is committed.

knstvk
  • 627
  • 4
  • 7