mirror of
https://gitee.com/jmix/cuba.git
synced 2024-12-02 11:17:40 +08:00
EntityLog throws NPE when creating new BaseIntIdentityIdEntity #1131
This commit is contained in:
parent
33f3b33a6a
commit
1343982c43
@ -38,6 +38,8 @@ import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.GuardedBy;
|
||||
@ -112,7 +114,9 @@ public class EntityLog implements EntityLogAPI {
|
||||
|
||||
for (EntityLogItem item : items) {
|
||||
List<EntityLogItem> sameEntityList = items.stream()
|
||||
.filter(entityLogItem -> entityLogItem.getObjectEntityId().equals(item.getObjectEntityId()))
|
||||
.filter(entityLogItem -> entityLogItem.getDbGeneratedIdEntity() != null ?
|
||||
entityLogItem.getDbGeneratedIdEntity().equals(item.getDbGeneratedIdEntity()) :
|
||||
entityLogItem.getObjectEntityId().equals(item.getObjectEntityId()))
|
||||
.collect(Collectors.toList());
|
||||
EntityLogItem itemToSave = sameEntityList.get(0);
|
||||
computeChanges(itemToSave, sameEntityList);
|
||||
@ -192,16 +196,31 @@ public class EntityLog implements EntityLogAPI {
|
||||
|
||||
protected void saveItem(EntityLogItem item) {
|
||||
String storeName = metadataTools.getStoreName(metadata.getClassNN(item.getEntity()));
|
||||
if (Stores.isMain(storeName)) {
|
||||
EntityManager em = persistence.getEntityManager();
|
||||
em.persist(item);
|
||||
} else {
|
||||
// Create a new transaction in main DB if we are saving an entity from additional data store
|
||||
try (Transaction tx = persistence.createTransaction()) {
|
||||
if (item.getDbGeneratedIdEntity() == null) {
|
||||
if (Stores.isMain(storeName)) {
|
||||
EntityManager em = persistence.getEntityManager();
|
||||
em.persist(item);
|
||||
tx.commit();
|
||||
} else {
|
||||
// Create a new transaction in main DB if we are saving an entity from additional data store
|
||||
try (Transaction tx = persistence.createTransaction()) {
|
||||
EntityManager em = persistence.getEntityManager();
|
||||
em.persist(item);
|
||||
tx.commit();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
|
||||
@Override
|
||||
public void afterCommit() {
|
||||
Number id = item.getDbGeneratedIdEntity().getId().getNN();
|
||||
item.setObjectEntityId(id);
|
||||
try (Transaction tx = persistence.createTransaction()) {
|
||||
EntityManager em = persistence.getEntityManager();
|
||||
em.persist(item);
|
||||
tx.commit();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -387,7 +406,11 @@ public class EntityLog implements EntityLogAPI {
|
||||
item.setUser(findUser(em));
|
||||
item.setType(EntityLogItem.Type.CREATE);
|
||||
item.setEntity(entityName);
|
||||
item.setObjectEntityId(referenceToEntitySupport.getReferenceId(entity));
|
||||
if (entity instanceof BaseDbGeneratedIdEntity) {
|
||||
item.setDbGeneratedIdEntity((BaseDbGeneratedIdEntity) entity);
|
||||
} else {
|
||||
item.setObjectEntityId(referenceToEntitySupport.getReferenceId(entity));
|
||||
}
|
||||
item.setAttributes(createLogAttributes(entity, attributes, null));
|
||||
|
||||
enqueueItem(item);
|
||||
|
@ -29,6 +29,8 @@ import com.haulmont.cuba.security.entity.Group
|
||||
import com.haulmont.cuba.security.entity.LoggedAttribute
|
||||
import com.haulmont.cuba.security.entity.LoggedEntity
|
||||
import com.haulmont.cuba.security.entity.User
|
||||
import com.haulmont.cuba.testmodel.primary_keys.IdentityEntity
|
||||
import com.haulmont.cuba.testmodel.primary_keys.IntIdentityEntity
|
||||
import com.haulmont.cuba.testsupport.TestContainer
|
||||
import com.haulmont.cuba.testsupport.TestSupport
|
||||
import org.junit.ClassRule
|
||||
@ -79,6 +81,26 @@ class EntityLogTest extends Specification {
|
||||
la.setEntity(le)
|
||||
la.setName('type')
|
||||
em.persist(la)
|
||||
|
||||
le = new LoggedEntity()
|
||||
le.setName('test$IntIdentityEntity')
|
||||
le.setAuto(true)
|
||||
em.persist(le)
|
||||
|
||||
la = new LoggedAttribute()
|
||||
la.setEntity(le)
|
||||
la.setName('name')
|
||||
em.persist(la)
|
||||
|
||||
le = new LoggedEntity()
|
||||
le.setName('test$IdentityEntity')
|
||||
le.setAuto(true)
|
||||
em.persist(le)
|
||||
|
||||
la = new LoggedAttribute()
|
||||
la.setEntity(le)
|
||||
la.setName('name')
|
||||
em.persist(la)
|
||||
}
|
||||
entityLog = AppBeans.get(EntityLogAPI.class)
|
||||
entityLog.invalidateCache()
|
||||
@ -102,16 +124,21 @@ class EntityLogTest extends Specification {
|
||||
runner.update("delete from SEC_LOGGED_ENTITY")
|
||||
}
|
||||
|
||||
private List<EntityLogItem> getEntityLogItems(def userId) {
|
||||
private List<EntityLogItem> getEntityLogItems(String entityName, def entityId) {
|
||||
Transaction tx
|
||||
List<EntityLogItem> items
|
||||
tx = cont.persistence().createTransaction()
|
||||
try {
|
||||
EntityManager em = cont.persistence().getEntityManager()
|
||||
String entityIdField
|
||||
if (entityId instanceof Integer) entityIdField = 'intEntityId'
|
||||
else if (entityId instanceof Long) entityIdField = 'longEntityId'
|
||||
else entityIdField = 'entityId'
|
||||
|
||||
TypedQuery<EntityLogItem> query = em.createQuery(
|
||||
'select i from sec$EntityLog i where i.entity = ?1 and i.entityRef.entityId = ?2 order by i.eventTs desc', EntityLogItem.class)
|
||||
query.setParameter(1, 'sec$User')
|
||||
query.setParameter(2, userId)
|
||||
"select i from sec\$EntityLog i where i.entity = ?1 and i.entityRef.$entityIdField = ?2 order by i.eventTs desc", EntityLogItem.class)
|
||||
query.setParameter(1, entityName)
|
||||
query.setParameter(2, entityId)
|
||||
items = query.getResultList()
|
||||
|
||||
tx.commit()
|
||||
@ -147,8 +174,8 @@ class EntityLogTest extends Specification {
|
||||
|
||||
then:
|
||||
|
||||
getEntityLogItems(user1Id).size() == 1
|
||||
getEntityLogItems(user2Id).size() == 1
|
||||
getEntityLogItems('sec$User', user1Id).size() == 1
|
||||
getEntityLogItems('sec$User', user2Id).size() == 1
|
||||
|
||||
when:
|
||||
|
||||
@ -164,8 +191,8 @@ class EntityLogTest extends Specification {
|
||||
|
||||
then:
|
||||
|
||||
getEntityLogItems(user1Id).size() == 2
|
||||
getEntityLogItems(user2Id).size() == 2
|
||||
getEntityLogItems('sec$User', user1Id).size() == 2
|
||||
getEntityLogItems('sec$User', user2Id).size() == 2
|
||||
}
|
||||
|
||||
def "correct old value in case of flush in the middle"() {
|
||||
@ -198,8 +225,8 @@ class EntityLogTest extends Specification {
|
||||
|
||||
then:
|
||||
|
||||
getEntityLogItems(user1Id).size() == 2
|
||||
def item = getEntityLogItems(user1Id)[0] // latest
|
||||
getEntityLogItems('sec$User', user1Id).size() == 2
|
||||
def item = getEntityLogItems('sec$User', user1Id)[0] // latest
|
||||
|
||||
item.attributes.find({ it.name == 'email' }).value == 'email111'
|
||||
item.attributes.find({ it.name == 'email' }).oldValue == 'email1'
|
||||
@ -207,4 +234,80 @@ class EntityLogTest extends Specification {
|
||||
item.attributes.find({ it.name == 'name' }).value == 'name11'
|
||||
item.attributes.find({ it.name == 'name' }).oldValue == 'name1'
|
||||
}
|
||||
|
||||
def "works for BaseIdentityIdEntity"() {
|
||||
|
||||
when:
|
||||
|
||||
IdentityEntity entity = cont.persistence().callInTransaction { em ->
|
||||
def e = new IdentityEntity(name: 'test1')
|
||||
em.persist(e)
|
||||
e
|
||||
}
|
||||
|
||||
then:
|
||||
|
||||
noExceptionThrown()
|
||||
|
||||
def item1 = getEntityLogItems('test$IdentityEntity', entity.id.get())[0]
|
||||
item1.attributes.find({ it.name == 'name' }).value == 'test1'
|
||||
item1.attributes.find({ it.name == 'name' }).oldValue == null
|
||||
|
||||
when:
|
||||
|
||||
cont.persistence().runInTransaction { em ->
|
||||
def e = em.find(IdentityEntity, entity.id)
|
||||
e.name = 'test2'
|
||||
}
|
||||
|
||||
then:
|
||||
|
||||
def item2 = getEntityLogItems('test$IdentityEntity', entity.id.get())[0]
|
||||
item2.attributes.find({ it.name == 'name' }).value == 'test2'
|
||||
item2.attributes.find({ it.name == 'name' }).oldValue == 'test1'
|
||||
|
||||
cleanup:
|
||||
|
||||
if (entity != null && entity.getId().get() != null) {
|
||||
new QueryRunner(cont.persistence().dataSource).update("delete from TEST_IDENTITY where id = ${entity.getId().get()}")
|
||||
}
|
||||
}
|
||||
|
||||
def "works for BaseIntIdentityIdEntity"() {
|
||||
|
||||
when:
|
||||
|
||||
IntIdentityEntity entity = cont.persistence().callInTransaction { em ->
|
||||
def e = new IntIdentityEntity(name: 'test1')
|
||||
em.persist(e)
|
||||
e
|
||||
}
|
||||
|
||||
then:
|
||||
|
||||
noExceptionThrown()
|
||||
|
||||
def item1 = getEntityLogItems('test$IntIdentityEntity', entity.id.get())[0]
|
||||
item1.attributes.find({ it.name == 'name' }).value == 'test1'
|
||||
item1.attributes.find({ it.name == 'name' }).oldValue == null
|
||||
|
||||
when:
|
||||
|
||||
cont.persistence().runInTransaction { em ->
|
||||
def e = em.find(IntIdentityEntity, entity.id)
|
||||
e.name = 'test2'
|
||||
}
|
||||
|
||||
then:
|
||||
|
||||
def item2 = getEntityLogItems('test$IntIdentityEntity', entity.id.get())[0]
|
||||
item2.attributes.find({ it.name == 'name' }).value == 'test2'
|
||||
item2.attributes.find({ it.name == 'name' }).oldValue == 'test1'
|
||||
|
||||
cleanup:
|
||||
|
||||
if (entity != null && entity.getId().get() != null) {
|
||||
new QueryRunner(cont.persistence().dataSource).update("delete from TEST_INT_IDENTITY where id = ${entity.getId().get()}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ package com.haulmont.cuba.security.entity;
|
||||
|
||||
import com.haulmont.chile.core.annotations.MetaProperty;
|
||||
import com.haulmont.chile.core.datatypes.impl.EnumClass;
|
||||
import com.haulmont.cuba.core.entity.BaseDbGeneratedIdEntity;
|
||||
import com.haulmont.cuba.core.entity.BaseUuidEntity;
|
||||
import com.haulmont.cuba.core.entity.Creatable;
|
||||
import com.haulmont.cuba.core.entity.ReferenceToEntity;
|
||||
@ -31,7 +32,6 @@ import javax.annotation.PostConstruct;
|
||||
import javax.persistence.*;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Record containing information about entity lifecycle event.
|
||||
@ -99,6 +99,9 @@ public class EntityLogItem extends BaseUuidEntity implements Creatable {
|
||||
@EmbeddedParameters(nullAllowed = false)
|
||||
private ReferenceToEntity entityRef;
|
||||
|
||||
@Transient
|
||||
private transient BaseDbGeneratedIdEntity dbGeneratedIdEntity;
|
||||
|
||||
@Transient
|
||||
@MetaProperty
|
||||
private Set<EntityLogAttr> attributes;
|
||||
@ -188,6 +191,14 @@ public class EntityLogItem extends BaseUuidEntity implements Creatable {
|
||||
this.entityRef = entityRef;
|
||||
}
|
||||
|
||||
public BaseDbGeneratedIdEntity getDbGeneratedIdEntity() {
|
||||
return dbGeneratedIdEntity;
|
||||
}
|
||||
|
||||
public void setDbGeneratedIdEntity(BaseDbGeneratedIdEntity dbGeneratedIdEntity) {
|
||||
this.dbGeneratedIdEntity = dbGeneratedIdEntity;
|
||||
}
|
||||
|
||||
public void setObjectEntityId(Object entity) {
|
||||
if (entityRef == null) {
|
||||
entityRef = AppBeans.get(Metadata.class).create(ReferenceToEntity.class);
|
||||
|
Loading…
Reference in New Issue
Block a user