mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
998d8ed6f2 | ||
|
|
a8da472872 | ||
|
|
a9cdf9736a | ||
|
|
c930a1dd6b | ||
|
|
67ce6ef58e | ||
|
|
c4f28efc45 | ||
|
|
afa4bc06d9 | ||
|
|
828c9ce128 | ||
|
|
6f37a0bd72 | ||
|
|
036086af02 | ||
|
|
f34b5e52e0 |
+13
-4
@@ -1,7 +1,11 @@
|
||||
sudo: required
|
||||
language: java
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
|
||||
git:
|
||||
depth: 3
|
||||
|
||||
addons:
|
||||
postgresql: "9.4"
|
||||
|
||||
@@ -9,15 +13,20 @@ services:
|
||||
- postgresql
|
||||
|
||||
before_script:
|
||||
- psql -c 'create extension pgcrypto;' -U postgres
|
||||
- psql -c 'create extension hstore;' -U postgres
|
||||
- psql -c 'create extension postgis;' -U postgres
|
||||
- psql -c 'create database unit;' -U postgres
|
||||
- ./.travis/setup_database
|
||||
|
||||
env:
|
||||
- EBEAN_DB=h2
|
||||
- EBEAN_DB=pg
|
||||
|
||||
install: true
|
||||
|
||||
script:
|
||||
- mvn clean test
|
||||
|
||||
after_failure:
|
||||
- ./.travis/print_surefire_reports
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.m2
|
||||
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "\n=== SUREFIRE REPORTS ===\n"
|
||||
|
||||
for file in target/surefire-reports/*.txt
|
||||
do
|
||||
echo ${file}
|
||||
cat ${file}
|
||||
echo
|
||||
done
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "\n=== SETUP DATABASE ===\n"
|
||||
|
||||
#set -e
|
||||
#set -x
|
||||
|
||||
# Setup postgres' users and databases
|
||||
sudo -u postgres psql -c "CREATE USER unit WITH PASSWORD 'unit';"
|
||||
sudo -u postgres psql -c 'CREATE DATABASE unit WITH OWNER unit;'
|
||||
sudo -u postgres psql unit -c 'CREATE EXTENSION hstore;'
|
||||
sudo -u postgres psql unit -c 'CREATE EXTENSION pgcrypto;'
|
||||
#sudo -u postgres psql test2 -c 'CREATE EXTENSION postgis;'
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm</artifactId>
|
||||
<version>6.16.2</version>
|
||||
<version>6.16.3</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>avaje-ebeanorm</name>
|
||||
@@ -219,7 +219,7 @@
|
||||
<plugin>
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm-mavenenhancer</artifactId>
|
||||
<version>4.8.1</version>
|
||||
<version>4.9.1</version>
|
||||
<executions>
|
||||
<!-- Not going to enhance Model bean -->
|
||||
<execution>
|
||||
|
||||
@@ -343,28 +343,10 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the lazy load succeeded. If not then mark this bean as having
|
||||
* failed lazy loading due to the underlying row being deleted.
|
||||
* <p>
|
||||
* We mark the bean this way rather than immediately fail as we might be batch
|
||||
* lazy loading and this bean might not be used by the client code at all.
|
||||
* Instead we will fail as soon as the client code tries to use this bean.
|
||||
* </p>
|
||||
* @param lazyLoadPropertyIndex the property that is expected to be loaded
|
||||
* Set lazy load failure flag.
|
||||
*/
|
||||
public boolean isLazyLoadFailure(int lazyLoadPropertyIndex) {
|
||||
if (lazyLoadProperty != -1 || !isLoadedProperty(lazyLoadPropertyIndex)) {
|
||||
lazyLoadFailure = true;
|
||||
return true;
|
||||
}
|
||||
lazyLoadFailure = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Id of the owner bean.
|
||||
*/
|
||||
public void setOwnerId(Object ownerId) {
|
||||
public void setLazyLoadFailure(Object ownerId) {
|
||||
this.lazyLoadFailure = true;
|
||||
this.ownerId = ownerId;
|
||||
}
|
||||
|
||||
|
||||
@@ -88,6 +88,8 @@ public class DbMigrationConfig {
|
||||
|
||||
protected String modelSuffix = ".model.xml";
|
||||
|
||||
protected boolean includeGeneratedFileComment;
|
||||
|
||||
/**
|
||||
* Return the DB platform to generate migration DDL for.
|
||||
*
|
||||
@@ -236,6 +238,20 @@ public class DbMigrationConfig {
|
||||
this.rollbackSuffix = rollbackSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the generated file comment should be included.
|
||||
*/
|
||||
public boolean isIncludeGeneratedFileComment() {
|
||||
return includeGeneratedFileComment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if the generated file comment should be included.
|
||||
*/
|
||||
public void setIncludeGeneratedFileComment(boolean includeGeneratedFileComment) {
|
||||
this.includeGeneratedFileComment = includeGeneratedFileComment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the migration version.
|
||||
* <p>
|
||||
@@ -281,6 +297,7 @@ public class DbMigrationConfig {
|
||||
dropSuffix = properties.get("migration.dropSuffix", dropSuffix);
|
||||
rollbackSuffix = properties.get("migration.rollbackSuffix", rollbackSuffix);
|
||||
modelSuffix = properties.get("migration.modelSuffix", modelSuffix);
|
||||
includeGeneratedFileComment = properties.getBoolean("migration.includeGeneratedFileComment", includeGeneratedFileComment);
|
||||
|
||||
platform = properties.getEnum(DbPlatformName.class, "migration.platform", platform);
|
||||
suppressRollback = properties.getBoolean("migration.suppressRollback", suppressRollback);
|
||||
|
||||
@@ -59,6 +59,8 @@ public class DbMigration {
|
||||
|
||||
private static final String initialVersion = "1.0";
|
||||
|
||||
private static final String GENERATED_COMMENT = "THIS IS A GENERATED FILE - DO NOT MODIFY";
|
||||
|
||||
/**
|
||||
* Set to true if DbMigration run with online EbeanServer instance.
|
||||
*/
|
||||
@@ -304,7 +306,8 @@ public class DbMigration {
|
||||
if (file.exists()) {
|
||||
return false;
|
||||
}
|
||||
MigrationXmlWriter xmlWriter = new MigrationXmlWriter();
|
||||
String comment = migrationConfig.isIncludeGeneratedFileComment() ? GENERATED_COMMENT : null;
|
||||
MigrationXmlWriter xmlWriter = new MigrationXmlWriter(comment);
|
||||
xmlWriter.write(dbMigration, file);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7,22 +7,46 @@ import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Marshaller;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Simple writer for output of the Migration/ChangeSet as an XML document.
|
||||
*/
|
||||
public class MigrationXmlWriter {
|
||||
|
||||
private final String comment;
|
||||
|
||||
public MigrationXmlWriter(String comment) {
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a Migration to a file as an xml document to the file.
|
||||
*/
|
||||
public void write(Migration migration, File file) {
|
||||
|
||||
try {
|
||||
|
||||
FileWriter writer = new FileWriter(file);
|
||||
writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");
|
||||
if (comment != null) {
|
||||
writer.write("<!-- ");
|
||||
writer.write(comment);
|
||||
writer.write(" -->\n");
|
||||
}
|
||||
|
||||
JAXBContext jaxbContext = JAXBContext.newInstance(Migration.class);
|
||||
Marshaller marshaller = jaxbContext.createMarshaller();
|
||||
marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
|
||||
marshaller.marshal(migration, file);
|
||||
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
|
||||
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
|
||||
|
||||
marshaller.marshal(migration, writer);
|
||||
|
||||
writer.close();
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
||||
} catch (JAXBException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
||||
@@ -8,7 +8,9 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Request for loading ManyToOne and OneToOne relationships.
|
||||
@@ -21,8 +23,6 @@ public class LoadBeanRequest extends LoadRequest {
|
||||
|
||||
private final LoadBeanBuffer loadBuffer;
|
||||
|
||||
private final int lazyLoadPropertyIndex;
|
||||
|
||||
private final String lazyLoadProperty;
|
||||
|
||||
private final boolean loadCache;
|
||||
@@ -30,24 +30,23 @@ public class LoadBeanRequest extends LoadRequest {
|
||||
/**
|
||||
* Construct for lazy load request.
|
||||
*/
|
||||
public LoadBeanRequest(LoadBeanBuffer LoadBuffer, int lazyLoadPropertyIndex, String lazyLoadProperty, boolean loadCache) {
|
||||
this(LoadBuffer, null, true, lazyLoadPropertyIndex, lazyLoadProperty, loadCache);
|
||||
public LoadBeanRequest(LoadBeanBuffer LoadBuffer, String lazyLoadProperty, boolean loadCache) {
|
||||
this(LoadBuffer, null, true, lazyLoadProperty, loadCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct for secondary query.
|
||||
*/
|
||||
public LoadBeanRequest(LoadBeanBuffer LoadBuffer, OrmQueryRequest<?> parentRequest) {
|
||||
this(LoadBuffer, parentRequest, false, -1, null, false);
|
||||
this(LoadBuffer, parentRequest, false, null, false);
|
||||
}
|
||||
|
||||
private LoadBeanRequest(LoadBeanBuffer loadBuffer, OrmQueryRequest<?> parentRequest, boolean lazy,
|
||||
int lazyLoadPropertyIndex, String lazyLoadProperty, boolean loadCache) {
|
||||
String lazyLoadProperty, boolean loadCache) {
|
||||
|
||||
super(parentRequest, lazy);
|
||||
this.loadBuffer = loadBuffer;
|
||||
this.batch = loadBuffer.getBatch();
|
||||
this.lazyLoadPropertyIndex = lazyLoadPropertyIndex;
|
||||
this.lazyLoadProperty = lazyLoadProperty;
|
||||
this.loadCache = loadCache;
|
||||
}
|
||||
@@ -96,7 +95,7 @@ public class LoadBeanRequest extends LoadRequest {
|
||||
*/
|
||||
public List<Object> getIdList(int batchSize) {
|
||||
|
||||
ArrayList<Object> idList = new ArrayList<Object>(batchSize);
|
||||
List<Object> idList = new ArrayList<Object>(batchSize);
|
||||
|
||||
BeanDescriptor<?> desc = loadBuffer.getBeanDescriptor();
|
||||
for (int i = 0; i < batch.size(); i++) {
|
||||
@@ -124,7 +123,7 @@ public class LoadBeanRequest extends LoadRequest {
|
||||
/**
|
||||
* Configure the query for lazy loading execution.
|
||||
*/
|
||||
public void configureQuery(SpiQuery<?> query) {
|
||||
public void configureQuery(SpiQuery<?> query, List<Object> idList) {
|
||||
|
||||
query.setMode(SpiQuery.Mode.LAZYLOAD_BEAN);
|
||||
query.setPersistenceContext(loadBuffer.getPersistenceContext());
|
||||
@@ -137,7 +136,13 @@ public class LoadBeanRequest extends LoadRequest {
|
||||
query.setLazyLoadBatchSize(getBatchSize());
|
||||
}
|
||||
|
||||
loadBuffer.configureQuery(query, getLazyLoadProperty());
|
||||
loadBuffer.configureQuery(query, lazyLoadProperty);
|
||||
|
||||
if (idList.size() == 1) {
|
||||
query.where().idEq(idList.get(0));
|
||||
} else {
|
||||
query.where().idIn(idList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,25 +150,27 @@ public class LoadBeanRequest extends LoadRequest {
|
||||
*/
|
||||
public void postLoad(List<?> list) {
|
||||
|
||||
if (isLoadCache()) {
|
||||
BeanDescriptor<?> desc = loadBuffer.getBeanDescriptor();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
desc.cacheBeanPutData((EntityBean) list.get(i));
|
||||
Set<Object> loadedIds = new HashSet<Object>();
|
||||
|
||||
BeanDescriptor<?> desc = loadBuffer.getBeanDescriptor();
|
||||
// collect Ids and maybe load bean cache
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
EntityBean loadedBean = (EntityBean) list.get(i);
|
||||
loadedIds.add(desc.getId(loadedBean));
|
||||
if (isLoadCache()) {
|
||||
desc.cacheBeanPutData(loadedBean);
|
||||
}
|
||||
}
|
||||
|
||||
if (lazyLoadPropertyIndex > -1) {
|
||||
// this is a lazy loading query so check for lazy loading failure (due to deleted rows)
|
||||
if (lazyLoadProperty != null) {
|
||||
for (int i = 0; i < batch.size(); i++) {
|
||||
// check if the underlying row in DB was deleted. Mark the bean as 'failed' if
|
||||
// necessary but allow processing to continue until it is accessed by client code
|
||||
EntityBeanIntercept ebi = batch.get(i);
|
||||
// all beans in the batch should have this property loaded now
|
||||
if (ebi.isLazyLoadFailure(lazyLoadPropertyIndex)) {
|
||||
BeanDescriptor<?> desc = loadBuffer.getBeanDescriptor();
|
||||
Object beanId = desc.getId(ebi.getOwner());
|
||||
ebi.setOwnerId(beanId);
|
||||
logger.info("Lazy loading unsuccessful for type:" + desc.getName() + " id:" + beanId + " - expecting when bean has been deleted");
|
||||
Object id = desc.getId(ebi.getOwner());
|
||||
if (!loadedIds.contains(id)) {
|
||||
logger.info("Lazy loading unsuccessful for type:" + desc.getName() + " id:" + id + " - expecting when bean has been deleted");
|
||||
ebi.setLazyLoadFailure(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,16 +206,9 @@ public class DefaultBeanLoader {
|
||||
}
|
||||
|
||||
SpiQuery<?> query = (SpiQuery<?>) server.createQuery(loadRequest.getBeanType());
|
||||
loadRequest.configureQuery(query);
|
||||
|
||||
if (idList.size() == 1) {
|
||||
query.where().idEq(idList.get(0));
|
||||
} else {
|
||||
query.where().idIn(idList);
|
||||
}
|
||||
loadRequest.configureQuery(query, idList);
|
||||
|
||||
List<?> list = executeQuery(loadRequest, query);
|
||||
|
||||
loadRequest.postLoad(list);
|
||||
|
||||
// log the query (for testing secondary queries)
|
||||
|
||||
@@ -190,7 +190,7 @@ public class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContex
|
||||
}
|
||||
}
|
||||
|
||||
LoadBeanRequest req = new LoadBeanRequest(this, ebi.getLazyLoadPropertyIndex(), ebi.getLazyLoadProperty(), context.hitCache);
|
||||
LoadBeanRequest req = new LoadBeanRequest(this, ebi.getLazyLoadProperty(), context.hitCache);
|
||||
context.desc.getEbeanServer().loadBean(req);
|
||||
}
|
||||
|
||||
|
||||
+16
-2
@@ -5,16 +5,30 @@ import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class MigrationXmlWriterTest {
|
||||
|
||||
@Test
|
||||
public void testReadWrite() throws Exception {
|
||||
|
||||
Migration migration = MigrationXmlReader.read("/container/test-create-table.xml");
|
||||
assertThat(migration.getChangeSet()).hasSize(1);
|
||||
assertThat(migration.getChangeSet().get(0).getChangeSetChildren()).hasSize(3);
|
||||
|
||||
File temp = File.createTempFile("migrationWrite",".xml");
|
||||
MigrationXmlWriter writer = new MigrationXmlWriter();
|
||||
writer.write(migration, temp);
|
||||
new MigrationXmlWriter("THIS IS A GENERATED FILE - DO NOT MODIFY").write(migration, temp);
|
||||
|
||||
Migration migrationRead = MigrationXmlReader.read(temp);
|
||||
assertThat(migrationRead.getChangeSet()).hasSize(1);
|
||||
assertThat(migrationRead.getChangeSet().get(0).getChangeSetChildren()).hasSize(3);
|
||||
|
||||
temp = File.createTempFile("migrationWrite",".xml");
|
||||
new MigrationXmlWriter(null).write(migration, temp);
|
||||
|
||||
Migration migrationRead2 = MigrationXmlReader.read(temp);
|
||||
|
||||
assertThat(migrationRead2.getChangeSet()).hasSize(1);
|
||||
assertThat(migrationRead.getChangeSet().get(0).getChangeSetChildren()).hasSize(3);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.avaje.tests.inheritance;
|
||||
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.tests.model.basic.Car;
|
||||
import com.avaje.tests.model.basic.Truck;
|
||||
import com.avaje.tests.model.basic.Vehicle;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
public class TestInheritanceBatchLazyLoad {
|
||||
|
||||
@Test
|
||||
public void lazyLoadProperty_when_propertyNotOnAllInheritanceTypes() {
|
||||
|
||||
Car c = new Car();
|
||||
c.setLicenseNumber("VZVZ1");
|
||||
c.setDriver("CarDriver");
|
||||
Ebean.save(c);
|
||||
|
||||
Truck t = new Truck();
|
||||
t.setLicenseNumber("VZVZ2");
|
||||
t.setCapacity(20D);
|
||||
Ebean.save(t);
|
||||
|
||||
|
||||
List<Vehicle> list = Ebean.find(Vehicle.class)
|
||||
.select("licenseNumber")
|
||||
.where().startsWith("licenseNumber","VZVZ")
|
||||
.order().asc("licenseNumber")
|
||||
.findList();
|
||||
|
||||
assertThat(list).hasSize(2);
|
||||
|
||||
Car car = (Car)list.get(0);
|
||||
car.getNotes();
|
||||
}
|
||||
}
|
||||
@@ -19,12 +19,14 @@ public class Car extends Vehicle {
|
||||
private String driver;
|
||||
|
||||
@ManyToOne
|
||||
TruckRef carRef;
|
||||
private TruckRef carRef;
|
||||
|
||||
@OneToMany(mappedBy = "car")
|
||||
@OrderBy("fuse.locationCode")
|
||||
private Set<CarAccessory> accessories = new HashSet<CarAccessory>();
|
||||
|
||||
private String notes;
|
||||
|
||||
public String getDriver() {
|
||||
return driver;
|
||||
}
|
||||
@@ -33,6 +35,14 @@ public class Car extends Vehicle {
|
||||
this.driver = driver;
|
||||
}
|
||||
|
||||
public String getNotes() {
|
||||
return notes;
|
||||
}
|
||||
|
||||
public void setNotes(String notes) {
|
||||
this.notes = notes;
|
||||
}
|
||||
|
||||
public TruckRef getCarRef() {
|
||||
return carRef;
|
||||
}
|
||||
|
||||
@@ -110,8 +110,8 @@ datasource.ora.password=unit
|
||||
datasource.ora.databaseUrl=jdbc:oracle:thin:@//127.0.0.1:1521/orcl
|
||||
datasource.ora.databaseDriver=oracle.jdbc.driver.OracleDriver
|
||||
|
||||
datasource.pg.username=postgres
|
||||
datasource.pg.password=
|
||||
datasource.pg.username=unit
|
||||
datasource.pg.password=unit
|
||||
datasource.pg.databaseUrl=jdbc:postgresql://127.0.0.1:5432/unit
|
||||
datasource.pg.databaseDriver=org.postgresql.Driver
|
||||
|
||||
|
||||
Reference in New Issue
Block a user