mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Merge remote-tracking branch 'ebean/master' into pr/bugfix/connection_closed_on_clob
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.FetchConfig;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -10,7 +9,7 @@ public class FetchConfigTest {
|
||||
@Test
|
||||
public void testLazy() {
|
||||
FetchConfig config = new FetchConfig().lazy();
|
||||
assertThat(config.getBatchSize()).isEqualTo(10);
|
||||
assertThat(config.getBatchSize()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -72,10 +72,16 @@ public class ServerConfigTest {
|
||||
props.setProperty("enabledL2Regions", "r0,users,orgs");
|
||||
props.setProperty("caseSensitiveCollation", "false");
|
||||
props.setProperty("loadModuleInfo", "true");
|
||||
props.setProperty("collectQueryPlanThresholdMicros", "10000");
|
||||
props.setProperty("forUpdateNoKey", "true");
|
||||
props.setProperty("defaultServer", "false");
|
||||
|
||||
props.setProperty("queryPlan.enable", "true");
|
||||
props.setProperty("queryPlan.thresholdMicros", "10000");
|
||||
props.setProperty("queryPlan.capture", "true");
|
||||
props.setProperty("queryPlan.capturePeriodSecs", "42");
|
||||
props.setProperty("queryPlan.captureMaxTimeMillis", "560");
|
||||
props.setProperty("queryPlan.captureMaxCount", "7");
|
||||
|
||||
serverConfig.loadFromProperties(props);
|
||||
|
||||
assertFalse(serverConfig.isDefaultServer());
|
||||
@@ -97,7 +103,6 @@ public class ServerConfigTest {
|
||||
assertEquals(PlatformConfig.DbUuid.BINARY, serverConfig.getPlatformConfig().getDbUuid());
|
||||
assertEquals(JsonConfig.DateTime.MILLIS, serverConfig.getJsonDateTime());
|
||||
assertEquals(JsonConfig.Date.MILLIS, serverConfig.getJsonDate());
|
||||
assertEquals(10000, serverConfig.getCollectQueryPlanThresholdMicros());
|
||||
|
||||
assertEquals("r0,users,orgs", serverConfig.getEnabledL2Regions());
|
||||
|
||||
@@ -106,6 +111,13 @@ public class ServerConfigTest {
|
||||
assertEquals(4, serverConfig.getBackgroundExecutorSchedulePoolSize());
|
||||
assertEquals(98, serverConfig.getBackgroundExecutorShutdownSecs());
|
||||
|
||||
assertTrue(serverConfig.isQueryPlanEnable());
|
||||
assertEquals(10000, serverConfig.getQueryPlanThresholdMicros());
|
||||
assertTrue(serverConfig.isQueryPlanCapture());
|
||||
assertEquals(42, serverConfig.getQueryPlanCapturePeriodSecs());
|
||||
assertEquals(560, serverConfig.getQueryPlanCaptureMaxTimeMillis());
|
||||
assertEquals(7, serverConfig.getQueryPlanCaptureMaxCount());
|
||||
|
||||
assertThat(serverConfig.getMappingLocations()).containsExactly("classpath:/foo","bar");
|
||||
|
||||
serverConfig.setPersistBatch(PersistBatch.NONE);
|
||||
@@ -137,6 +149,7 @@ public class ServerConfigTest {
|
||||
ServerConfig serverConfig = new ServerConfig();
|
||||
assertTrue(serverConfig.isIdGeneratorAutomatic());
|
||||
assertTrue(serverConfig.isDefaultServer());
|
||||
assertFalse(serverConfig.isAutoPersistUpdates());
|
||||
|
||||
serverConfig.setIdGeneratorAutomatic(false);
|
||||
assertFalse(serverConfig.isIdGeneratorAutomatic());
|
||||
@@ -144,10 +157,18 @@ public class ServerConfigTest {
|
||||
assertEquals(JsonConfig.Date.ISO8601, serverConfig.getJsonDate());
|
||||
assertTrue(serverConfig.getPlatformConfig().isCaseSensitiveCollation());
|
||||
assertTrue(serverConfig.isAutoLoadModuleInfo());
|
||||
assertEquals(Long.MAX_VALUE, serverConfig.getCollectQueryPlanThresholdMicros());
|
||||
|
||||
assertFalse(serverConfig.isQueryPlanEnable());
|
||||
assertEquals(Long.MAX_VALUE, serverConfig.getQueryPlanThresholdMicros());
|
||||
assertFalse(serverConfig.isQueryPlanCapture());
|
||||
assertEquals(600, serverConfig.getQueryPlanCapturePeriodSecs());
|
||||
assertEquals(10000L, serverConfig.getQueryPlanCaptureMaxTimeMillis());
|
||||
assertEquals(10, serverConfig.getQueryPlanCaptureMaxCount());
|
||||
|
||||
serverConfig.setLoadModuleInfo(false);
|
||||
assertFalse(serverConfig.isAutoLoadModuleInfo());
|
||||
serverConfig.setAutoPersistUpdates(true);
|
||||
assertTrue(serverConfig.isAutoPersistUpdates());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -11,10 +11,10 @@ public class DtoQueryRequestTest {
|
||||
public void testParse() {
|
||||
|
||||
assertEquals("foo", DtoQueryRequest.parseColumn("foo"));
|
||||
assertEquals("bar", DtoQueryRequest.parseColumn("_e_t0_bar"));
|
||||
assertEquals("BAR", DtoQueryRequest.parseColumn("_E_T0_BAR"));
|
||||
assertEquals("baz", DtoQueryRequest.parseColumn("_e_t42_baz"));
|
||||
assertEquals("BAZ", DtoQueryRequest.parseColumn("_E_T42_BAZ"));
|
||||
assertEquals("bar", DtoQueryRequest.parseColumn("zx__t0_bar"));
|
||||
assertEquals("BAR", DtoQueryRequest.parseColumn("ZX__T0_BAR"));
|
||||
assertEquals("baz", DtoQueryRequest.parseColumn("zx__t42_baz"));
|
||||
assertEquals("BAZ", DtoQueryRequest.parseColumn("ZX__T42_BAZ"));
|
||||
|
||||
assertEquals("e_t42_nope", DtoQueryRequest.parseColumn("e_t42_nope"));
|
||||
assertEquals("_f_t42_nope", DtoQueryRequest.parseColumn("_f_t42_nope"));
|
||||
|
||||
@@ -4,21 +4,22 @@ import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.plugin.Property;
|
||||
import io.ebeaninternal.server.core.CacheOptions;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployIdentityMode;
|
||||
import io.ebeanservice.docstore.api.DocStoreBeanAdapter;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Animal;
|
||||
import org.tests.model.basic.AnimalShelter;
|
||||
import org.tests.model.basic.Cat;
|
||||
import org.tests.model.basic.Contact;
|
||||
import org.tests.model.basic.Country;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.Dog;
|
||||
import org.tests.model.basic.Order;
|
||||
import org.tests.model.basic.*;
|
||||
import org.tests.model.bridge.BSite;
|
||||
import org.tests.model.bridge.BUser;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class BeanDescriptorTest extends BaseTestCase {
|
||||
|
||||
@@ -88,6 +89,42 @@ public class BeanDescriptorTest extends BaseTestCase {
|
||||
assertThat(props).extracting("name").contains("id", "status", "orderDate", "shipDate");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchBaseTable() {
|
||||
BeanDescriptor<Customer> desc = getBeanDescriptor(Customer.class);
|
||||
assertTrue(desc.matchBaseTable("o_customer"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchBaseTable_whenTableHasSchema_expect_matchRegardlessOfSchema() {
|
||||
|
||||
DeployBeanDescriptor<Customer> deploy = mockDeployCustomer();
|
||||
|
||||
when(deploy.getBaseTable()).thenReturn("foo.o_customer");
|
||||
BeanDescriptor<?> desc1 = new BeanDescriptor<>(mockOwner(), deploy);
|
||||
assertTrue(desc1.matchBaseTable("o_customer"));
|
||||
|
||||
when(deploy.getBaseTable()).thenReturn("bar.o_customer");
|
||||
BeanDescriptor<?> desc2 = new BeanDescriptor<>(mockOwner(), deploy);
|
||||
assertTrue(desc2.matchBaseTable("o_customer"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private DeployBeanDescriptor<Customer> mockDeployCustomer() {
|
||||
DeployBeanDescriptor<Customer> deploy = mock(DeployBeanDescriptor.class);
|
||||
when(deploy.getBeanType()).thenReturn(Customer.class);
|
||||
when(deploy.getIdentityMode()).thenReturn(DeployIdentityMode.auto());
|
||||
when(deploy.buildIdentityMode()).thenReturn(IdentityMode.NONE);
|
||||
when(deploy.getCacheOptions()).thenReturn(CacheOptions.NO_CACHING);
|
||||
return deploy;
|
||||
}
|
||||
|
||||
private BeanDescriptorMap mockOwner() {
|
||||
BeanDescriptorMap owner = mock(BeanDescriptorMap.class);
|
||||
when(owner.createDocStoreBeanAdapter(any(), any())).thenReturn(mock(DocStoreBeanAdapter.class));
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void merge_when_empty() {
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ public class ParseFetchConfigTest {
|
||||
@Test
|
||||
public void parseLazy() {
|
||||
FetchConfig lazy = ParseFetchConfig.parse("lazy");
|
||||
assertThat(lazy.getBatchSize()).isEqualTo(10);
|
||||
assertThat(lazy.getBatchSize()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -46,7 +46,12 @@ public class MainMemoryLeak {
|
||||
config.addClass(ECachedBean.class);
|
||||
config.loadFromProperties();
|
||||
|
||||
Database server1 = DatabaseFactory.create(config);
|
||||
assert server1 != null;
|
||||
|
||||
// create again for #2193
|
||||
Database server = DatabaseFactory.create(config);
|
||||
assert server != null;
|
||||
|
||||
// create a string with 10k chars
|
||||
char[] c = new char[10_000];
|
||||
|
||||
@@ -25,6 +25,10 @@ public class PersonCacheEmail {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public PersonCacheEmail(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package org.tests.cache.personinfo;
|
||||
|
||||
import io.ebean.annotation.WhenCreated;
|
||||
import io.ebean.annotation.WhenModified;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Version;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.time.Instant;
|
||||
|
||||
@Entity
|
||||
public class PersonOther {
|
||||
|
||||
@Id
|
||||
@Size(max=128)
|
||||
private String id;
|
||||
|
||||
private String email;
|
||||
|
||||
@WhenCreated
|
||||
private Instant whenCreated;
|
||||
|
||||
@WhenModified
|
||||
private Instant whenModified;
|
||||
|
||||
@Version
|
||||
private long version;
|
||||
|
||||
public PersonOther(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public Instant getWhenCreated() {
|
||||
return whenCreated;
|
||||
}
|
||||
|
||||
public void setWhenCreated(Instant whenCreated) {
|
||||
this.whenCreated = whenCreated;
|
||||
}
|
||||
|
||||
public Instant getWhenModified() {
|
||||
return whenModified;
|
||||
}
|
||||
|
||||
public void setWhenModified(Instant whenModified) {
|
||||
this.whenModified = whenModified;
|
||||
}
|
||||
|
||||
public long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(long version) {
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.tests.cache.personinfo;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.DB;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestStringIdOnly extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void insert() {
|
||||
|
||||
PersonCacheEmail b0 = new PersonCacheEmail("IdOnly");
|
||||
DB.save(b0);
|
||||
|
||||
PersonCacheEmail found = DB.find(PersonCacheEmail.class, b0.getId());
|
||||
assertThat(found).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insert_whenIdOnly() {
|
||||
|
||||
PersonOther b0 = new PersonOther("IdOnly");
|
||||
DB.save(b0);
|
||||
|
||||
PersonOther found = DB.find(PersonOther.class, b0.getId());
|
||||
assertThat(found).isNotNull();
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,16 @@
|
||||
package org.tests.model.embedded;
|
||||
|
||||
import io.ebean.annotation.NotNull;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
import java.util.Date;
|
||||
|
||||
@Embeddable
|
||||
public class EEmbDatePeriod {
|
||||
|
||||
@NotNull
|
||||
Date date1;
|
||||
@NotNull
|
||||
Date date2;
|
||||
|
||||
public Date getDate1() {
|
||||
|
||||
@@ -169,22 +169,40 @@ public class TestQueryFindEach extends BaseTestCase {
|
||||
DB.find(OmBasicParent.class).delete();
|
||||
insertData();
|
||||
|
||||
test_setLazyLoadBatchSize_withFetchLazy();
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
try (final Transaction transaction = DB.beginTransaction()) {
|
||||
// DB.find(OmBasicParent.class).findList();
|
||||
DB.find(OmBasicChild.class)
|
||||
.setLazyLoadBatchSize(100)
|
||||
//.fetchQuery("parent","name")
|
||||
//.fetch("parent","name")
|
||||
.findEach(child -> {
|
||||
assertNotNull(child.getParent().getName());
|
||||
});
|
||||
}
|
||||
|
||||
DB.find(OmBasicChild.class)
|
||||
.setLazyLoadBatchSize(100)
|
||||
.findEach(child -> {
|
||||
assertNotNull(child.getParent().getName());
|
||||
});
|
||||
|
||||
final List<String> sql = LoggedSqlCollector.stop();
|
||||
assertThat(sql.size()).isLessThan(50);
|
||||
}
|
||||
|
||||
private void test_setLazyLoadBatchSize_withFetchLazy() {
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
DB.find(OmBasicParent.class)
|
||||
.setLazyLoadBatchSize(5)
|
||||
.fetchLazy("children")
|
||||
.setMaxRows(50)
|
||||
.findEach(it -> {
|
||||
it.getChildren().size();
|
||||
});
|
||||
|
||||
final List<String> sql = LoggedSqlCollector.stop();
|
||||
assertThat(sql).hasSize(11);
|
||||
assertThat(sql.get(0)).contains(" from om_basic_parent ");
|
||||
for (int i = 1; i < 11; i++) {
|
||||
assertThat(sql.get(i)).contains(" --bind(Array[5]");
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(batchSize = 40)
|
||||
private void insertData() {
|
||||
for (int i = 0; i < 150; i++) {
|
||||
|
||||
@@ -31,7 +31,7 @@ public class TestCustomerFinder extends BaseTestCase {
|
||||
runQueries();
|
||||
|
||||
StringBuilder buffer0 = new StringBuilder();
|
||||
server().getMetaInfoManager()
|
||||
DB.getDefault().getMetaInfoManager()
|
||||
.collectMetricsAsJson()
|
||||
.withHeader(false)
|
||||
.write(buffer0);
|
||||
@@ -45,7 +45,7 @@ public class TestCustomerFinder extends BaseTestCase {
|
||||
runQueries();
|
||||
|
||||
StringBuilder buffer1 = new StringBuilder();
|
||||
server().getMetaInfoManager()
|
||||
DB.getDefault().getMetaInfoManager()
|
||||
.collectMetricsAsJson()
|
||||
.withHeader(false)
|
||||
.write(buffer1);
|
||||
@@ -55,7 +55,6 @@ public class TestCustomerFinder extends BaseTestCase {
|
||||
assertThat(json1).contains("\"name\":\"txn.main\"");
|
||||
assertThat(json1).contains("\"name\":\"orm.Customer.findList\"");
|
||||
assertThat(json1).doesNotContain("\"sql\":\"select t0.id, t0.status, t0.name");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -85,7 +84,6 @@ public class TestCustomerFinder extends BaseTestCase {
|
||||
assertThat(customer.getName()).isEqualTo(customer1.getName());
|
||||
|
||||
assertThat(Customer.find.db().getName()).isEqualTo(DB.getDefault().getName());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -175,20 +173,27 @@ public class TestCustomerFinder extends BaseTestCase {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
// change default collect query plan threshold to 200 micros
|
||||
QueryPlanInit init0 = new QueryPlanInit();
|
||||
init0.setAll(true);
|
||||
init0.setThresholdMicros(2);
|
||||
final List<MetaQueryPlan> plans = server().getMetaInfoManager().queryPlanInit(init0);
|
||||
assertThat(plans.size()).isGreaterThan(1);
|
||||
|
||||
// the server has some plans
|
||||
runQueries();
|
||||
|
||||
// enable query plan bind capture on all plans threshold 100 micros
|
||||
// change query plan threshold to 100 micros
|
||||
QueryPlanInit init = new QueryPlanInit();
|
||||
init.setAll(true);
|
||||
init.setThresholdMicros(100);
|
||||
init.setThresholdMicros(1);
|
||||
final List<MetaQueryPlan> appliedToPlans = server().getMetaInfoManager().queryPlanInit(init);
|
||||
assertThat(appliedToPlans.size()).isGreaterThan(4);
|
||||
|
||||
// will collect bind captures
|
||||
// run queries again
|
||||
runQueries();
|
||||
|
||||
ServerMetrics metrics = server().getMetaInfoManager().collectMetrics();
|
||||
ServerMetrics metrics = DB.getDefault().getMetaInfoManager().collectMetrics();
|
||||
|
||||
List<MetaQueryMetric> planStats = metrics.getQueryMetrics();
|
||||
assertThat(planStats.size()).isGreaterThan(4);
|
||||
@@ -203,12 +208,21 @@ public class TestCustomerFinder extends BaseTestCase {
|
||||
|
||||
// obtains db query plans ...
|
||||
QueryPlanRequest request = new QueryPlanRequest();
|
||||
List<MetaQueryPlan> plans = server().getMetaInfoManager().queryPlanCollectNow(request);
|
||||
assertThat(plans).isNotEmpty();
|
||||
// collect max 1000 plans (use something more like 10)
|
||||
request.setMaxCount(1_000);
|
||||
// don't collect any more plans if used 10 secs
|
||||
request.setMaxTimeMillis(10_000);
|
||||
List<MetaQueryPlan> plans0 = server().getMetaInfoManager().queryPlanCollectNow(request);
|
||||
assertThat(plans0).isNotEmpty();
|
||||
|
||||
for (MetaQueryPlan plan : plans) {
|
||||
logger.info("queryplan label:{}, queryTimeMicros:{} loc:{} sql:{} bind:{} plan:{}",
|
||||
plan.getLabel(), plan.getQueryTimeMicros(), plan.getProfileLocation(),
|
||||
plan.getSql(), plan.getBind(), plan.getPlan());
|
||||
System.out.println(plan);
|
||||
}
|
||||
|
||||
//DB.getBackgroundExecutor().scheduleWithFixedDelay(...)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,38 +1,42 @@
|
||||
package org.tests.rawsql;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.RawSql;
|
||||
import io.ebean.RawSqlBuilder;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestRawSqlPositionedParams extends BaseTestCase {
|
||||
|
||||
private static final RawSql RAWSQL_1 = RawSqlBuilder
|
||||
.parse("select r.id, r.name from o_customer r where r.id >= ? and r.name like ?")
|
||||
.create();
|
||||
|
||||
private static final RawSql RAW_SQL_2 = RawSqlBuilder
|
||||
.unparsed("select r.id, r.name from o_customer r where r.id >= ? and r.name like ?")
|
||||
.columnMapping("r.id", "id")
|
||||
.columnMapping("r.name", "name")
|
||||
.create();
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
RawSql rawSql = RawSqlBuilder
|
||||
.parse("select r.id, r.name from o_customer r where r.id >= ? and r.name like ?")
|
||||
.create();
|
||||
List<Customer> list = DB.find(Customer.class)
|
||||
.setRawSql(RAWSQL_1)
|
||||
.setParameter(1)
|
||||
.setParameter("R%")
|
||||
.where().lt("id", 2001)
|
||||
.findList();
|
||||
|
||||
Query<Customer> query = Ebean.find(Customer.class);
|
||||
query.setRawSql(rawSql);
|
||||
query.setParameter(1, 1);
|
||||
query.setParameter(2, "R%");
|
||||
query.where().lt("id", 2001);
|
||||
|
||||
List<Customer> list = query.findList();
|
||||
|
||||
assertNotNull(list);
|
||||
assertThat(list).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -40,18 +44,12 @@ public class TestRawSqlPositionedParams extends BaseTestCase {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
RawSql rawSql = RawSqlBuilder
|
||||
.unparsed("select r.id, r.name from o_customer r where r.id >= ? and r.name like ?")
|
||||
.columnMapping("r.id", "id")
|
||||
.columnMapping("r.name", "name").create();
|
||||
List<Customer> list = DB.find(Customer.class)
|
||||
.setRawSql(RAW_SQL_2)
|
||||
.setParameter(1)
|
||||
.setParameter("R%")
|
||||
.findList();
|
||||
|
||||
Query<Customer> query = Ebean.find(Customer.class);
|
||||
query.setRawSql(rawSql);
|
||||
query.setParameter(1, 1);
|
||||
query.setParameter(2, "R%");
|
||||
|
||||
List<Customer> list = query.findList();
|
||||
|
||||
assertNotNull(list);
|
||||
assertThat(list).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,25 @@
|
||||
package org.tests.rawsql;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.RawSql;
|
||||
import io.ebean.RawSqlBuilder;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestRawSqlUnparsedQuery extends BaseTestCase {
|
||||
|
||||
private static final RawSql rawSql = RawSqlBuilder
|
||||
.unparsed("select r.id, r.name from o_customer r where r.id >= :a and r.name like :b")
|
||||
.columnMapping("r.id", "id")
|
||||
.columnMapping("r.name", "name")
|
||||
.create();
|
||||
|
||||
@Test
|
||||
public void testDoubleUnparsedQuery() {
|
||||
|
||||
@@ -25,17 +31,14 @@ public class TestRawSqlUnparsedQuery extends BaseTestCase {
|
||||
}
|
||||
|
||||
private static void test() {
|
||||
RawSql rawSql = RawSqlBuilder
|
||||
.unparsed("select r.id, r.name from o_customer r where r.id >= :a and r.name like :b")
|
||||
.columnMapping("r.id", "id").columnMapping("r.name", "name").create();
|
||||
|
||||
Query<Customer> query = Ebean.find(Customer.class);
|
||||
query.setRawSql(rawSql);
|
||||
query.setParameter("a", 1);
|
||||
query.setParameter("b", "R%");
|
||||
List<Customer> list = DB.find(Customer.class)
|
||||
.setRawSql(rawSql)
|
||||
.setParameter("a", 1)
|
||||
.setParameter("b", "R%")
|
||||
.findList();
|
||||
|
||||
List<Customer> list = query.findList();
|
||||
Assert.assertNotNull(list);
|
||||
assertThat(list).isNotNull();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,298 @@
|
||||
package org.tests.transparentpersist;
|
||||
|
||||
import io.ebean.*;
|
||||
import io.ebean.annotation.*;
|
||||
import io.ebeaninternal.api.SpiTransaction;
|
||||
import io.ebeantest.LoggedSql;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.EBasicVer;
|
||||
import org.tests.model.basic.Order;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestTransparentPersist extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void insertFlush_mutateFlush_expect_update() {
|
||||
|
||||
LoggedSql.start();
|
||||
|
||||
EBasicVer newBean;
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
transaction.setAutoPersistUpdates(true); // EXPERIMENTAL feature
|
||||
|
||||
newBean = new EBasicVer("insertMe");
|
||||
DB.save(newBean);
|
||||
|
||||
// flush - new bean needs to get registered into persistence context
|
||||
transaction.flush();
|
||||
|
||||
// make it dirty, we expect it to execute an update on flush()
|
||||
newBean.setName("make it dirty - auto save");
|
||||
|
||||
// flush again, auto persist dirty bean in persistence context
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
List<String> sql = LoggedSql.stop();
|
||||
|
||||
EBasicVer found = DB.find(EBasicVer.class, newBean.getId());
|
||||
assertThat(found.getName()).isEqualTo("make it dirty - auto save");
|
||||
|
||||
assertThat(sql).hasSize(4);
|
||||
assertThat(sql.get(0)).contains("insert into e_basicver");
|
||||
assertThat(sql.get(1)).contains(" -- bind(");
|
||||
assertThat(sql.get(2)).contains("update e_basicver set name=?, last_update=? where id=? and last_update=?");
|
||||
assertThat(sql.get(3)).contains(" -- bind(");
|
||||
|
||||
DB.delete(found);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void delete_expect_beanRemovedFromPersistenceContext() {
|
||||
|
||||
EBasicVer b0 = new EBasicVer("simpleDelete");
|
||||
DB.save(b0);
|
||||
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
transaction.setAutoPersistUpdates(true); // EXPERIMENTAL feature
|
||||
|
||||
EBasicVer found = DB.find(EBasicVer.class, b0.getId());
|
||||
// make it dirty
|
||||
found.setName("make it dirty");
|
||||
|
||||
// delete it, should remove it from the "live" part of persistence context
|
||||
// with the expectation that no update is executed (no dirty in PC update)
|
||||
DB.delete(found);
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
EBasicVer after = DB.find(EBasicVer.class, b0.getId());
|
||||
assertThat(after).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleInsertUpdateDelete_experimental() {
|
||||
|
||||
EBasicVer b0 = new EBasicVer("simpleIUD_0");
|
||||
b0.save();
|
||||
EBasicVer b1 = new EBasicVer("simpleIUD_1");
|
||||
b1.save();
|
||||
EBasicVer b2 = new EBasicVer("simpleIUD_2");
|
||||
b2.save();
|
||||
|
||||
EBasicVer newBean;
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
transaction.setAutoPersistUpdates(true); // EXPERIMENTAL feature
|
||||
|
||||
EBasicVer found = DB.find(EBasicVer.class, b0.getId());
|
||||
found.setName("auto dirty");
|
||||
|
||||
// delete by id
|
||||
DB.delete(EBasicVer.class, b1.getId());
|
||||
// find and delete, note the delete is batched up to execute later
|
||||
DB.delete(DB.find(EBasicVer.class, b2.getId()));
|
||||
|
||||
// insert is batched up to execute later
|
||||
newBean = new EBasicVer("simpleIUD_New1");
|
||||
DB.save(newBean);
|
||||
// can still mutate newBean before flush (but not after flush yet as new bean isn't put into Persistence context)
|
||||
newBean.setName("simpleIUD_New2");
|
||||
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
EBasicVer after = DB.find(EBasicVer.class, b0.getId());
|
||||
assertThat(after.getName()).isEqualTo("auto dirty");
|
||||
|
||||
EBasicVer wasInserted = DB.find(EBasicVer.class, newBean.getId());
|
||||
assertThat(wasInserted.getName()).isEqualTo("simpleIUD_New2");
|
||||
|
||||
assertThat(DB.find(EBasicVer.class, b1.getId())).isNull();
|
||||
assertThat(DB.find(EBasicVer.class, b2.getId())).isNull();
|
||||
|
||||
DB.delete(after);
|
||||
DB.delete(wasInserted);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleUpdate_experimental() {
|
||||
|
||||
EBasicVer transPersist = new EBasicVer("simulate_simpleUpdate");
|
||||
transPersist.save();
|
||||
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
transaction.setAutoPersistUpdates(true); // EXPERIMENTAL feature
|
||||
|
||||
EBasicVer found = DB.find(EBasicVer.class, transPersist.getId());
|
||||
found.setName("Persisted automatically as dirty");
|
||||
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
EBasicVer after = DB.find(EBasicVer.class,transPersist.getId());
|
||||
assertThat(after.getName()).isEqualTo("Persisted automatically as dirty");
|
||||
DB.delete(after);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateWithPersistCascadeInsert() {
|
||||
|
||||
// setup data
|
||||
Customer c0 = new Customer();
|
||||
c0.setName("firstCust");
|
||||
Order order = new Order();
|
||||
order.setStatus(Order.Status.NEW);
|
||||
order.setCustomer(c0);
|
||||
DB.save(order);
|
||||
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
transaction.setAutoPersistUpdates(true); // EXPERIMENTAL feature
|
||||
|
||||
Order foundOrder = DB.find(Order.class, order.getId());
|
||||
foundOrder.setStatus(Order.Status.APPROVED);
|
||||
// cascade persist will insert this customer (even though it isn't in the persistence context)
|
||||
Customer c1 = new Customer();
|
||||
c1.setName("newCust CascadePersist");
|
||||
foundOrder.setCustomer(c1);
|
||||
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
Order checkOrder = DB.find(Order.class, order.getId());
|
||||
|
||||
assertThat(checkOrder.getStatus()).isEqualTo(Order.Status.APPROVED);
|
||||
assertThat(checkOrder.getCustomer().getName()).isEqualTo("newCust CascadePersist");
|
||||
|
||||
DB.delete(checkOrder);
|
||||
DB.delete(Customer.class, checkOrder.getCustomer().getId());
|
||||
DB.delete(Customer.class, c0.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateReferenceOnlyWithPersistCascade_Insert_andUpdateForeignKey() {
|
||||
|
||||
// setup data
|
||||
Customer c0 = new Customer();
|
||||
c0.setName("firstCust");
|
||||
Order order = new Order();
|
||||
order.setStatus(Order.Status.NEW);
|
||||
order.setCustomer(c0);
|
||||
DB.save(order);
|
||||
|
||||
LoggedSql.start();
|
||||
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
transaction.setAutoPersistUpdates(true); // EXPERIMENTAL feature
|
||||
|
||||
Order foundOrder = DB.find(Order.class, order.getId());
|
||||
// we ONLY mutate the foreign key
|
||||
// cascade persist will insert this customer (even though it isn't in the persistence context)
|
||||
Customer c1 = new Customer();
|
||||
c1.setName("newCust CascadePersist");
|
||||
foundOrder.setCustomer(c1);
|
||||
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
List<String> sql = LoggedSql.stop();
|
||||
|
||||
Order checkOrder = DB.find(Order.class, order.getId());
|
||||
|
||||
assertThat(checkOrder.getStatus()).isEqualTo(Order.Status.NEW);
|
||||
assertThat(checkOrder.getCustomer().getName()).isEqualTo("newCust CascadePersist");
|
||||
|
||||
assertThat(sql).hasSize(5);
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.status, t0.order_date");
|
||||
assertThat(sql.get(1)).contains("insert into o_customer");
|
||||
assertThat(sql.get(2)).contains(" -- bind(");
|
||||
assertThat(sql.get(3)).contains("update o_order set updtime=?, kcustomer_id=? where id=? and updtime=?");
|
||||
assertThat(sql.get(4)).contains(" -- bind(");
|
||||
|
||||
DB.delete(checkOrder);
|
||||
DB.delete(Customer.class, checkOrder.getCustomer().getId());
|
||||
DB.delete(Customer.class, c0.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void txScope_setAutoPersistUpdates() {
|
||||
|
||||
EBasicVer b0 = new EBasicVer("txScopeUpdate");
|
||||
b0.save();
|
||||
|
||||
DB.execute(TxScope.required().setAutoPersistUpdates(TxOption.ON), () -> {
|
||||
EBasicVer found = DB.find(EBasicVer.class, b0.getId());
|
||||
found.setName("mutable txScope bean");
|
||||
});
|
||||
|
||||
EBasicVer after = DB.find(EBasicVer.class, b0.getId());
|
||||
assertThat(after.getName()).isEqualTo("mutable txScope bean");
|
||||
|
||||
DB.delete(after);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void txn_setAutoPersistUpdates() {
|
||||
|
||||
EBasicVer b0 = new EBasicVer("txn autoPersistUpdates ON");
|
||||
b0.save();
|
||||
|
||||
performUpdate(b0);
|
||||
|
||||
EBasicVer after = DB.find(EBasicVer.class, b0.getId());
|
||||
assertThat(after.getName()).isEqualTo("mutated with autoPersistUpdates ON");
|
||||
|
||||
DB.delete(after);
|
||||
}
|
||||
|
||||
@Transactional(autoPersistUpdates = TxOption.ON)
|
||||
private void performUpdate(EBasicVer b0) {
|
||||
EBasicVer found = DB.find(EBasicVer.class, b0.getId());
|
||||
found.setName("mutated with autoPersistUpdates ON");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simulate_transparentPersistence_forSimpleUpdate() {
|
||||
|
||||
EBasicVer transPersist = new EBasicVer("simulate_simpleUpdate");
|
||||
transPersist.save();
|
||||
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
transaction.setBatchMode(true);
|
||||
transaction.setBatchSize(10);
|
||||
|
||||
EBasicVer found = DB.find(EBasicVer.class, transPersist.getId());
|
||||
found.setName("Changed");
|
||||
|
||||
// simulate transparent persistence
|
||||
List<Object> dirtyBeans = simulateTransparentPersist(transaction);
|
||||
assertThat(dirtyBeans).hasSize(1);
|
||||
assertThat(dirtyBeans).contains(found);
|
||||
|
||||
// would occur as first part of flush
|
||||
transaction.flush();
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
EBasicVer after = DB.find(EBasicVer.class,transPersist.getId());
|
||||
assertThat(after.getName()).isEqualTo("Changed");
|
||||
DB.delete(after);
|
||||
}
|
||||
|
||||
private List<Object> simulateTransparentPersist(Transaction transaction) {
|
||||
Database db = DB.getDefault();
|
||||
List<Object> dirtyBeans = getDirtyBeansFromPersistenceContext(transaction);
|
||||
for (Object dirtyBean : dirtyBeans) {
|
||||
db.update(dirtyBean, transaction);
|
||||
}
|
||||
return dirtyBeans;
|
||||
}
|
||||
|
||||
private List<Object> getDirtyBeansFromPersistenceContext(Transaction transaction) {
|
||||
return ((SpiTransaction)transaction).getPersistenceContext().dirtyBeans();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user