mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#390 - ENH: Add Change log mechanism for easy fine grained logging of insert, update, delete activity
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
package com.avaje.ebeaninternal.server.core;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebean.ValuePair;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.tests.model.basic.Customer;
|
||||
import com.avaje.tests.model.basic.Order;
|
||||
import com.avaje.tests.model.basic.Order.Status;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class TestDiffHelpInsertSimple extends BaseTestCase {
|
||||
|
||||
long firstTime = System.currentTimeMillis() - 10000;
|
||||
|
||||
EbeanServer server;
|
||||
|
||||
BeanDescriptor<Order> orderDesc;
|
||||
|
||||
public TestDiffHelpInsertSimple() {
|
||||
server = Ebean.getServer(null);
|
||||
SpiEbeanServer spiServer = (SpiEbeanServer) server;
|
||||
orderDesc = spiServer.getBeanDescriptor(Order.class);
|
||||
}
|
||||
|
||||
private Order createBaseOrder(EbeanServer server) {
|
||||
Order order1 = new Order();
|
||||
order1.setId(12);
|
||||
order1.setCretime(new Timestamp(firstTime));
|
||||
order1.setCustomer(server.getReference(Customer.class, 1234));
|
||||
order1.setStatus(Status.NEW);
|
||||
//order1.setShipDate(new Date(firstTime));
|
||||
order1.setOrderDate(new Date(firstTime));
|
||||
return order1;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basic() {
|
||||
|
||||
Order order1 = createBaseOrder(server);
|
||||
|
||||
Map<String, ValuePair> diff = DiffHelpInsert.diff((EntityBean) order1, orderDesc);
|
||||
|
||||
assertEquals(4, diff.size());
|
||||
|
||||
Set<String> keySet = diff.keySet();
|
||||
assertTrue(keySet.contains("cretime"));
|
||||
assertTrue(keySet.contains("status"));
|
||||
assertTrue(keySet.contains("orderDate"));
|
||||
assertTrue(keySet.contains("customer.id"));
|
||||
assertFalse(keySet.contains("shipDate"));
|
||||
}
|
||||
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
package com.avaje.ebeaninternal.server.core;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebean.ValuePair;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.tests.model.embedded.EMain;
|
||||
import com.avaje.tests.model.embedded.Eembeddable;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
public class TestDiffHelpInsertWithEmbedded extends BaseTestCase {
|
||||
|
||||
EbeanServer server;
|
||||
|
||||
BeanDescriptor<EMain> emainDesc;
|
||||
|
||||
public TestDiffHelpInsertWithEmbedded() {
|
||||
server = Ebean.getServer(null);
|
||||
SpiEbeanServer spiServer = (SpiEbeanServer) server;
|
||||
emainDesc = spiServer.getBeanDescriptor(EMain.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simple() {
|
||||
|
||||
EMain emain1 = createEMain();
|
||||
|
||||
Map<String, ValuePair> diff = DiffHelpInsert.diff((EntityBean) emain1, emainDesc);
|
||||
assertEquals(3, diff.size());
|
||||
assertEquals("foo", diff.get("name").getNewValue());
|
||||
assertEquals(13L, diff.get("version").getNewValue());
|
||||
|
||||
ValuePair valuePair = diff.get("embeddable.description");
|
||||
assertNotNull(valuePair);
|
||||
assertEquals("bar", valuePair.getNewValue());
|
||||
assertNull(valuePair.getOldValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scalarPropertyAsNull() {
|
||||
|
||||
EMain emain1 = createEMain();
|
||||
emain1.setName(null);
|
||||
|
||||
Map<String, ValuePair> diff = DiffHelpInsert.diff((EntityBean) emain1, emainDesc);
|
||||
assertEquals(2, diff.size());
|
||||
assertNull(diff.get("name"));
|
||||
assertEquals(13L, diff.get("version").getNewValue());
|
||||
|
||||
ValuePair valuePair = diff.get("embeddable.description");
|
||||
assertNotNull(valuePair);
|
||||
assertEquals("bar", valuePair.getNewValue());
|
||||
assertNull(valuePair.getOldValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void embeddedAsNull() {
|
||||
|
||||
EMain emain1 = createEMain();
|
||||
emain1.setEmbeddable(null);
|
||||
|
||||
Map<String, ValuePair> diff = DiffHelpInsert.diff((EntityBean) emain1, emainDesc);
|
||||
assertEquals(2, diff.size());
|
||||
assertEquals("foo", diff.get("name").getNewValue());
|
||||
assertEquals(13L, diff.get("version").getNewValue());
|
||||
|
||||
assertNull(diff.get("embeddable.description"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void embeddedPropertiesAsNull() {
|
||||
|
||||
EMain emain1 = createEMain();
|
||||
emain1.getEmbeddable().setDescription(null);
|
||||
|
||||
Map<String, ValuePair> diff = DiffHelpInsert.diff((EntityBean) emain1, emainDesc);
|
||||
assertEquals(2, diff.size());
|
||||
assertEquals("foo", diff.get("name").getNewValue());
|
||||
assertEquals(13L, diff.get("version").getNewValue());
|
||||
|
||||
assertNull(diff.get("embeddable.description"));
|
||||
}
|
||||
|
||||
private EMain createEMain() {
|
||||
|
||||
EMain emain = new EMain();
|
||||
emain.setName("foo");
|
||||
emain.setVersion(13l);
|
||||
|
||||
Eembeddable embeddable = new Eembeddable();
|
||||
embeddable.setDescription("bar");
|
||||
emain.setEmbeddable(embeddable);
|
||||
|
||||
return emain;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
package com.avaje.tests.changelog;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.EbeanServerFactory;
|
||||
import com.avaje.ebean.annotation.ChangeLog;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.event.BeanPersistRequest;
|
||||
import com.avaje.ebean.event.changelog.ChangeLogFilter;
|
||||
import com.avaje.ebean.event.changelog.ChangeLogListener;
|
||||
import com.avaje.ebean.event.changelog.ChangeLogPrepare;
|
||||
import com.avaje.ebean.event.changelog.ChangeLogRegister;
|
||||
import com.avaje.ebean.event.changelog.ChangeSet;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.tests.model.basic.EBasicChangeLog;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class TestChangeLog extends BaseTestCase {
|
||||
|
||||
TDChangeLogPrepare changeLogPrepare = new TDChangeLogPrepare();
|
||||
|
||||
TDChangeLogListener changeLogListener = new TDChangeLogListener();
|
||||
|
||||
TDChangeLogRegister changeLogRegister = new TDChangeLogRegister();
|
||||
|
||||
SpiEbeanServer server;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
server = getServer();
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdown() {
|
||||
server.shutdown(true, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
EBasicChangeLog bean = new EBasicChangeLog();
|
||||
bean.setName("logBean");
|
||||
bean.setShortDescription("hello");
|
||||
server.save(bean);
|
||||
|
||||
bean.setName("ChangedName");
|
||||
server.save(bean);
|
||||
|
||||
server.delete(bean);
|
||||
|
||||
}
|
||||
|
||||
private SpiEbeanServer getServer() {
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
config.setName("h2other");
|
||||
config.loadFromProperties();
|
||||
|
||||
config.setDdlGenerate(true);
|
||||
config.setDdlRun(true);
|
||||
config.setDefaultServer(false);
|
||||
config.setRegister(false);
|
||||
|
||||
config.addClass(EBasicChangeLog.class);
|
||||
|
||||
config.setChangeLogPrepare(changeLogPrepare);
|
||||
config.setChangeLogListener(changeLogListener);
|
||||
config.setChangeLogRegister(changeLogRegister);
|
||||
|
||||
return (SpiEbeanServer) EbeanServerFactory.create(config);
|
||||
}
|
||||
|
||||
class TDChangeLogPrepare implements ChangeLogPrepare {
|
||||
@Override
|
||||
public boolean prepare(ChangeSet changes) {
|
||||
changes.setUserId("appUser1");
|
||||
changes.setUserIpAddress("1.1.1.1");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class TDChangeLogListener implements ChangeLogListener {
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
ChangeSet changes;
|
||||
|
||||
/**
|
||||
*/
|
||||
public TDChangeLogListener() {
|
||||
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void log(ChangeSet changes) {
|
||||
this.changes = changes;
|
||||
try {
|
||||
String json = objectMapper.writeValueAsString(changes);
|
||||
|
||||
logger.info(json);
|
||||
|
||||
ChangeSet changes1 = objectMapper.readValue(json, ChangeSet.class);
|
||||
|
||||
assertEquals(changes.getTxnId(), changes1.getTxnId());
|
||||
assertEquals(changes.getUserId(), changes1.getUserId());
|
||||
assertEquals(changes.getUserIpAddress(), changes1.getUserIpAddress());
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TDChangeLogRegister implements ChangeLogRegister {
|
||||
|
||||
@Override
|
||||
public ChangeLogFilter getChangeFilter(Class<?> beanType) {
|
||||
|
||||
ChangeLog changeLog = beanType.getAnnotation(ChangeLog.class);
|
||||
if (changeLog != null) {
|
||||
return new TDFilter();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Change log filter that includes all the inserts, updates and deletes.
|
||||
*/
|
||||
class TDFilter implements ChangeLogFilter {
|
||||
|
||||
/**
|
||||
* Returns true including all the inserts.
|
||||
*/
|
||||
@Override
|
||||
public boolean includeInsert(BeanPersistRequest<?> insertRequest) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean includeUpdate(BeanPersistRequest<?> updateRequest) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean includeDelete(BeanPersistRequest<?> deleteRequest) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package com.avaje.tests.model.basic;
|
||||
|
||||
import com.avaje.ebean.annotation.ChangeLog;
|
||||
import com.avaje.ebean.annotation.WhenCreated;
|
||||
import com.avaje.ebean.annotation.WhenModified;
|
||||
import com.avaje.ebean.annotation.WhoCreated;
|
||||
import com.avaje.ebean.annotation.WhoModified;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Version;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ChangeLog
|
||||
@Entity
|
||||
public class EBasicChangeLog {
|
||||
|
||||
@Id
|
||||
Long id;
|
||||
|
||||
@Size(max = 20)
|
||||
String name;
|
||||
|
||||
@Size(max = 50)
|
||||
String shortDescription;
|
||||
|
||||
@Size(max = 100)
|
||||
String longDescription;
|
||||
|
||||
@WhoCreated
|
||||
String whoCreated;
|
||||
|
||||
@WhoModified
|
||||
String whoModified;
|
||||
|
||||
@WhenCreated
|
||||
Timestamp whenCreated;
|
||||
|
||||
@WhenModified
|
||||
Timestamp whenModified;
|
||||
|
||||
@Version
|
||||
Long version;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getShortDescription() {
|
||||
return shortDescription;
|
||||
}
|
||||
|
||||
public void setShortDescription(String shortDescription) {
|
||||
this.shortDescription = shortDescription;
|
||||
}
|
||||
|
||||
public String getLongDescription() {
|
||||
return longDescription;
|
||||
}
|
||||
|
||||
public void setLongDescription(String longDescription) {
|
||||
this.longDescription = longDescription;
|
||||
}
|
||||
|
||||
public String getWhoCreated() {
|
||||
return whoCreated;
|
||||
}
|
||||
|
||||
public void setWhoCreated(String whoCreated) {
|
||||
this.whoCreated = whoCreated;
|
||||
}
|
||||
|
||||
public String getWhoModified() {
|
||||
return whoModified;
|
||||
}
|
||||
|
||||
public void setWhoModified(String whoModified) {
|
||||
this.whoModified = whoModified;
|
||||
}
|
||||
|
||||
public Timestamp getWhenCreated() {
|
||||
return whenCreated;
|
||||
}
|
||||
|
||||
public void setWhenCreated(Timestamp whenCreated) {
|
||||
this.whenCreated = whenCreated;
|
||||
}
|
||||
|
||||
public Timestamp getWhenModified() {
|
||||
return whenModified;
|
||||
}
|
||||
|
||||
public void setWhenModified(Timestamp whenModified) {
|
||||
this.whenModified = whenModified;
|
||||
}
|
||||
|
||||
public Long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(Long version) {
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user