mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-23 21:15:52 +00:00
ENH: Add mappingsLocation config to search xml mapping files.
ENH: Add mappingsLocation config to search xml mapping files. ENH: Add mappingsLocation config to search xml mapping files. ENH: Add mappingsLocation config to search xml mapping files. ENH: Add mappingsLocation config to search xml mapping files. ENH: Add mappingsLocation config to search xml mapping files. remove unused import. ENH: Add mappingsLocation config and search xml mapping files feature.
This commit is contained in:
@@ -14,14 +14,7 @@ import io.ebean.config.dbplatform.DbEncrypt;
|
||||
import io.ebean.config.dbplatform.DbType;
|
||||
import io.ebean.config.dbplatform.IdType;
|
||||
import io.ebean.config.properties.PropertiesLoader;
|
||||
import io.ebean.event.BeanFindController;
|
||||
import io.ebean.event.BeanPersistController;
|
||||
import io.ebean.event.BeanPersistListener;
|
||||
import io.ebean.event.BeanPostConstructListener;
|
||||
import io.ebean.event.BeanPostLoad;
|
||||
import io.ebean.event.BeanQueryAdapter;
|
||||
import io.ebean.event.BulkTableEventListener;
|
||||
import io.ebean.event.ServerConfigStartup;
|
||||
import io.ebean.event.*;
|
||||
import io.ebean.event.changelog.ChangeLogListener;
|
||||
import io.ebean.event.changelog.ChangeLogPrepare;
|
||||
import io.ebean.event.changelog.ChangeLogRegister;
|
||||
@@ -33,14 +26,7 @@ import io.ebean.util.StringHelper;
|
||||
import org.avaje.datasource.DataSourceConfig;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* The configuration used for creating a EbeanServer.
|
||||
@@ -488,6 +474,12 @@ public class ServerConfig {
|
||||
*/
|
||||
private boolean defaultOrderById = false;
|
||||
|
||||
/**
|
||||
* The mappingLocations for searching xml mapping. Only used when
|
||||
* mappingLocations is empty/not explicitly specified.
|
||||
*/
|
||||
private List<String> mappingLocations = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Construct a Server Configuration for programmatically creating an EbeanServer.
|
||||
*/
|
||||
@@ -2782,7 +2774,7 @@ public class ServerConfig {
|
||||
|
||||
if (packages != null) {
|
||||
String packagesProp = p.get("search.packages", p.get("packages", null));
|
||||
packages = getSearchJarsPackages(packagesProp);
|
||||
packages = getSearchList(packagesProp);
|
||||
}
|
||||
|
||||
collectQueryStatsByNode = p.getBoolean("collectQueryStatsByNode", collectQueryStatsByNode);
|
||||
@@ -2862,6 +2854,12 @@ public class ServerConfig {
|
||||
tenantSchemaProvider = p.createInstance(TenantSchemaProvider.class, "tenant.schemaProvider", tenantSchemaProvider);
|
||||
tenantPartitionColumn = p.get("tenant.partitionColumn", tenantPartitionColumn);
|
||||
classes = getClasses(p);
|
||||
|
||||
|
||||
if (mappingLocations != null) {
|
||||
String mappingsProp = p.get("search.mappingsLocations", p.get("mappingsLocations", null));
|
||||
mappingLocations = getSearchList(mappingsProp);
|
||||
}
|
||||
}
|
||||
|
||||
private NamingConvention createNamingConvention(PropertiesWrapper properties, NamingConvention namingConvention) {
|
||||
@@ -2898,10 +2896,10 @@ public class ServerConfig {
|
||||
return classes;
|
||||
}
|
||||
|
||||
private List<String> getSearchJarsPackages(String searchPackages) {
|
||||
private List<String> getSearchList(String searchNames) {
|
||||
|
||||
if (searchPackages != null) {
|
||||
String[] entries = StringHelper.splitNames(searchPackages);
|
||||
if (searchNames != null) {
|
||||
String[] entries = StringHelper.splitNames(searchNames);
|
||||
|
||||
List<String> hitList = new ArrayList<>(entries.length);
|
||||
Collections.addAll(hitList, entries);
|
||||
@@ -3076,6 +3074,33 @@ public class ServerConfig {
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a mapping location to search for xml mapping via class path search.
|
||||
*/
|
||||
public void addMappingLocation(String mappingLocation) {
|
||||
if (mappingLocations == null) {
|
||||
mappingLocations = new ArrayList<>();
|
||||
}
|
||||
mappingLocations.add(mappingLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return mapping locations to search for xml mapping via class path search.
|
||||
*/
|
||||
public List<String> getMappingLocations() {
|
||||
return mappingLocations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set mapping locations to search for xml mapping via class path search.
|
||||
* <p>
|
||||
* This is only used if classes have not been explicitly specified.
|
||||
* </p>
|
||||
*/
|
||||
public void setMappingLocations(List<String> mappingLocations) {
|
||||
this.mappingLocations = mappingLocations;
|
||||
}
|
||||
|
||||
public enum UuidVersion {
|
||||
VERSION4,
|
||||
VERSION1,
|
||||
|
||||
@@ -26,6 +26,7 @@ import io.ebeaninternal.api.ConcurrencyMode;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.api.TransactionEventTable;
|
||||
import io.ebeaninternal.server.cache.SpiCacheManager;
|
||||
import io.ebeaninternal.server.core.ClassPathScanners;
|
||||
import io.ebeaninternal.server.core.InternString;
|
||||
import io.ebeaninternal.server.core.InternalConfiguration;
|
||||
import io.ebeaninternal.server.core.Message;
|
||||
@@ -65,6 +66,9 @@ import io.ebeaninternal.xmlmapping.model.XmNamedQuery;
|
||||
import io.ebeaninternal.xmlmapping.model.XmRawSql;
|
||||
import io.ebeanservice.docstore.api.DocStoreBeanAdapter;
|
||||
import io.ebeanservice.docstore.api.DocStoreFactory;
|
||||
import org.avaje.classpath.scanner.ClassPathScanner;
|
||||
import org.avaje.classpath.scanner.Resource;
|
||||
import org.avaje.classpath.scanner.ResourceFilter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -72,6 +76,7 @@ import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.Transient;
|
||||
import javax.sql.DataSource;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
@@ -416,6 +421,13 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
}
|
||||
}
|
||||
|
||||
List<Resource> xmlMappingResources = searchXmlMapping();
|
||||
for (Resource xmlMappingRes : xmlMappingResources) {
|
||||
try (InputStream is = new FileInputStream(xmlMappingRes.getLocationOnDisk())) {
|
||||
mappings.add(XmlMappingReader.read(is));
|
||||
}
|
||||
}
|
||||
|
||||
for (XmEbean mapping : mappings) {
|
||||
List<XmEntity> entityDeploy = mapping.getEntity();
|
||||
for (XmEntity deploy : entityDeploy) {
|
||||
@@ -424,10 +436,35 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error reading ebean.xml", e);
|
||||
throw new RuntimeException("Error reading ebean xml mapping", e);
|
||||
}
|
||||
}
|
||||
|
||||
private List<Resource> searchXmlMapping() {
|
||||
List<ClassPathScanner> scanners = ClassPathScanners.find(serverConfig);
|
||||
List<String> mappingLocations = serverConfig.getMappingLocations();
|
||||
List<Resource> resourceList = new ArrayList<>();
|
||||
|
||||
long st = System.currentTimeMillis();
|
||||
if (mappingLocations != null && !mappingLocations.isEmpty()) {
|
||||
for (ClassPathScanner finder : scanners) {
|
||||
for (String mappingLocation : mappingLocations) {
|
||||
resourceList.addAll(finder.scanForResources(mappingLocation, new ResourceFilter() {
|
||||
|
||||
@Override
|
||||
public boolean isMatch(String resourceName) {
|
||||
return resourceName.endsWith(".xml");
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long searchTime = System.currentTimeMillis() - st;
|
||||
logger.debug("Classpath search mappings[{}] searchTime[{}]", resourceList.size(), searchTime);
|
||||
return resourceList;
|
||||
}
|
||||
|
||||
private void readEntityMapping(ClassLoader classLoader, XmEntity entityDeploy) {
|
||||
|
||||
String entityClassName = entityDeploy.getClazz();
|
||||
|
||||
@@ -250,4 +250,19 @@ public class EbeanServer_eqlTest extends BaseTestCase {
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("from o_customer t0 left join contact t1 on t1.customer_id = t0.id ");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void namedQuery_fromCustomXmlLocations() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
Query<Customer> query = server()
|
||||
.createNamedQuery(Customer.class, "withContactsById2")
|
||||
.setParameter("id", 1);
|
||||
|
||||
query.setUseCache(false);
|
||||
query.findOne();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("from o_customer t0 left join contact t1 on t1.customer_id = t0.id ");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,32 @@ public class TestRawSqlOrmQuery extends BaseTestCase {
|
||||
assertThat(sql).contains("where o.status = ? order by c.name, c.id");
|
||||
}
|
||||
|
||||
@IgnorePlatform(Platform.ORACLE)
|
||||
@Test
|
||||
public void testNamed_fromCustomXmlLocations() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
Query<Order> query = Ebean.createNamedQuery(Order.class, "myRawTest2");
|
||||
query.setParameter("orderStatus", Order.Status.NEW);
|
||||
query.setMaxRows(10);
|
||||
List<Order> list = query.findList();
|
||||
for (Order order : list) {
|
||||
order.getCretime();
|
||||
}
|
||||
|
||||
String sql = query.getGeneratedSql();
|
||||
if (isSqlServer()) {
|
||||
assertThat(sql).contains("select top 10 o.id,");
|
||||
} else {
|
||||
assertThat(sql).contains("select o.id,");
|
||||
assertThat(sql).contains("limit 10");
|
||||
}
|
||||
assertThat(sql).contains("o.id, o.status, o.ship_date, c.id, c.name, a.id, a.line_1, a.line_2, a.city from o_order o");
|
||||
assertThat(sql).contains("join o_customer c on o.kcustomer_id = c.id ");
|
||||
assertThat(sql).contains("where o.status = ? order by c.name, c.id");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<ebean xmlns="http://ebean-orm.github.io/xml/ns/ebean">
|
||||
|
||||
<entity class="org.tests.model.basic.Customer">
|
||||
<named-query name="withContactsById2">
|
||||
<query>
|
||||
select (name, version)
|
||||
fetch contacts (firstName, lastName, email)
|
||||
where id = :id
|
||||
</query>
|
||||
</named-query>
|
||||
</entity>
|
||||
|
||||
</ebean>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<ebean xmlns="http://ebean-orm.github.io/xml/ns/ebean">
|
||||
|
||||
<entity class="org.tests.model.basic.Order">
|
||||
<raw-sql name="myRawTest2">
|
||||
<alias-mapping alias="c" property="customer"/>
|
||||
<alias-mapping alias="a" property="customer.billingAddress"/>
|
||||
<query>
|
||||
select o.id, o.status, o.ship_date, c.id, c.name, a.id, a.line_1, a.line_2, a.city
|
||||
from o_order o
|
||||
join o_customer c on o.kcustomer_id = c.id
|
||||
join o_address a on c.billing_address_id = a.id
|
||||
where o.status = :orderStatus
|
||||
order by c.name, c.id
|
||||
</query>
|
||||
</raw-sql>
|
||||
</entity>
|
||||
|
||||
</ebean>
|
||||
@@ -168,3 +168,5 @@ ebean.migrationtest.ddl.header=-- Migrationscripts for ebean unittest
|
||||
ebean.migrationtest.migration.appName=migrationtest
|
||||
ebean.migrationtest.migration.migrationPath=dbmigration/migrationtest
|
||||
ebean.migrationtest.migration.strict=true
|
||||
|
||||
ebean.mappingsLocations=classpath:/ebean-xml-mappings
|
||||
|
||||
Reference in New Issue
Block a user