mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#919 - io.ebean package initial
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.config.PropertyMap;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import org.tests.model.basic.UTDetail;
|
||||
import org.tests.model.basic.UTMaster;
|
||||
import org.avaje.datasource.DataSourceConfig;
|
||||
import org.avaje.datasource.DataSourcePool;
|
||||
import org.avaje.datasource.pool.ConnectionPool;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class TestAutoCommitDataSource extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() throws SQLException {
|
||||
|
||||
Properties properties = PropertyMap.defaultProperties();
|
||||
|
||||
DataSourceConfig dsConfig = new DataSourceConfig();
|
||||
dsConfig.loadSettings(properties, "h2autocommit");//"pg"
|
||||
dsConfig.setAutoCommit(true);
|
||||
|
||||
DataSourcePool pool = new ConnectionPool("h2autocommit", dsConfig);
|
||||
|
||||
Connection connection = pool.getConnection();
|
||||
assertTrue(connection.getAutoCommit());
|
||||
connection.close();
|
||||
|
||||
System.setProperty("ebean.ignoreExtraDdl", "true");
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
config.setName("h2autocommit");
|
||||
config.setH2ProductionMode(true);
|
||||
config.loadFromProperties();
|
||||
config.setDataSource(pool);
|
||||
config.setDefaultServer(false);
|
||||
config.setRegister(false);
|
||||
|
||||
config.addClass(UTMaster.class);
|
||||
config.addClass(UTDetail.class);
|
||||
config.setDdlGenerate(true);
|
||||
config.setDdlRun(true);
|
||||
config.setAutoCommitMode(true);
|
||||
|
||||
EbeanServer ebeanServer = EbeanServerFactory.create(config);
|
||||
|
||||
Query<UTMaster> query = ebeanServer.find(UTMaster.class);
|
||||
List<UTMaster> details = ebeanServer.findList(query, null);
|
||||
assertEquals(0, details.size());
|
||||
|
||||
UTMaster bean1 = new UTMaster("one1");
|
||||
UTMaster bean2 = new UTMaster("two2");
|
||||
UTMaster bean3 = new UTMaster("three3");
|
||||
|
||||
// use a different transaction to do final query check
|
||||
Transaction otherTxn = ebeanServer.createTransaction();
|
||||
Transaction txn = ebeanServer.beginTransaction();
|
||||
|
||||
assertTrue(txn.getConnection().getAutoCommit());
|
||||
|
||||
try {
|
||||
ebeanServer.save(bean1);
|
||||
ebeanServer.save(bean2);
|
||||
|
||||
Query<UTMaster> query2 = ebeanServer.find(UTMaster.class);
|
||||
details = ebeanServer.findList(query2, otherTxn);
|
||||
assertEquals(2, details.size());
|
||||
|
||||
ebeanServer.save(bean3);
|
||||
|
||||
txn.rollback();
|
||||
|
||||
} finally {
|
||||
txn.end();
|
||||
}
|
||||
|
||||
Query<UTMaster> query3 = ebeanServer.find(UTMaster.class);
|
||||
details = ebeanServer.findList(query3, otherTxn);
|
||||
assertEquals(3, details.size());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.PersistBatch;
|
||||
import org.tests.model.basic.UTDetail;
|
||||
import org.tests.model.basic.UTMaster;
|
||||
import org.avaje.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class TestBatchPersistCascade extends BaseTestCase {
|
||||
|
||||
Logger logger = LoggerFactory.getLogger(TestBatchPersistCascade.class);
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
EbeanServer ebeanServer = Ebean.getServer(null);
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
Transaction txn = ebeanServer.beginTransaction();
|
||||
try {
|
||||
txn.setBatch(PersistBatch.INSERT);
|
||||
logger.info("start ------------");
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
UTMaster master = createMaster(i);
|
||||
logger.info("save ------------ {}", i);
|
||||
ebeanServer.save(master);
|
||||
//txn.flushBatch();
|
||||
}
|
||||
|
||||
logger.info("commit ------------");
|
||||
txn.commit();
|
||||
|
||||
} finally {
|
||||
txn.end();
|
||||
}
|
||||
|
||||
List<String> loggedSql = LoggedSqlCollector.stop();
|
||||
assertTrue(loggedSql.size() > 2);
|
||||
|
||||
|
||||
testUpdates();
|
||||
|
||||
}
|
||||
|
||||
private void testUpdates() {
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
|
||||
List<UTMaster> list = server.find(UTMaster.class).fetch("details").findList();
|
||||
|
||||
Transaction txn = server.beginTransaction();
|
||||
try {
|
||||
txn.setBatch(PersistBatch.INSERT);
|
||||
txn.setBatchOnCascade(PersistBatch.ALL);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
UTMaster master = createMaster(i + 500);
|
||||
logger.info("save ------------ {}", i);
|
||||
server.save(master);
|
||||
}
|
||||
|
||||
logger.info("starting updates ------------ ");
|
||||
|
||||
UTMaster lastMaster = null;
|
||||
for (UTMaster utMaster : list) {
|
||||
utMaster.setName(utMaster.getName() + " + mod");
|
||||
List<UTDetail> details = utMaster.getDetails();
|
||||
for (UTDetail detail : details) {
|
||||
detail.setQty(detail.getQty() + 7);
|
||||
detail.setName(detail.getName() + " + foo");
|
||||
}
|
||||
|
||||
server.save(utMaster);
|
||||
lastMaster = utMaster;
|
||||
}
|
||||
|
||||
logger.info("starting some inserts ------------ ");
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
UTMaster master = createMaster(i + 1000);
|
||||
logger.info("save ------------ {}", i);
|
||||
server.save(master);
|
||||
if (i == 1) {
|
||||
logger.info("save lastMaster ------------ ");
|
||||
lastMaster.setName("mod");
|
||||
server.save(lastMaster);
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("commit ------------ ");
|
||||
|
||||
server.commitTransaction();
|
||||
} finally {
|
||||
server.endTransaction();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private UTDetail createUTDetail(String master, int count) {
|
||||
UTDetail detail = new UTDetail();
|
||||
detail.setName(master + "-" + count);
|
||||
detail.setAmount(50d);
|
||||
detail.setQty(count);
|
||||
return detail;
|
||||
}
|
||||
|
||||
private UTMaster createMaster(int count) {
|
||||
|
||||
String name = "master" + count;
|
||||
|
||||
UTMaster m0 = new UTMaster();
|
||||
m0.setName(name);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
m0.addDetail(createUTDetail(name, i));
|
||||
}
|
||||
return m0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.Transaction;
|
||||
import org.tests.model.m2m.MnyB;
|
||||
import org.tests.model.m2m.MnyC;
|
||||
import org.avaje.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
public class TestBeanStateReset extends BaseTestCase {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(TestBeanStateReset.class);
|
||||
|
||||
@Test
|
||||
public void resetForInsert() {
|
||||
|
||||
// setup to fail foreign key constraint
|
||||
MnyC c = new MnyC();
|
||||
c.setId(Long.MAX_VALUE);
|
||||
|
||||
MnyB b = new MnyB();
|
||||
b.getCs().add(c);
|
||||
|
||||
try {
|
||||
// inserts of b succeeds but intersection insert fails FK check on c
|
||||
b.save();
|
||||
|
||||
} catch (PersistenceException e) {
|
||||
logger.info("expected error " + e.getMessage());
|
||||
|
||||
Ebean.getBeanState(b).resetForInsert();
|
||||
b.getCs().clear();
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
b.setName("mod");
|
||||
b.save();
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
assertThat(sql.get(0)).contains("insert into mny_b (id, name, version, when_created, when_modified, a_id) values (");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void alternativeVia_persistCascadeOff_with_commitAndContinue() {
|
||||
|
||||
// setup to fail foreign key constraint when using cascade save
|
||||
MnyC c = new MnyC();
|
||||
c.setId(Long.MAX_VALUE);
|
||||
|
||||
MnyB b = new MnyB();
|
||||
b.getCs().add(c);
|
||||
|
||||
Transaction transaction = Ebean.beginTransaction();
|
||||
|
||||
try {
|
||||
// turn off cascade ...
|
||||
transaction.setPersistCascade(false);
|
||||
b.save();
|
||||
|
||||
// commit at this point
|
||||
transaction.commitAndContinue();
|
||||
try {
|
||||
|
||||
// turn on cascade ... such that the ManyToMany is persisted
|
||||
transaction.setPersistCascade(true);
|
||||
|
||||
// save b again which this time cascades to the ManyToMany
|
||||
// but this fails due to FK on ManyToMany
|
||||
b.save();
|
||||
|
||||
// we actually don't get here due to the FK error
|
||||
transaction.commit();
|
||||
|
||||
} catch (PersistenceException e) {
|
||||
// so we failed the second save but that is ok'ish
|
||||
// we handle this exception knowing b got inserted and committed
|
||||
// and that the inserts into the intersection table failed
|
||||
logger.info("The ManyToMany intersection error: " + e.getMessage());
|
||||
}
|
||||
} finally {
|
||||
// performs a rollback as the commit at line:80 does not happen
|
||||
transaction.end();
|
||||
}
|
||||
|
||||
// assert our insert prior to the commitAndContinue succeeded
|
||||
MnyB madeIt = Ebean.find(MnyB.class, b.getId());
|
||||
assertNotNull(madeIt);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.TxIsolation;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.sql.Connection;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class TestBeginTransactionWithExisting extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void testTransactionIsoLevels() {
|
||||
|
||||
assertEquals(Transaction.READ_COMMITTED, Connection.TRANSACTION_READ_COMMITTED);
|
||||
assertEquals(Transaction.READ_UNCOMMITTED, Connection.TRANSACTION_READ_UNCOMMITTED);
|
||||
assertEquals(Transaction.REPEATABLE_READ, Connection.TRANSACTION_REPEATABLE_READ);
|
||||
assertEquals(Transaction.SERIALIZABLE, Connection.TRANSACTION_SERIALIZABLE);
|
||||
}
|
||||
|
||||
@Test(expected = PersistenceException.class)
|
||||
public void test() {
|
||||
|
||||
assertEquals(Transaction.READ_COMMITTED, Connection.TRANSACTION_READ_COMMITTED);
|
||||
|
||||
Transaction txn = Ebean.beginTransaction();
|
||||
try {
|
||||
|
||||
Ebean.beginTransaction(TxIsolation.READ_COMMITED);
|
||||
|
||||
} finally {
|
||||
txn.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.annotation.Transactional;
|
||||
import org.tests.model.m2m.MnyB;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
public class TestCommitAndContinue extends BaseTestCase {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger("org.avaje.ebean.TXN");
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void transactional_partialSuccess() {
|
||||
|
||||
MnyB a = new MnyB("a100");
|
||||
MnyB b = new MnyB("b200");
|
||||
|
||||
a.save();
|
||||
|
||||
// commit at this point
|
||||
Ebean.currentTransaction().commitAndContinue();
|
||||
|
||||
try {
|
||||
b.save();
|
||||
|
||||
// some error occurs
|
||||
throw new IllegalStateException();
|
||||
|
||||
} catch (IllegalStateException e) {
|
||||
// mark the transaction as rollback
|
||||
Ebean.currentTransaction().setRollbackOnly();
|
||||
|
||||
// use a different transaction to assert
|
||||
EbeanServer server = Ebean.getDefaultServer();
|
||||
Transaction anotherTxn = server.createTransaction();
|
||||
|
||||
// success prior to commitAndContinue
|
||||
assertNotNull(server.find(MnyB.class, a.getId(), anotherTxn));
|
||||
|
||||
// insert failed after commitAndContinue
|
||||
assertNull(server.find(MnyB.class, b.getId(), anotherTxn));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The @Transactional is nicer to me.
|
||||
*/
|
||||
@Test
|
||||
public void tryFinally_partialSuccess() {
|
||||
|
||||
MnyB a = new MnyB("a100");
|
||||
MnyB b = new MnyB("b200");
|
||||
|
||||
EbeanServer server = Ebean.getDefaultServer();
|
||||
Transaction txn = server.beginTransaction();
|
||||
try {
|
||||
a.save();
|
||||
// commit at this point
|
||||
txn.commitAndContinue();
|
||||
|
||||
try {
|
||||
b.save();
|
||||
|
||||
// some error occurs
|
||||
throw new IllegalStateException();
|
||||
|
||||
} catch (IllegalStateException e) {
|
||||
// mark the transaction as rollback
|
||||
txn.setRollbackOnly();
|
||||
|
||||
// use a different transaction to assert
|
||||
Transaction anotherTxn = server.createTransaction();
|
||||
// success prior to commitAndContinue
|
||||
assertNotNull(server.find(MnyB.class, a.getId(), anotherTxn));
|
||||
// insert failed after commitAndContinue
|
||||
assertNull(server.find(MnyB.class, b.getId(), anotherTxn));
|
||||
}
|
||||
|
||||
// does not commit due to the txn.setRollbackOnly();
|
||||
txn.commit();
|
||||
|
||||
} finally {
|
||||
server.endTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void transactional_partialSuccess_secondTransactionInsert() {
|
||||
|
||||
MnyB a = new MnyB("a100");
|
||||
MnyB b = new MnyB("b200");
|
||||
MnyB c = new MnyB("c300");
|
||||
|
||||
a.save();
|
||||
|
||||
// commit at this point
|
||||
Ebean.currentTransaction().commitAndContinue();
|
||||
|
||||
try {
|
||||
b.save();
|
||||
|
||||
// some error occurs
|
||||
throw new IllegalStateException();
|
||||
|
||||
} catch (IllegalStateException e) {
|
||||
// mark the transaction as rollback
|
||||
Ebean.currentTransaction().setRollbackOnly();
|
||||
|
||||
// use a different transaction to do something useful
|
||||
EbeanServer server = Ebean.getDefaultServer();
|
||||
Transaction txn2 = server.createTransaction();
|
||||
try {
|
||||
server.save(c, txn2);
|
||||
txn2.commit();
|
||||
} finally {
|
||||
txn2.end();
|
||||
}
|
||||
}
|
||||
|
||||
// asserts
|
||||
|
||||
EbeanServer server = Ebean.getDefaultServer();
|
||||
Transaction txnForAssert = server.createTransaction();
|
||||
|
||||
// success prior to commitAndContinue
|
||||
assertNotNull(server.find(MnyB.class, a.getId(), txnForAssert));
|
||||
|
||||
// insert failed after commitAndContinue
|
||||
assertNull(server.find(MnyB.class, b.getId(), txnForAssert));
|
||||
|
||||
// successful insert using txn2
|
||||
assertNotNull(server.find(MnyB.class, c.getId(), txnForAssert));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basic() {
|
||||
|
||||
MnyB a = new MnyB("a");
|
||||
MnyB b = new MnyB("b");
|
||||
MnyB c = new MnyB("c");
|
||||
|
||||
Transaction txn = Ebean.beginTransaction();
|
||||
try {
|
||||
a.save();
|
||||
txn.commitAndContinue();
|
||||
|
||||
txn.setBatchMode(true);
|
||||
b.save();
|
||||
logger.info("... pre commitAndContinue");
|
||||
txn.commitAndContinue();
|
||||
|
||||
c.save();
|
||||
txn.commit();
|
||||
|
||||
} finally {
|
||||
txn.end();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void runTransactional() {
|
||||
|
||||
new MnyB("a100").save();
|
||||
new MnyB("a101").save();
|
||||
|
||||
Ebean.currentTransaction().commitAndContinue();
|
||||
|
||||
new MnyB("a200").save();
|
||||
new MnyB("a201").save();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TestCreateTransactionWithIsolation extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
// EbeanServer server = Ebean.getServer(null);
|
||||
// Transaction txn = server.createTransaction(TxIsolation.SERIALIZABLE);
|
||||
// txn.end();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebeaninternal.api.SpiTransaction;
|
||||
import org.tests.model.basic.EBasicVer;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
import org.junit.Test;
|
||||
|
||||
import static junit.framework.TestCase.assertNull;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
public class TestDeleteFromPersistenceContext extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void testDeleteBean() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
EBasicVer bean = new EBasicVer("Please Delete Me");
|
||||
Ebean.save(bean);
|
||||
|
||||
SpiTransaction transaction = (SpiTransaction) Ebean.beginTransaction();
|
||||
try {
|
||||
|
||||
EBasicVer bean2 = Ebean.find(EBasicVer.class, bean.getId());
|
||||
assertNotSame(bean, bean2);
|
||||
|
||||
EBasicVer bean3 = Ebean.find(EBasicVer.class, bean.getId());
|
||||
// same instance from PersistenceContext
|
||||
assertSame(bean2, bean3);
|
||||
|
||||
Object bean4 = transaction.getPersistenceContext().get(EBasicVer.class, bean.getId());
|
||||
assertSame(bean2, bean4);
|
||||
|
||||
Ebean.delete(bean2);
|
||||
|
||||
Object bean5 = transaction.getPersistenceContext().get(EBasicVer.class, bean.getId());
|
||||
assertNull("Bean is deleted from PersistenceContext", bean5);
|
||||
|
||||
Ebean.commitTransaction();
|
||||
|
||||
} finally {
|
||||
Ebean.endTransaction();
|
||||
}
|
||||
|
||||
EBasicVer bean6 = Ebean.find(EBasicVer.class).where().eq("id", bean.getId()).findUnique();
|
||||
assertNull("Bean where id eq is not found " + bean6, bean6);
|
||||
|
||||
awaitL2Cache();
|
||||
EBasicVer bean7 = Ebean.find(EBasicVer.class, bean.getId());
|
||||
assertNull("Bean is not expected to be found? " + bean7, bean7);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.config.PropertyMap;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import org.tests.model.basic.UTDetail;
|
||||
import org.tests.model.basic.UTMaster;
|
||||
import org.avaje.datasource.DataSourceConfig;
|
||||
import org.avaje.datasource.DataSourcePool;
|
||||
import org.avaje.datasource.pool.ConnectionPool;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class TestExplicitTransactionMode extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() throws SQLException {
|
||||
|
||||
Properties properties = PropertyMap.defaultProperties();
|
||||
|
||||
DataSourceConfig dsConfig = new DataSourceConfig();
|
||||
dsConfig.loadSettings(properties, "h2autocommit");//"h2autocommit","pg"
|
||||
dsConfig.setAutoCommit(true);
|
||||
|
||||
DataSourcePool pool = new ConnectionPool("h2autocommit", dsConfig);
|
||||
|
||||
Connection connection = pool.getConnection();
|
||||
assertTrue(connection.getAutoCommit());
|
||||
connection.close();
|
||||
|
||||
System.setProperty("ebean.ignoreExtraDdl", "true");
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
config.setName("h2autocommit");
|
||||
config.loadFromProperties();
|
||||
config.setDataSource(pool);
|
||||
config.setDefaultServer(false);
|
||||
config.setRegister(false);
|
||||
config.setExplicitTransactionBeginMode(true);
|
||||
|
||||
config.addClass(UTMaster.class);
|
||||
config.addClass(UTDetail.class);
|
||||
config.setDdlGenerate(true);
|
||||
config.setDdlRun(true);
|
||||
|
||||
EbeanServer ebeanServer = EbeanServerFactory.create(config);
|
||||
|
||||
Query<UTMaster> query = ebeanServer.find(UTMaster.class);
|
||||
List<UTMaster> details = ebeanServer.findList(query, null);
|
||||
assertEquals(0, details.size());
|
||||
|
||||
UTMaster bean0 = new UTMaster("one0");
|
||||
Transaction txn0 = ebeanServer.beginTransaction();
|
||||
try {
|
||||
ebeanServer.save(bean0);
|
||||
txn0.rollback();
|
||||
} finally {
|
||||
txn0.end();
|
||||
}
|
||||
|
||||
// rollback as expected
|
||||
assertEquals(0, ebeanServer.find(UTMaster.class).findCount());
|
||||
|
||||
UTMaster bean1 = new UTMaster("one1");
|
||||
UTMaster bean2 = new UTMaster("two2");
|
||||
UTMaster bean3 = new UTMaster("three3");
|
||||
|
||||
// use a different transaction to do final query check
|
||||
Transaction otherTxn = ebeanServer.createTransaction();
|
||||
Transaction txn = ebeanServer.beginTransaction();
|
||||
|
||||
try {
|
||||
ebeanServer.save(bean1);
|
||||
ebeanServer.save(bean2);
|
||||
|
||||
// not visible in other transaction
|
||||
Query<UTMaster> query2 = ebeanServer.find(UTMaster.class);
|
||||
details = ebeanServer.findList(query2, otherTxn);
|
||||
assertEquals(0, details.size());
|
||||
|
||||
ebeanServer.save(bean3);
|
||||
|
||||
txn.commit();
|
||||
|
||||
} finally {
|
||||
txn.end();
|
||||
}
|
||||
|
||||
// commit as expected
|
||||
Query<UTMaster> query3 = ebeanServer.find(UTMaster.class);
|
||||
details = ebeanServer.findList(query3, otherTxn);
|
||||
assertEquals(3, details.size());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import org.tests.model.basic.BBookmark;
|
||||
import org.tests.model.basic.BBookmarkUser;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TestInsertManyAndRef extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void testMe() {
|
||||
|
||||
// ResetBasicData.reset();
|
||||
//
|
||||
// Customer u = new Customer();
|
||||
// u.setName("Mr Test");
|
||||
//
|
||||
// final List<Order> bookmarks = new ArrayList<Order>();
|
||||
// final Order b1 = new Order();
|
||||
// b1.setCustomer(u);
|
||||
// b1.setStatus(Status.NEW);
|
||||
//
|
||||
// final Order b2 = new Order();
|
||||
// b2.setStatus(Status.NEW);
|
||||
// b2.setCustomer(u);
|
||||
//
|
||||
// bookmarks.add(b1);
|
||||
// bookmarks.add(b2);
|
||||
//
|
||||
// Ebean.save(bookmarks);
|
||||
|
||||
final BBookmarkUser u = new BBookmarkUser();
|
||||
u.setEmailAddress("test@test.com");
|
||||
u.setName("Mr Test");
|
||||
u.setPassword("password");
|
||||
|
||||
final List<BBookmark> bookmarks = new ArrayList<>();
|
||||
final BBookmark b1 = new BBookmark();
|
||||
b1.setBookmarkReference("Acts 2:7-20");
|
||||
b1.setUser(u);
|
||||
|
||||
final BBookmark b2 = new BBookmark();
|
||||
b2.setBookmarkReference("Acts 7:1-20");
|
||||
b2.setUser(u);
|
||||
|
||||
bookmarks.add(b1);
|
||||
bookmarks.add(b2);
|
||||
|
||||
Ebean.saveAll(bookmarks);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.TxRunnable;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TestNested extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
try {
|
||||
Ebean.execute(() -> willFail());
|
||||
} catch (RuntimeException e) {
|
||||
Assert.assertEquals(e.getMessage(), "test rollback");
|
||||
}
|
||||
}
|
||||
|
||||
private void willFail() {
|
||||
Ebean.execute(new TxRunnable() {
|
||||
public void run() {
|
||||
|
||||
String msg = "test rollback";
|
||||
throw new RuntimeException(msg);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.TxScope;
|
||||
import org.tests.model.basic.Country;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.Product;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class TestNestedBeginRequired extends BaseTestCase {
|
||||
|
||||
Logger logger = LoggerFactory.getLogger(TestNestedBeginRequired.class);
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
someOuterMethod();
|
||||
}
|
||||
|
||||
private void someOuterMethod() {
|
||||
|
||||
Transaction txn = server.beginTransaction(TxScope.required());
|
||||
try {
|
||||
|
||||
server.find(Country.class).findCount();
|
||||
|
||||
someInnerMethod();
|
||||
|
||||
server.find(Product.class).findCount();
|
||||
|
||||
txn.commit();
|
||||
|
||||
} finally {
|
||||
txn.end();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void someInnerMethod() {
|
||||
|
||||
logger.debug("someInnerMethod() ...");
|
||||
Transaction txn = server.beginTransaction(TxScope.required());
|
||||
try {
|
||||
|
||||
server.find(Customer.class).findCount();
|
||||
|
||||
txn.commit();
|
||||
|
||||
} finally {
|
||||
txn.end();
|
||||
}
|
||||
logger.debug("someInnerMethod() ... done");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.TxScope;
|
||||
import org.tests.model.basic.Country;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.EBasic;
|
||||
import org.tests.model.basic.Product;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class TestNestedBeginRequiredWithFailure extends BaseTestCase {
|
||||
|
||||
Logger logger = LoggerFactory.getLogger(TestNestedBeginRequiredWithFailure.class);
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
someOuterMethod();
|
||||
}
|
||||
|
||||
private void someOuterMethod() {
|
||||
|
||||
Transaction txn = server.beginTransaction(TxScope.required());
|
||||
try {
|
||||
|
||||
server.find(Country.class).findCount();
|
||||
|
||||
try {
|
||||
someInnerMethodWithFailure();
|
||||
|
||||
server.find(Product.class).findCount();
|
||||
txn.commit();
|
||||
|
||||
} catch (RuntimeException e) {
|
||||
logger.info("Inner method failed with " + e);
|
||||
}
|
||||
|
||||
} finally {
|
||||
// For REQUIRED ... the transaction can already been
|
||||
// rolled back (by inner method) so that case is expected
|
||||
// (and that is the case here - txn is already rolled back)
|
||||
txn.end();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void someInnerMethodWithFailure() {
|
||||
|
||||
logger.debug("someInnerMethod() ...");
|
||||
Transaction txn = server.beginTransaction(TxScope.required());
|
||||
try {
|
||||
|
||||
server.find(Customer.class).findCount();
|
||||
|
||||
EBasic basic = new EBasic();
|
||||
basic.setName("ignore");
|
||||
server.save(basic);
|
||||
|
||||
if (server != null) {
|
||||
throw new RuntimeException("barf");
|
||||
}
|
||||
|
||||
txn.commit();
|
||||
|
||||
} finally {
|
||||
txn.end();
|
||||
logger.debug("someInnerMethod() ... done");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.TxScope;
|
||||
import org.tests.model.basic.Country;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.Product;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class TestNestedBeginRequiresNew extends BaseTestCase {
|
||||
|
||||
Logger logger = LoggerFactory.getLogger(TestNestedBeginRequiresNew.class);
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
someOuterMethod();
|
||||
}
|
||||
|
||||
private void someOuterMethod() {
|
||||
|
||||
Transaction txn = server.beginTransaction(TxScope.requiresNew());
|
||||
try {
|
||||
|
||||
server.find(Country.class).findCount();
|
||||
|
||||
someInnerMethod();
|
||||
|
||||
server.find(Product.class).findCount();
|
||||
|
||||
txn.commit();
|
||||
|
||||
} finally {
|
||||
txn.end();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void someInnerMethod() {
|
||||
|
||||
logger.debug("someInnerMethod() ...");
|
||||
Transaction txn = server.beginTransaction(TxScope.requiresNew());
|
||||
try {
|
||||
|
||||
server.find(Customer.class).findCount();
|
||||
txn.commit();
|
||||
|
||||
} finally {
|
||||
txn.end();
|
||||
}
|
||||
logger.debug("someInnerMethod() ... done");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.TxScope;
|
||||
import org.tests.model.basic.Country;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.Product;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class TestNestedBeginRequiresNewWithFailure extends BaseTestCase {
|
||||
|
||||
Logger logger = LoggerFactory.getLogger(TestNestedBeginRequiresNewWithFailure.class);
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
someOuterMethod();
|
||||
}
|
||||
|
||||
private void someOuterMethod() {
|
||||
|
||||
Transaction txn = server.beginTransaction(TxScope.requiresNew());
|
||||
try {
|
||||
|
||||
server.find(Country.class).findCount();
|
||||
|
||||
try {
|
||||
someInnerMethodWithFailure();
|
||||
} catch (RuntimeException e) {
|
||||
logger.info("Inner method failed with " + e.getMessage());
|
||||
}
|
||||
server.find(Product.class).findCount();
|
||||
|
||||
txn.commit();
|
||||
|
||||
} finally {
|
||||
txn.end();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void someInnerMethodWithFailure() {
|
||||
|
||||
logger.debug("someInnerMethod() ...");
|
||||
Transaction txn = server.beginTransaction(TxScope.requiresNew());
|
||||
try {
|
||||
|
||||
server.find(Customer.class).findCount();
|
||||
|
||||
if (server != null) {
|
||||
throw new RuntimeException("barf");
|
||||
}
|
||||
txn.commit();
|
||||
|
||||
} finally {
|
||||
txn.end();
|
||||
}
|
||||
logger.debug("someInnerMethod() ... done");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebeaninternal.api.SpiTransaction;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.Order;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class TestPersistContextClear extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
ResetBasicData.createOrderCustAndOrder("testPc");
|
||||
|
||||
Transaction t = Ebean.beginTransaction();
|
||||
SpiTransaction spiTxn = (SpiTransaction) t;
|
||||
PersistenceContext pc = spiTxn.getPersistenceContext();
|
||||
|
||||
// no orders or customers in the PC
|
||||
Assert.assertEquals(0, pc.size(Order.class));
|
||||
Assert.assertEquals(0, pc.size(Customer.class));
|
||||
|
||||
Order order0 = null;
|
||||
try {
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
List<Order> list = server.find(Order.class).fetch("customer").fetch("details").findList();
|
||||
|
||||
int orderSize = list.size();
|
||||
Assert.assertTrue(orderSize > 1);
|
||||
|
||||
// keep a hold of one of them
|
||||
order0 = list.get(0);
|
||||
|
||||
Assert.assertEquals(orderSize, pc.size(Order.class));
|
||||
|
||||
System.gc();
|
||||
Assert.assertEquals(orderSize, pc.size(Order.class));
|
||||
Assert.assertTrue(pc.size(Customer.class) > 0);
|
||||
|
||||
list = null;
|
||||
// System.gc();
|
||||
|
||||
// transaction still holds PC ...
|
||||
// System.out.println("pc2:"+pc);
|
||||
// These asserts may not succeed depending on JVM
|
||||
// Assert.assertEquals(pc.size(Order.class), 1);
|
||||
// Assert.assertEquals(pc.size(Customer.class), 1);
|
||||
|
||||
} finally {
|
||||
t.end();
|
||||
}
|
||||
|
||||
System.gc();
|
||||
|
||||
// we still have the order
|
||||
Assert.assertNotNull(order0);
|
||||
// its likely the only one in the PC now
|
||||
// due to the System.gc(); but can't garuntee it
|
||||
// so removing these asserts... can put them back
|
||||
// to manually test.
|
||||
// Assert.assertEquals(pc.size(Order.class), 1);
|
||||
// Assert.assertEquals(pc.size(Customer.class), 1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import org.tests.model.basic.EBasic;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
public class TestStatelessUpdateClearPC extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
|
||||
Ebean.beginTransaction();
|
||||
|
||||
EBasic newUser = new EBasic();
|
||||
newUser.setName("any@email.com");
|
||||
Ebean.save(newUser);
|
||||
|
||||
// load the bean into the persistence context
|
||||
EBasic dummyLoadedUser = Ebean.find(EBasic.class, newUser.getId()); // This row is added
|
||||
assertNotNull(dummyLoadedUser);
|
||||
|
||||
// stateless update (should clear the bean from the persistence context)
|
||||
EBasic updateUser = new EBasic();
|
||||
updateUser.setId(newUser.getId());
|
||||
updateUser.setName("anyNew@email.com");
|
||||
Ebean.update(updateUser);
|
||||
|
||||
EBasic loadedUser = Ebean.find(EBasic.class, newUser.getId());
|
||||
assertEquals("anyNew@email.com", loadedUser.getName());
|
||||
|
||||
Ebean.rollbackTransaction();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.TransactionCallbackAdapter;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class TestTransactionCallback extends BaseTestCase {
|
||||
|
||||
int countPreCommit;
|
||||
int countPostCommit;
|
||||
int countPreRollback;
|
||||
int countPostRollback;
|
||||
|
||||
@Test(expected = PersistenceException.class)
|
||||
public void test_noActiveTransaction() {
|
||||
|
||||
Ebean.register(new MyCallback());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_commitAndRollback() {
|
||||
|
||||
|
||||
Transaction txn = Ebean.beginTransaction();
|
||||
Ebean.register(new MyCallback());
|
||||
txn.getConnection();
|
||||
Ebean.commitTransaction();
|
||||
|
||||
assertEquals(1, countPreCommit);
|
||||
assertEquals(1, countPostCommit);
|
||||
assertEquals(0, countPreRollback);
|
||||
assertEquals(0, countPostRollback);
|
||||
|
||||
Ebean.beginTransaction();
|
||||
Ebean.register(new MyCallback());
|
||||
Ebean.rollbackTransaction();
|
||||
|
||||
assertEquals(1, countPreCommit);
|
||||
assertEquals(1, countPostCommit);
|
||||
assertEquals(1, countPreRollback);
|
||||
assertEquals(1, countPostRollback);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test(expected = PersistenceException.class)
|
||||
public void test_withEbeanserver() {
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
server.register(new MyCallback());
|
||||
}
|
||||
|
||||
|
||||
class MyCallback extends TransactionCallbackAdapter {
|
||||
|
||||
@Override
|
||||
public void preCommit() {
|
||||
countPreCommit++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postCommit() {
|
||||
countPostCommit++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRollback() {
|
||||
countPreRollback++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postRollback() {
|
||||
countPostRollback++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.annotation.Transactional;
|
||||
import org.tests.model.basic.EBasic;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class TestTransactionRollbackOnly {
|
||||
|
||||
private EBasic one;
|
||||
|
||||
private EBasic two;
|
||||
|
||||
@Test
|
||||
public void transaction_setRollbackOnly() {
|
||||
|
||||
doVia_currentTransaction();
|
||||
|
||||
assertThat(one.getId()).isNotNull();
|
||||
assertThat(Ebean.find(EBasic.class, one.getId())).isNull();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
protected void doVia_currentTransaction() {
|
||||
|
||||
one = new EBasic("WillNotSave");
|
||||
Ebean.save(one);
|
||||
|
||||
Transaction transaction = Ebean.currentTransaction();
|
||||
assertFalse(transaction.isRollbackOnly());
|
||||
|
||||
transaction.setRollbackOnly();
|
||||
assertTrue(transaction.isRollbackOnly());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Ebean_setRollbackOnly() {
|
||||
|
||||
do_Ebean_setRollbackOnly();
|
||||
|
||||
assertThat(two.getId()).isNotNull();
|
||||
assertThat(Ebean.find(EBasic.class, two.getId())).isNull();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
protected void do_Ebean_setRollbackOnly() {
|
||||
|
||||
two = new EBasic("WillNotSave");
|
||||
Ebean.save(two);
|
||||
|
||||
Ebean.setRollbackOnly();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.annotation.Transactional;
|
||||
import org.avaje.agentloader.AgentLoader;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.Table;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* It shows the issue that the user record does NOT rolback when there is an exception thrown
|
||||
*/
|
||||
public class TransactionNotTerminatedAfterRollback {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TransactionNotTerminatedAfterRollback.class);
|
||||
|
||||
@BeforeClass
|
||||
public static void preStart() {
|
||||
LOG.debug("... preStart");
|
||||
// display the log message to see if the UserService is enhanced
|
||||
AgentLoader.loadAgentFromClasspath("avaje-ebeanorm-agent", "debug=1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
try {
|
||||
new UserService().create(new User(1L, "David"));
|
||||
fail("Exception should be thrown");
|
||||
} catch (PersistenceException pe) {
|
||||
LOG.error("e: " + pe);
|
||||
}
|
||||
List<User> users = Ebean.find(User.class).findList();
|
||||
LOG.debug("users: {}", users);
|
||||
assertTrue("users should be empty", users.isEmpty());
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = PersistenceException.class)
|
||||
public class UserService {
|
||||
public void create(User i) {
|
||||
Ebean.save(i);
|
||||
Ebean.save(new User(1L, "Peter")); // make it throw exception and rollback
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name = "tx_user")
|
||||
public static class User {
|
||||
@Id
|
||||
Long id;
|
||||
String name;
|
||||
|
||||
public User() {
|
||||
}
|
||||
|
||||
public User(Long id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder s = new StringBuilder();
|
||||
s.append("{");
|
||||
s.append("id: ").append(id).append(", ");
|
||||
s.append("name: ").append(name);
|
||||
s.append("}");
|
||||
return s.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user