Compare commits

..
Author SHA1 Message Date
rob bygrave 11586fb635 [maven-release-plugin] prepare release ebean-11.18.5 2018-07-15 16:09:00 +12:00
rob bygrave d555122067 #1453 - @Formula property included in DDL when on @Inheritance bean and without @Transient 2018-07-15 15:36:29 +12:00
rob bygrave b6d3dc3516 Fix test code only - Tune entity bean needs at least 1 non Id property 2018-07-15 15:01:17 +12:00
rob bygrave bbf54d6196 git push origin masterMerge branch 'FOCONIS-cache-bug-delete' 2018-07-15 14:13:48 +12:00
rob bygrave 74c88ce511 #1452 Fix - Deleting a bean does not invalidate the bean cache (Regression from 11.18.1 - introduced by changes in #1427) 2018-07-15 14:13:29 +12:00
rob bygrave 309bf6a11a Merge branch 'cache-bug-delete' of https://github.com/FOCONIS/ebean into FOCONIS-cache-bug-delete 2018-07-15 13:56:37 +12:00
rob bygrave 02b6ab0f74 No effective change, move null check on orderBy to prior to parse 2018-07-15 13:55:51 +12:00
rob bygrave 0c41993ce7 No effective change, whitespace 2018-07-15 13:55:15 +12:00
rob bygrave d949c48245 git push origin masterMerge branch 'tobias--bugfix/lazy_fetch_with_id_column_name' 2018-07-15 13:52:14 +12:00
rob bygrave 93e603ca25 #1449 Fix for failing lazy fetch when logical property name starts with underscore 2018-07-15 13:49:05 +12:00
rob bygrave 117d22fd67 Merge branch 'bugfix/lazy_fetch_with_id_column_name' of https://github.com/tobias-/ebean into tobias--bugfix/lazy_fetch_with_id_column_name 2018-07-15 13:11:33 +12:00
Roland Praml f13de2c8a6 ADD: Testcase for delete with cache 2018-07-13 19:57:56 +02:00
Mitsch164andRob Bygrave 5b8ef8154a Fix Transaction Flushing when ID Property is Loaded (#1450)
* Fix for unintentianal flush when ID is loaded

* fix duplicateKey Exception

* higher id
2018-07-12 15:10:17 +12:00
Tobias df892f4509 Failing testcase with lazy fetch
For some reason, all entities with an id starting with _ fails when
lazy-fetching due to sort not being properly renamed.
2018-07-11 15:52:56 +02:00
rob bygrave 2755e6d1ec [maven-release-plugin] prepare for next development iteration 2018-07-05 23:40:12 +12:00
rob bygrave 2024193da9 [maven-release-plugin] prepare release ebean-11.18.4 2018-07-05 23:39:56 +12:00
rob bygrave 72788c7428 No effective change - tidy test code 2018-07-05 22:41:28 +12:00
rob bygrave 8789709fb8 No effective change - tidy test code 2018-07-05 22:40:09 +12:00
rob bygrave 588aaf9361 #1447 - Delete query ... should honour cascading delete if defined
See also PR #1445 with the failing test case
2018-07-05 22:37:54 +12:00
Michael BenzandRob Bygrave 68649d0e98 Failing unit test to demonstrate the bug that deleting an entity via … (#1445)
* Failing unit test to demonstrate the bug that deleting an entity via an Ebean query does not respect the cascade setting.
(here a mapped optional OneToOne entity is not deleted using an Ebean query even if the CascadeType.ALL was used)

* moved init and cleanup code to @Before and @After JUnit methods and added another test that shows Ebean.delete() works as expected
2018-07-05 19:52:40 +12:00
rob bygrave f6047d3b73 [maven-release-plugin] prepare for next development iteration 2018-07-04 22:09:27 +12:00
rob bygrave 629e096e28 [maven-release-plugin] prepare release ebean-11.18.3 2018-07-04 22:09:12 +12:00
rob bygrave c981944c8e #1444 - JSON parsing with inheritance - java.lang.UnsupportedOperationException: cannot create entity bean for abstract entity ... 2018-07-04 21:26:17 +12:00
rob bygrave 1ba9f4e9de No effective change - Add simple profile query main 2018-07-04 21:25:36 +12:00
rob bygrave ce02e7ce70 No effective change - tidy tests 2018-07-04 21:25:10 +12:00
rob bygrave 1d9a2ed43a No effective change - tidy DJsonContext 2018-07-02 21:33:59 +12:00
rob bygrave ae81ce5f47 #1443 - Bump ebean-migration to 11.7.1 (which adds JdbcMigration support and "I" run first repeatable migrations) 2018-07-01 20:30:54 +12:00
rob bygrave 9e42f98902 [maven-release-plugin] prepare for next development iteration 2018-06-28 10:27:06 +12:00
34 changed files with 674 additions and 206 deletions
+3 -3
View File
@@ -9,7 +9,7 @@
<groupId>io.ebean</groupId>
<artifactId>ebean</artifactId>
<version>11.18.2</version>
<version>11.18.5</version>
<packaging>jar</packaging>
<name>ebean</name>
@@ -22,7 +22,7 @@
<scm>
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
<tag>ebean-11.18.2</tag>
<tag>ebean-11.18.5</tag>
</scm>
<profiles>
@@ -135,7 +135,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>11.6.1</version>
<version>11.7.1</version>
</dependency>
<dependency>
@@ -133,8 +133,7 @@ public class VisitAllUsing {
InheritInfo inheritInfo = descriptor.getInheritInfo();
if (inheritInfo != null && inheritInfo.isRoot()) {
// add all properties on the children objects
InheritChildVisitor childVisitor = new InheritChildVisitor(this, pv);
inheritInfo.visitChildren(childVisitor);
inheritInfo.visitChildren(new InheritChildVisitor(this, pv));
}
}
@@ -155,9 +154,10 @@ public class VisitAllUsing {
@Override
public void visit(InheritInfo inheritInfo) {
BeanProperty[] propertiesLocal = inheritInfo.desc().propertiesLocal();
for (BeanProperty aPropertiesLocal : propertiesLocal) {
owner.visit(pv, aPropertiesLocal);
for (BeanProperty beanProperty : inheritInfo.desc().propertiesLocal()) {
if (beanProperty.isDDLColumn()) {
owner.visit(pv, beanProperty);
}
}
}
}
@@ -1384,7 +1384,18 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
try {
request.initTransIfRequired();
request.markNotQueryOnly();
return request.delete();
if (request.isDeleteByStatement()) {
return request.delete();
} else {
// escalate to fetch the ids of the beans to delete due
// to cascading deletes or l2 caching etc
List<Object> ids = request.findIds();
if (ids.isEmpty()) {
return 0;
} else {
return persister.deleteByIds(request.getBeanDescriptor(), ids, request.getTransaction(), false);
}
}
} finally {
request.endTransIfRequired();
}
@@ -116,6 +116,11 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
}
}
@Override
public boolean isDeleteByStatement() {
return beanDescriptor.isDeleteByStatement();
}
@Override
public boolean isMultiValueIdSupported() {
return beanDescriptor.isMultiValueIdSupported();
@@ -356,7 +356,15 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
private boolean flushBatchOnGetter(int propertyIndex) {
// propertyIndex of -1 the Id property, no flush for get Id on UPDATE
return propertyIndex == -1 ? type == Type.INSERT : beanDescriptor.isGeneratedProperty(propertyIndex);
if (propertyIndex == -1) {
if (beanDescriptor.isIdLoaded(intercept)) {
return false;
} else {
return type == Type.INSERT;
}
} else {
return beanDescriptor.isGeneratedProperty(propertyIndex);
}
}
public void setSkipBatchForTopLevel() {
@@ -63,6 +63,11 @@ public interface Persister {
*/
int deleteMany(Class<?> beanType, Collection<?> ids, Transaction transaction, boolean permanent);
/**
* Delete multiple beans when escalated from a delete query.
*/
int deleteByIds(BeanDescriptor<?> descriptor, List<Object> idList, Transaction transaction, boolean permanent);
/**
* Execute the Update.
*/
@@ -171,4 +171,9 @@ public interface SpiOrmQueryRequest<T> extends BeanQueryRequest<T>, DocQueryRequ
* Set profile location for "find all" if not set.
*/
void profileLocationAll();
/**
* Return true if delete by statement is allowed for this type given cascade rules etc.
*/
boolean isDeleteByStatement();
}
@@ -291,6 +291,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
*/
protected final InheritInfo inheritInfo;
private final boolean abstractType;
/**
* Derived list of properties that make up the unique id.
*/
@@ -546,7 +548,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
this.whenCreatedProperty = findWhenCreatedProperty();
// derive the index position of the Id and Version properties
if (Modifier.isAbstract(beanType.getModifiers())) {
this.abstractType = Modifier.isAbstract(beanType.getModifiers());
if (abstractType) {
this.idPropertyIndex = -1;
this.versionPropertyIndex = -1;
this.unloadProperties = new int[0];
@@ -653,6 +656,13 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
return ebeanServer;
}
/**
* Return true if this is an abstract type.
*/
public boolean isAbstractType() {
return abstractType;
}
/**
* Return true if this is a "Doc Store only" entity bean.
*/
@@ -3150,6 +3160,10 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
public boolean hasIdPropertyOnly(EntityBeanIntercept ebi) {
return ebi.hasIdOnly(idPropertyIndex);
}
public boolean isIdLoaded(EntityBeanIntercept ebi) {
return ebi.isLoadedProperty(idPropertyIndex);
}
public boolean hasIdValue(EntityBean bean) {
return (idProperty != null && !DmlUtil.isNullOrZero(idProperty.getValue(bean)));
@@ -3433,11 +3447,11 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
}
public T jsonRead(SpiJsonReader jsonRead, String path) throws IOException {
return jsonHelp.jsonRead(jsonRead, path);
return jsonHelp.jsonRead(jsonRead, path, true);
}
protected T jsonReadObject(SpiJsonReader jsonRead, String path) throws IOException {
return jsonHelp.jsonReadObject(jsonRead, path);
public T jsonReadObject(SpiJsonReader jsonRead, String path) throws IOException {
return jsonHelp.jsonRead(jsonRead, path, false);
}
public List<BeanProperty[]> getUniqueProps() {
@@ -739,6 +739,7 @@ final class BeanDescriptorCacheHelp<T> {
if (invalidateQueryCache) {
changeSet.addInvalidate(desc);
} else {
queryCacheClear(changeSet);
if (beanCache != null) {
changeSet.addBeanRemoveMany(desc, ids);
}
@@ -3,6 +3,8 @@ package io.ebeaninternal.server.deploy;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.ebean.bean.EntityBean;
import io.ebean.text.json.EJson;
import io.ebeaninternal.api.json.SpiJsonReader;
@@ -12,18 +14,18 @@ import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
public class BeanDescriptorJsonHelp<T> {
class BeanDescriptorJsonHelp<T> {
private final BeanDescriptor<T> desc;
private final InheritInfo inheritInfo;
public BeanDescriptorJsonHelp(BeanDescriptor<T> desc) {
BeanDescriptorJsonHelp(BeanDescriptor<T> desc) {
this.desc = desc;
this.inheritInfo = desc.inheritInfo;
}
public void jsonWrite(SpiJsonWriter writeJson, EntityBean bean, String key) throws IOException {
void jsonWrite(SpiJsonWriter writeJson, EntityBean bean, String key) throws IOException {
writeJson.writeStartObject(key);
@@ -42,13 +44,11 @@ public class BeanDescriptorJsonHelp<T> {
writeJson.writeEndObject();
}
protected void jsonWriteProperties(SpiJsonWriter writeJson, EntityBean bean) throws IOException {
void jsonWriteProperties(SpiJsonWriter writeJson, EntityBean bean) {
writeJson.writeBean(desc, bean);
}
public void jsonWriteDirty(SpiJsonWriter writeJson, EntityBean bean, boolean[] dirtyProps) throws IOException {
void jsonWriteDirty(SpiJsonWriter writeJson, EntityBean bean, boolean[] dirtyProps) throws IOException {
if (inheritInfo == null) {
jsonWriteDirtyProperties(writeJson, bean, dirtyProps);
} else {
@@ -56,7 +56,7 @@ public class BeanDescriptorJsonHelp<T> {
}
}
protected void jsonWriteDirtyProperties(SpiJsonWriter writeJson, EntityBean bean, boolean[] dirtyProps) throws IOException {
void jsonWriteDirtyProperties(SpiJsonWriter writeJson, EntityBean bean, boolean[] dirtyProps) throws IOException {
writeJson.writeStartObject(null);
// render the dirty properties
@@ -70,7 +70,7 @@ public class BeanDescriptorJsonHelp<T> {
}
@SuppressWarnings("unchecked")
public T jsonRead(SpiJsonReader jsonRead, String path) throws IOException {
T jsonRead(SpiJsonReader jsonRead, String path, boolean withInheritance) throws IOException {
JsonParser parser = jsonRead.getParser();
//noinspection StatementWithEmptyBody
@@ -87,43 +87,39 @@ public class BeanDescriptorJsonHelp<T> {
}
}
if (desc.inheritInfo == null) {
if (desc.inheritInfo == null || !withInheritance) {
return jsonReadObject(jsonRead, path);
}
ObjectNode node = jsonRead.getObjectMapper().readTree(parser);
if (node.isNull()) {
return null;
}
JsonParser newParser = node.traverse();
SpiJsonReader newReader = jsonRead.forJson(newParser, false);
// check for the discriminator value to determine the correct sub type
String discColumn = inheritInfo.getRoot().getDiscriminatorColumn();
if (parser.nextToken() != JsonToken.FIELD_NAME) {
String msg = "Error reading inheritance discriminator - expected [" + discColumn + "] but no json key?";
throw new JsonParseException(parser, msg, parser.getCurrentLocation());
}
String propName = parser.getCurrentName();
if (!propName.equalsIgnoreCase(discColumn)) {
// just try to assume this is the correct bean type in the inheritance
BeanProperty property = desc.getBeanProperty(propName);
if (property != null) {
EntityBean bean = desc.createEntityBean();
property.jsonRead(jsonRead, bean);
return jsonReadProperties(jsonRead, bean, path);
JsonNode discNode = node.get(discColumn);
if (discNode == null || discNode.isNull()) {
if (!desc.isAbstractType()) {
return desc.jsonReadObject(newReader, path);
}
String msg = "Error reading inheritance discriminator, expected property [" + discColumn + "] but got [" + propName + "] ?";
throw new JsonParseException(parser, msg, parser.getCurrentLocation());
String msg = "Error reading inheritance discriminator - expected [" + discColumn + "] but no json key?";
throw new JsonParseException(newParser, msg, parser.getCurrentLocation());
}
String discValue = parser.nextTextValue();
return (T) inheritInfo.readType(discValue).desc().jsonReadObject(jsonRead, path);
return (T) inheritInfo.readType(discNode.asText()).desc().jsonReadObject(newReader, path);
}
protected T jsonReadObject(SpiJsonReader readJson, String path) throws IOException {
private T jsonReadObject(SpiJsonReader readJson, String path) throws IOException {
EntityBean bean = desc.createEntityBeanForJson();
return jsonReadProperties(readJson, bean, path);
}
@SuppressWarnings("unchecked")
protected T jsonReadProperties(SpiJsonReader readJson, EntityBean bean, String path) throws IOException {
private T jsonReadProperties(SpiJsonReader readJson, EntityBean bean, String path) throws IOException {
if (path != null) {
readJson.pushPath(path);
@@ -187,6 +187,6 @@ public abstract class DeployParser {
}
private boolean isWordStart(char ch) {
return Character.isLetter(ch);
return Character.isLetter(ch) || ch == UNDERSCORE;
}
}
@@ -151,7 +151,6 @@ public class InheritInfo {
* Set the descriptor for this node.
*/
public void setDescriptor(BeanDescriptor<?> descriptor) {
this.descriptor = descriptor;
}
@@ -1,5 +1,6 @@
package io.ebeaninternal.server.deploy.meta;
import io.ebean.bean.EntityBean;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.BeanDescriptorMap;
import io.ebeaninternal.server.deploy.BeanProperty;
@@ -11,6 +12,7 @@ import io.ebeaninternal.server.deploy.BeanPropertySimpleCollection;
import io.ebeaninternal.server.deploy.InheritInfo;
import io.ebeaninternal.server.deploy.TableJoin;
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedProperty;
import io.ebeaninternal.server.properties.BeanPropertySetter;
import io.ebeaninternal.server.type.ScalarTypeString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -26,6 +28,8 @@ public class DeployBeanPropertyLists {
private static final Logger logger = LoggerFactory.getLogger(DeployBeanPropertyLists.class);
private static final NoopSetter NOOP_SETTER = new NoopSetter();
private BeanProperty versionProperty;
private BeanProperty unmappedJson;
@@ -100,6 +104,7 @@ public class DeployBeanPropertyLists {
discDeployProp.setDiscriminator();
discDeployProp.setName(discriminatorColumn);
discDeployProp.setDbColumn(discriminatorColumn);
discDeployProp.setSetter(NOOP_SETTER);
// only register it in the propertyMap. This might not be used if
// an explicit property is mapped to the discriminator on the bean
@@ -491,4 +496,17 @@ public class DeployBeanPropertyLists {
return new BeanProperty(desc, deployProp);
}
private static class NoopSetter implements BeanPropertySetter {
@Override
public void set(EntityBean bean, Object value) {
// do nothing
}
@Override
public void setIntercept(EntityBean bean, Object value) {
// do nothing
}
}
}
@@ -680,6 +680,12 @@ public final class DefaultPersister implements Persister {
return delete(descriptor, id, null, transaction, deleteMode);
}
@Override
public int deleteByIds(BeanDescriptor<?> descriptor, List<Object> idList, Transaction transaction, boolean permanent) {
DeleteMode deleteMode = (permanent || !descriptor.isSoftDelete()) ? DeleteMode.HARD : DeleteMode.SOFT;
return delete(descriptor, null, idList, transaction, deleteMode);
}
/**
* Delete by Id or a List of Id's.
*/
@@ -739,18 +745,20 @@ public final class DefaultPersister implements Persister {
// OneToMany's with delete cascade
BeanPropertyAssocMany<?>[] manys = descriptor.propertiesManyDelete();
for (BeanPropertyAssocMany<?> many : manys) {
BeanDescriptor<?> targetDesc = many.getTargetDescriptor();
// only cascade soft deletes when supported by target
if (deleteMode.isHard() || targetDesc.isSoftDelete()) {
if (deleteMode.isHard() && targetDesc.isDeleteByStatement()) {
// we can just delete children with a single statement
SqlUpdate sqlDelete = many.deleteByParentId(id, idList);
executeSqlUpdate(sqlDelete, t);
} else {
// we need to fetch the Id's to delete (recurse or notify L2 cache)
List<Object> childIds = many.findIdsByParentId(id, idList, t, null);
if (!childIds.isEmpty()) {
delete(targetDesc, null, childIds, t, deleteMode);
if (!many.isManyToMany()) {
BeanDescriptor<?> targetDesc = many.getTargetDescriptor();
// only cascade soft deletes when supported by target
if (deleteMode.isHard() || targetDesc.isSoftDelete()) {
if (deleteMode.isHard() && targetDesc.isDeleteByStatement()) {
// we can just delete children with a single statement
SqlUpdate sqlDelete = many.deleteByParentId(id, idList);
executeSqlUpdate(sqlDelete, t);
} else {
// we need to fetch the Id's to delete (recurse or notify L2 cache)
List<Object> childIds = many.findIdsByParentId(id, idList, t, null);
if (!childIds.isEmpty()) {
delete(targetDesc, null, childIds, t, deleteMode);
}
}
}
}
@@ -2,7 +2,6 @@ package io.ebeaninternal.server.query;
import io.ebean.OrderBy;
import io.ebean.OrderBy.Property;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.BeanProperty;
import io.ebeaninternal.server.deploy.BeanPropertyAssoc;
@@ -18,27 +17,22 @@ class CQueryOrderBy {
private final BeanDescriptor<?> desc;
private final SpiQuery<?> query;
private final OrderBy<?> orderBy;
/**
* Create the logical order by clause.
*/
public static String parse(BeanDescriptor<?> desc, SpiQuery<?> query) {
return new CQueryOrderBy(desc, query).parseInternal();
public static String parse(BeanDescriptor<?> desc, OrderBy<?> orderBy) {
return new CQueryOrderBy(desc, orderBy).parseInternal();
}
private CQueryOrderBy(BeanDescriptor<?> desc, SpiQuery<?> query) {
private CQueryOrderBy(BeanDescriptor<?> desc, OrderBy<?> orderBy) {
this.desc = desc;
this.query = query;
this.orderBy = orderBy;
}
private String parseInternal() {
OrderBy<?> orderBy = query.getOrderBy();
if (orderBy == null) {
return null;
}
StringBuilder sb = new StringBuilder();
List<Property> properties = orderBy.getProperties();
@@ -1,5 +1,6 @@
package io.ebeaninternal.server.query;
import io.ebean.OrderBy;
import io.ebeaninternal.api.BindParams;
import io.ebeaninternal.api.SpiExpressionList;
import io.ebeaninternal.api.SpiQuery;
@@ -329,7 +330,11 @@ public class CQueryPredicates {
private String parseOrderBy() {
return CQueryOrderBy.parse(request.getBeanDescriptor(), query);
OrderBy<?> orderBy = query.getOrderBy();
if (orderBy == null) {
return null;
}
return CQueryOrderBy.parse(request.getBeanDescriptor(), orderBy);
}
/**
@@ -47,8 +47,6 @@ public class DJsonContext implements SpiJsonContext {
private final JsonFactory jsonFactory;
private final TypeManager typeManager;
private final Object defaultObjectMapper;
private final JsonConfig.Include defaultInclude;
@@ -57,11 +55,10 @@ public class DJsonContext implements SpiJsonContext {
public DJsonContext(SpiEbeanServer server, JsonFactory jsonFactory, TypeManager typeManager) {
this.server = server;
this.typeManager = typeManager;
this.jsonFactory = (jsonFactory != null) ? jsonFactory : new JsonFactory();
this.defaultObjectMapper = this.server.getServerConfig().getObjectMapper();
this.defaultInclude = this.server.getServerConfig().getJsonInclude();
this.jsonScalar = new DJsonScalar(this.typeManager);
this.jsonScalar = new DJsonScalar(typeManager);
}
@Override
@@ -121,9 +118,8 @@ public class DJsonContext implements SpiJsonContext {
public <T> T toBean(Class<T> cls, JsonParser parser, JsonReadOptions options) throws JsonIOException {
BeanDescriptor<T> desc = getDescriptor(cls);
SpiJsonReader readJson = new ReadJson(desc, parser, options, determineObjectMapper(options));
try {
return desc.jsonRead(readJson, null);
return desc.jsonRead(new ReadJson(desc, parser, options, determineObjectMapper(options)), null);
} catch (IOException e) {
throw new JsonIOException(e);
}
@@ -133,8 +129,7 @@ public class DJsonContext implements SpiJsonContext {
public <T> DJsonBeanReader<T> createBeanReader(Class<T> cls, JsonParser parser, JsonReadOptions options) throws JsonIOException {
BeanDescriptor<T> desc = getDescriptor(cls);
SpiJsonReader readJson = new ReadJson(desc, parser, options, determineObjectMapper(options));
return new DJsonBeanReader<>(desc, readJson);
return new DJsonBeanReader<>(desc, new ReadJson(desc, parser, options, determineObjectMapper(options)));
}
@Override
@@ -354,8 +349,7 @@ public class DJsonContext implements SpiJsonContext {
@Override
public SpiJsonWriter createJsonWriter(Writer writer) {
JsonGenerator generator = createGenerator(writer);
return createJsonWriter(generator, null);
return createJsonWriter(createGenerator(writer), null);
}
@Override
@@ -375,9 +369,7 @@ public class DJsonContext implements SpiJsonContext {
gen.writeFieldName(key);
}
gen.writeStartArray();
WriteJson writeJson = createWriteJson(gen, options);
for (T bean : collection) {
BeanDescriptor<?> d = getDescriptor(bean.getClass());
d.jsonWrite(writeJson, (EntityBean) bean, null);
@@ -0,0 +1,76 @@
package org.tests.basic.delete;
import static org.assertj.core.api.Assertions.assertThat;
import io.ebean.BaseTestCase;
import io.ebean.Ebean;
import io.ebean.Query;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.tests.model.onetoone.OtoUser;
import org.tests.model.onetoone.OtoUserOptional;
public class TestDeleteCascadeByQuery extends BaseTestCase {
private OtoUser testUser;
private OtoUserOptional userOptional;
private Query<OtoUserOptional> userOptionalQuery = Ebean.find(OtoUserOptional.class);
private Query<OtoUser> userQuery = Ebean.find(OtoUser.class);
/**
* Init each test. Delete all existing beans. Then create OtoUser, add OtoUserOptional and save.
*/
@Before
public void init() {
Ebean.deleteAll(userQuery.findList());
Ebean.deleteAll(userOptionalQuery.findList());
userOptional = new OtoUserOptional();
Ebean.save(userOptional);
testUser = new OtoUser();
testUser.setOptional(userOptional);
Ebean.save(testUser);
}
/**
* Test that validates deleting a bean using Ebean.delete() respects the CascadeType.DELETE
* setting.
*/
@Test
public void testDeleteCascadeByEbeanDelete() {
assertThat(Ebean.delete(testUser)).isTrue();
assertThat(userOptionalQuery.findCount())
.overridingErrorMessage("Entity OtoUserOptional found. Ebean.delete() on the user "
+ "did not delete the OneToOne mapped entity as set with CascadeType.ALL")
.isEqualTo(0);
}
/**
* Test that validates deleting a bean with OneToOne mapping with a query respects the
* CascadeType.DELETE setting.
*/
@Test
public void testDeleteCascadeByQuery() {
assertThat(userQuery.delete()).isEqualTo(1);
assertThat(userOptionalQuery.findCount())
.overridingErrorMessage("Entity OtoUserOptional found. Ebean query delete() on the user "
+ "did not delete the OneToOne mapped entity as set with CascadeType.ALL")
.isEqualTo(0);
}
/**
* Cleanup - Delete all existing beans for the next test.
*/
@After
public void cleanup() {
Ebean.deleteAll(userQuery.findList());
Ebean.deleteAll(userOptionalQuery.findList());
}
}
@@ -122,15 +122,20 @@ public class TestBatchInsertFlush extends BaseTestCase {
public void transactional_flushOnGetId() {
EbeanServer server = Ebean.getDefaultServer();
LoggedSqlCollector.start();
EBasicVer b1 = new EBasicVer("b1");
server.save(b1);
EBasicVer b2 = new EBasicVer("b2");
server.save(b2);
//flush here
assertThat(LoggedSqlCollector.current()).isEmpty();
Integer id = b1.getId();
assertNotNull(id);
assertThat(LoggedSqlCollector.current()).hasSize(2);
EBasicVer b3 = new EBasicVer("b3");
server.save(b3);
}
@@ -141,7 +146,8 @@ public class TestBatchInsertFlush extends BaseTestCase {
EbeanServer server = Ebean.getDefaultServer();
Transaction txn = server.beginTransaction();
try {
txn.setBatch(PersistBatch.ALL);
LoggedSqlCollector.start();
txn.setBatchMode(true);
EBasicVer b1 = new EBasicVer("b1");
server.save(b1, txn);
@@ -149,8 +155,11 @@ public class TestBatchInsertFlush extends BaseTestCase {
EBasicVer b2 = new EBasicVer("b2");
server.save(b2, txn);
//flush here
assertThat(LoggedSqlCollector.current()).isEmpty();
Integer id = b1.getId();
assertNotNull(id);
assertThat(LoggedSqlCollector.current()).hasSize(2);
EBasicVer b3 = new EBasicVer("b3");
server.save(b3, txn);
@@ -161,6 +170,67 @@ public class TestBatchInsertFlush extends BaseTestCase {
txn.end();
}
}
@Test
@Transactional(batch = PersistBatch.ALL)
public void transactional_noflushWhenIdIsLoaded() {
EbeanServer server = Ebean.getDefaultServer();
LoggedSqlCollector.start();
EBasicVer b1 = new EBasicVer("b1");
b1.setId(78965);
server.save(b1);
EBasicVer b2 = new EBasicVer("b2");
b2.setId(78645);
server.save(b2);
assertThat(LoggedSqlCollector.current()).isEmpty();
// dont flush here
Integer id = b1.getId();
assertNotNull(id);
assertThat(LoggedSqlCollector.current()).isEmpty();
EBasicVer b3 = new EBasicVer("b3");
server.save(b3);
}
@Test
public void noflushWhenIdIsLoaded() {
EbeanServer server = Ebean.getDefaultServer();
Transaction txn = server.beginTransaction();
try {
LoggedSqlCollector.start();
txn.setBatchMode(true);
EBasicVer b1 = new EBasicVer("b1");
b1.setId(546864);
server.save(b1, txn);
EBasicVer b2 = new EBasicVer("b2");
b2.setId(21354);
server.save(b2, txn);
assertThat(LoggedSqlCollector.current()).isEmpty();
//dont flush here
Integer id = b1.getId();
assertNotNull(id);
assertThat(LoggedSqlCollector.current()).isEmpty();
EBasicVer b3 = new EBasicVer("b3");
server.save(b3, txn);
txn.commit();
assertThat(LoggedSqlCollector.current()).hasSize(3);
} finally {
txn.end();
}
}
@Test
public void testFlushOnGetProperty() {
@@ -7,7 +7,9 @@ import io.ebean.Query;
import io.ebean.annotation.IgnorePlatform;
import io.ebean.annotation.Platform;
import org.tests.model.basic.BBookmarkUser;
import org.tests.model.basic.Contact;
import org.tests.model.basic.Country;
import org.tests.model.basic.Customer;
import org.tests.model.basic.ResetBasicData;
import org.ebeantest.LoggedSqlCollector;
@@ -22,7 +24,46 @@ public class TestDeleteByQuery extends BaseTestCase {
@Test
@IgnorePlatform(Platform.MYSQL)
// FIXME: MySql does not the sub query selecting from the delete table
public void test() {
public void deleteWithSubquery() {
EbeanServer server = Ebean.getDefaultServer();
BBookmarkUser u1 = new BBookmarkUser("u1");
Ebean.save(u1);
Query<BBookmarkUser> query = server.find(BBookmarkUser.class)
.where().eq("org.name", "NahYeahMaybe")
.query();
LoggedSqlCollector.start();
query.delete();
List<String> loggedSql = LoggedSqlCollector.stop();
assertThat(loggedSql).hasSize(1);
assertThat(trimSql(loggedSql.get(0), 1)).contains("delete from bbookmark_user where id in (select t0.id from bbookmark_user t0 left join bbookmark_org t1 on t1.id = t0.org_id where t1.name");
Query<BBookmarkUser> query2 = server.find(BBookmarkUser.class)
.where().eq("name", "NotARealFirstName").query();
LoggedSqlCollector.start();
query2.delete();
loggedSql = LoggedSqlCollector.stop();
assertThat(loggedSql).hasSize(1);
assertThat(loggedSql.get(0)).contains("delete from bbookmark_user where name =");
server.find(BBookmarkUser.class).select("id").where().eq("name", "NotARealFirstName").delete();
server.find(BBookmarkUser.class).select("id").where().eq("name", "TwoAlsoNotRealFirstName").query().delete();
List<BBookmarkUser> list = server.find(BBookmarkUser.class).select("id").where().eq("name", "NotARealFirstName").findList();
assertThat(list).isEmpty();
}
@Test
@IgnorePlatform(Platform.MYSQL)
// FIXME: MySql does not the sub query selecting from the delete table
public void deleteWithSubquery_withEscalation() {
EbeanServer server = Ebean.getDefaultServer();
@@ -33,7 +74,7 @@ public class TestDeleteByQuery extends BaseTestCase {
List<String> loggedSql = LoggedSqlCollector.stop();
assertThat(loggedSql).hasSize(1);
assertThat(trimSql(loggedSql.get(0), 1)).contains("delete from contact where id in (select t0.id from contact t0 left join");
assertThat(trimSql(loggedSql.get(0), 1)).contains("select t0.id from contact t0 left join contact_group t1 on t1.id = t0.group_id where t1.name = ?");
Query<Contact> query2 = server.find(Contact.class).where().eq("firstName", "NotARealFirstName").query();
@@ -42,7 +83,7 @@ public class TestDeleteByQuery extends BaseTestCase {
loggedSql = LoggedSqlCollector.stop();
assertThat(loggedSql).hasSize(1);
assertThat(loggedSql.get(0)).contains("delete from contact where first_name =");
assertThat(loggedSql.get(0)).contains("select t0.id from contact t0 where t0.first_name = ?");
server.find(Contact.class).select("id").where().eq("firstName", "NotARealFirstName").delete();
@@ -57,12 +98,29 @@ public class TestDeleteByQuery extends BaseTestCase {
LoggedSqlCollector.start();
Ebean.find(BBookmarkUser.class).where().eq("id", 7000).delete();
Ebean.find(BBookmarkUser.class).setId(7000).delete();
List<String> sql = LoggedSqlCollector.stop();
assertThat(sql.get(0)).contains("delete from bbookmark_user where id = ?");
assertThat(sql.get(1)).contains("delete from bbookmark_user where id = ?");
// and note this is the easiest option
Ebean.delete(BBookmarkUser.class, 7000);
}
@Test
public void queryByIdDelete_withEscalation() {
LoggedSqlCollector.start();
Ebean.find(Contact.class).where().eq("id", 7000).delete();
Ebean.find(Contact.class).setId(7000).delete();
List<String> sql = LoggedSqlCollector.stop();
assertThat(sql.get(0)).contains("delete from contact where id = ?");
assertThat(sql.get(1)).contains("delete from contact where id = ?");
// escalate to fetch ids then delete ... but no rows found
assertThat(sql.get(0)).contains("select t0.id from contact t0 where t0.id = ?");
assertThat(sql.get(1)).contains("select t0.id from contact t0 where t0.id = ?");
// and note this is the easiest option
Ebean.delete(Contact.class, 7000);
@@ -80,11 +138,23 @@ public class TestDeleteByQuery extends BaseTestCase {
List<String> sql = LoggedSqlCollector.stop();
assertThat(sql).hasSize(1);
assertThat(sql.get(0)).contains("delete from o_customer where name = ?");
assertThat(sql.get(0)).contains("select t0.id from o_customer t0 where t0.name = ?");
}
@Test
public void testCommit() {
public void deleteByPredicate() {
BBookmarkUser ud = new BBookmarkUser("deleteQueryByPredicate");
Ebean.save(ud);
Ebean.find(BBookmarkUser.class).where().eq("name", "deleteQueryByPredicate").delete();
BBookmarkUser found = Ebean.find(BBookmarkUser.class, ud.getId());
assertThat(found).isNull();
}
@Test
public void deleteByPredicate_withEscalation() {
ResetBasicData.reset();
@@ -101,4 +171,22 @@ public class TestDeleteByQuery extends BaseTestCase {
Contact contactFind = Ebean.find(Contact.class, contact.getId());
assertThat(contactFind).isNull();
}
@Test
public void deleteByPredicateCached() {
Country country = new Country();
country.setCode("XX");
country.setName("SecretName");
Ebean.save(country);
Query<Country> query = Ebean.find(Country.class).where().eq("name", "SecretName").setUseQueryCache(true);
assertThat(query.findList()).hasSize(1);
assertThat(query.findCount()).isEqualTo(1);
Ebean.find(Country.class).where().eq("name", "SecretName").delete();
//Ebean.getDefaultServer().getPluginApi().getBeanType(Country.class).clearQueryCache();
assertThat(query.findList()).hasSize(0);
assertThat(query.findCount()).isEqualTo(0);
}
}
@@ -26,44 +26,26 @@ public class BBookmark {
@Column
private BBookmarkUser user;
/**
* @return the id
*/
public Integer getId() {
return this.id;
}
/**
* @param id the id to set
*/
public void setId(final Integer id) {
this.id = id;
}
/**
* @return the bookmarkReference
*/
public String getBookmarkReference() {
return this.bookmarkReference;
}
/**
* @param bookmarkReference the bookmarkReference to set
*/
public void setBookmarkReference(final String bookmarkReference) {
this.bookmarkReference = bookmarkReference;
}
/**
* @return the user
*/
public BBookmarkUser getUser() {
return this.user;
}
/**
* @param user the user to set
*/
public void setUser(final BBookmarkUser user) {
this.user = user;
}
@@ -0,0 +1,35 @@
package org.tests.model.basic;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class BBookmarkOrg {
@Id
@GeneratedValue
private int id;
private String name;
public BBookmarkOrg(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@@ -1,13 +1,11 @@
package org.tests.model.basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
/**
* represents a user entity. A user contains a username and password.
*
* @author Chris
*/
@Entity
@@ -17,97 +15,69 @@ public class BBookmarkUser {
@GeneratedValue
private Integer id;
@Column
private String name;
@Column
private String password;
@Column
private String emailAddress;
@Column
private String country;
// @Version
// private Timestamp lastUpdate;
/**
* @return the id
* An optional non-cascading ManyToOne.
*/
@ManyToOne
private BBookmarkOrg org;
public BBookmarkUser(String name) {
this.name = name;
}
public Integer getId() {
return this.id;
}
/**
* @param id the id to set
*/
public void setId(final Integer id) {
this.id = id;
}
/**
* @return the password
*/
public String getPassword() {
return this.password;
}
/**
* @param password the password to set
*/
public void setPassword(final String password) {
this.password = password;
}
/**
* @return the name
*/
public String getName() {
return this.name;
}
/**
* @param name the name to set
*/
public void setName(final String name) {
this.name = name;
}
/**
* @return the emailAddress
*/
public String getEmailAddress() {
return this.emailAddress;
}
/**
* @param emailAddress the emailAddress to set
*/
public void setEmailAddress(final String emailAddress) {
this.emailAddress = emailAddress;
}
/**
* @return the country
*/
public String getCountry() {
return this.country;
}
/**
* @param country the country to set
*/
public void setCountry(final String country) {
this.country = country;
}
// public Timestamp getLastUpdate() {
// return lastUpdate;
// }
//
// public void setLastUpdate(Timestamp lastUpdate) {
// this.lastUpdate = lastUpdate;
// }
public BBookmarkOrg getOrg() {
return org;
}
public void setOrg(BBookmarkOrg org) {
this.org = org;
}
}
@@ -1,5 +1,7 @@
package org.tests.model.basic;
import io.ebean.annotation.Formula;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@@ -9,6 +11,9 @@ public class Cat extends Animal {
String name;
@Formula(select = "${ta}.species")
String catFormula;
public String getName() {
return name;
}
@@ -17,4 +22,11 @@ public class Cat extends Animal {
this.name = name;
}
public String getCatFormula() {
return catFormula;
}
public void setCatFormula(String catFormula) {
this.catFormula = catFormula;
}
}
@@ -8,14 +8,13 @@ import io.ebean.annotation.TxType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.persistence.EntityNotFoundException;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class DummyDao {
Logger logger = LoggerFactory.getLogger(DummyDao.class);
private final Logger logger = LoggerFactory.getLogger(DummyDao.class);
@Transactional(type = TxType.REQUIRES_NEW)
public void doSomething() {
@@ -30,18 +29,12 @@ public class DummyDao {
}
@Transactional
public void addToObject(Long id, Double anotherNumber, List<Long> ids) throws EntityNotFoundException {
// and more code
}
@Transactional(batch = PersistBatch.ALL, batchOnCascade = PersistBatch.ALL, batchSize = 99)
public void doWithBatchOptionsSet() {
private void doWithBatchOptionsSet() {
Transaction txn = Ebean.currentTransaction();
assertEquals(PersistBatch.ALL, txn.getBatch());
assertEquals(PersistBatch.ALL, txn.getBatchOnCascade());
assertTrue(txn.isBatchMode());
assertTrue(txn.isBatchOnCascade());
assertEquals(99, txn.getBatchSize());
}
@@ -51,15 +44,15 @@ public class DummyDao {
Transaction txn = Ebean.currentTransaction();
assertEquals(PersistBatch.ALL, txn.getBatch());
assertEquals(PersistBatch.NONE, txn.getBatchOnCascade());
assertTrue(txn.isBatchMode());
assertFalse(txn.isBatchOnCascade());
assertEquals(77, txn.getBatchSize());
doWithBatchOptionsSet();
// batch options set back
assertEquals(PersistBatch.ALL, txn.getBatch());
assertEquals(PersistBatch.NONE, txn.getBatchOnCascade());
assertTrue(txn.isBatchMode());
assertFalse(txn.isBatchOnCascade());
assertEquals(77, txn.getBatchSize());
}
@@ -0,0 +1,36 @@
package org.tests.model.lazywithid;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
@Entity
public class Looney {
@Id
public Long id;
@ManyToOne
private Tune tune;
private String name;
public Looney(final String name) {
this.name = name;
}
public Tune getTune() {
return tune;
}
public void setTune(final Tune tune) {
this.tune = tune;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
}
@@ -0,0 +1,26 @@
package org.tests.model.lazywithid;
import static org.junit.Assert.assertEquals;
import java.util.List;
import org.junit.Test;
import io.ebean.BaseTestCase;
import io.ebean.Ebean;
public class TestColumnIdName extends BaseTestCase {
@Test
public void test() {
Tune tune = new Tune();
tune.getLoonies().add(new Looney("Taz"));
Ebean.save(tune);
final List<Tune> fetchedCollection = Ebean.find(Tune.class).findList();
assertEquals(1, fetchedCollection.size());
assertEquals(1, fetchedCollection.get(0).getLoonies().size());
assertEquals("Taz", fetchedCollection.get(0).getLoonies().get(0).getName());
}
}
@@ -0,0 +1,40 @@
package org.tests.model.lazywithid;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import io.ebean.common.BeanList;
@Entity
public class Tune {
@Id
@Column(name = "id")
Long _id;
String name;
@OneToMany(cascade = CascadeType.ALL)
private List<Looney> loonies = new BeanList<>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Looney> getLoonies() {
return loonies;
}
public void setLoonies(final List<Looney> loonies) {
this.loonies = loonies;
}
}
@@ -0,0 +1,31 @@
package org.tests.model.onetoone;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.tests.model.BaseModel;
@Entity
@Table(name = "oto_user_model")
public class OtoUser extends BaseModel {
private String name;
@OneToOne(cascade = CascadeType.ALL)
private OtoUserOptional userOptional;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setOptional(OtoUserOptional userOptional) {
this.userOptional = userOptional;
}
}
@@ -0,0 +1,22 @@
package org.tests.model.onetoone;
import javax.persistence.Entity;
import javax.persistence.Table;
import org.tests.model.BaseModel;
@Entity
@Table(name = "oto_user_model_optional")
public class OtoUserOptional extends BaseModel {
private String optional;
public void setPassword(final String optional) {
this.optional = optional;
}
public String getOptional() {
return optional;
}
}
@@ -0,0 +1,35 @@
package org.tests.profile;
import org.tests.model.basic.Customer;
//import org.tests.model.basic.ResetBasicData;
public class ProfileSimpleQuery {
public static void main(String[] args) {
// ResetBasicData.reset();
ProfileSimpleQuery me = new ProfileSimpleQuery();
me.runIt();
}
private long counter;
private void runIt() {
long start = System.currentTimeMillis();
for (int i = 0; i < 1000_000; i++) {
readCustomer();
}
long exe = System.currentTimeMillis() - start;
System.out.println("run in " + exe);
}
private void readCustomer() {
Customer customer = Customer.find.byName("Rob");
String name = customer.getName();
if (name.length() > 999) {
counter++;
}
}
}
@@ -3,20 +3,20 @@ package org.tests.text.json;
import io.ebean.BaseTestCase;
import io.ebean.Ebean;
import io.ebean.text.json.JsonContext;
import org.junit.Test;
import org.tests.model.basic.Animal;
import org.tests.model.basic.Cat;
import org.tests.model.basic.Dog;
import org.junit.Assert;
import org.junit.Test;
import java.io.IOException;
import java.sql.Date;
import java.util.List;
import static org.junit.Assert.assertEquals;
public class TestJsonInheritanceDiscriminator extends BaseTestCase {
@Test
public void testNoDiscriminator() throws IOException {
public void testNoDiscriminator() {
Cat cat = new Cat();
cat.setName("Gemma");
@@ -28,17 +28,17 @@ public class TestJsonInheritanceDiscriminator extends BaseTestCase {
Cat cat2 = json.toBean(Cat.class, jsonContent);
Assert.assertEquals(cat.getId(), cat2.getId());
Assert.assertEquals(cat.getName(), cat2.getName());
Assert.assertEquals(cat.getVersion(), cat2.getVersion());
assertEquals(cat.getId(), cat2.getId());
assertEquals(cat.getName(), cat2.getName());
assertEquals(cat.getVersion(), cat2.getVersion());
String noDiscriminator = "{\"id\":1,\"name\":\"Gemma\",\"version\":1}";
Cat cat3 = json.toBean(Cat.class, noDiscriminator);
Assert.assertEquals(1L, cat3.getId().longValue());
Assert.assertEquals("Gemma", cat3.getName());
Assert.assertEquals(1L, cat3.getVersion().longValue());
assertEquals(1L, cat3.getId().longValue());
assertEquals("Gemma", cat3.getName());
assertEquals(1L, cat3.getVersion().longValue());
Dog dog = new Dog();
dog.setRegistrationNumber("ABC123");
@@ -51,11 +51,11 @@ public class TestJsonInheritanceDiscriminator extends BaseTestCase {
String listJson = json.toJson(animals);
List<Animal> animals2 = json.toList(Animal.class, listJson);
Assert.assertEquals(animals.size(), animals2.size());
assertEquals(animals.size(), animals2.size());
String noDiscList = "[{\"id\":1,\"name\":\"Gemma\",\"version\":1},{\"name\":\"PussCat\",\"version\":1},{\"species\":\"CAT\",\"name\":\"PussCat\",\"version\":1}]";
List<Cat> cats = json.toList(Cat.class, noDiscList);
Assert.assertEquals(cats.size(), 3);
assertEquals(cats.size(), 3);
}
@@ -13,13 +13,24 @@ import org.tests.model.basic.VehicleDriver;
import org.junit.Assert;
import org.junit.Test;
import java.io.IOException;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
public class TestTextJsonInheritance extends BaseTestCase {
@Test
public void test() throws IOException {
public void parseJson_when_inheritanceType_outOfOrderDtype() {
String fom = "{\"id\":90,\"name\":\"Frank\",\"vehicle\":{\"id\":42,\"licenseNumber\":\"T100\",\"capacity\":99.0,\"dtype\":\"T\"}}";
VehicleDriver driver1 = Ebean.json().toBean(VehicleDriver.class, fom);
assertThat(driver1.getVehicle()).isInstanceOf(Truck.class);
assertThat(driver1.getVehicle().getLicenseNumber()).isEqualTo("T100");
}
@Test
public void test() {
setupData();
@@ -14,28 +14,8 @@ 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();
final BBookmarkUser u = new BBookmarkUser("Mr Test");
u.setEmailAddress("test@test.com");
u.setName("Mr Test");
u.setPassword("password");
final List<BBookmark> bookmarks = new ArrayList<>();