This commit is contained in:
@@ -6,6 +6,11 @@
|
||||
<!-- 为NONE表示不启动缓存,@Cacheable 失效; 非NONE值(通常用ALL)表示开启缓存。 -->
|
||||
<shared-cache-mode>NONE</shared-cache-mode>
|
||||
<properties>
|
||||
<!--
|
||||
DataSource的实现类,没有设置默认为org.redkale.source.DataDefaultSource的实现,使用常规基于JDBC的数据库驱动一般无需设置
|
||||
-->
|
||||
<property name="javax.persistence.datasource" value="org.redkale.source.DataDefaultSource"/>
|
||||
|
||||
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/dbuser?characterEncoding=utf8"/>
|
||||
<!--
|
||||
javax.persistence.jdbc.driver在JPA的值是JDBC驱动,Redkale有所不同,值应该是javax.sql.DataSource的子类。
|
||||
|
||||
@@ -307,7 +307,7 @@ public final class Application {
|
||||
|
||||
File persist = new File(this.home, "conf/persistence.xml");
|
||||
final String homepath = this.home.getCanonicalPath();
|
||||
if (persist.isFile()) System.setProperty(DataDefaultSource.DATASOURCE_CONFPATH, persist.getCanonicalPath());
|
||||
if (persist.isFile()) System.setProperty(Sources.DATASOURCE_CONFPATH, persist.getCanonicalPath());
|
||||
logger.log(Level.INFO, RESNAME_APP_HOME + "= " + homepath + "\r\n" + RESNAME_APP_ADDR + "= " + this.localAddress.getHostAddress());
|
||||
String lib = config.getValue("lib", "").trim().replace("${APP_HOME}", homepath);
|
||||
lib = lib.isEmpty() ? (homepath + "/conf") : (lib + ";" + homepath + "/conf");
|
||||
|
||||
@@ -220,7 +220,7 @@ public abstract class NodeServer {
|
||||
try {
|
||||
if (field.getAnnotation(Resource.class) == null) return;
|
||||
if ((src instanceof Service) && Sncp.isRemote((Service) src)) return; //远程模式不得注入 DataSource
|
||||
DataSource source = new DataDefaultSource(resourceName);
|
||||
DataSource source = Sources.createDataSource(resourceName);
|
||||
application.dataSources.add(source);
|
||||
appResFactory.register(resourceName, DataSource.class, source);
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.*;
|
||||
import java.util.logging.*;
|
||||
import javax.annotation.Resource;
|
||||
import javax.xml.stream.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
@@ -25,9 +24,7 @@ import org.redkale.util.*;
|
||||
* @author zhangjx
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final class DataDefaultSource implements DataSource, Function<Class, EntityInfo>, AutoCloseable {
|
||||
|
||||
public static final String DATASOURCE_CONFPATH = "DATASOURCE_CONFPATH";
|
||||
public final class DataDefaultSource implements DataSource, Function<Class, EntityInfo>, AutoCloseable {
|
||||
|
||||
private static final Flipper FLIPPER_ONE = new Flipper(1);
|
||||
|
||||
@@ -50,54 +47,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
|
||||
|
||||
private final BiFunction<DataSource, Class, List> fullloader = (s, t) -> querySheet(false, false, t, null, null, (FilterNode) null).list(true);
|
||||
|
||||
public DataDefaultSource() throws IOException {
|
||||
this("");
|
||||
}
|
||||
|
||||
public DataDefaultSource(final String unitName) throws IOException {
|
||||
this(unitName, System.getProperty(DATASOURCE_CONFPATH) == null
|
||||
? DataDefaultSource.class.getResource("/META-INF/persistence.xml")
|
||||
: new File(System.getProperty(DATASOURCE_CONFPATH)).toURI().toURL());
|
||||
}
|
||||
|
||||
public DataDefaultSource(final String unitName, URL url) throws IOException {
|
||||
if (url == null) url = this.getClass().getResource("/persistence.xml");
|
||||
InputStream in = url.openStream();
|
||||
Map<String, Properties> map = loadProperties(in);
|
||||
Properties readprop = null;
|
||||
Properties writeprop = null;
|
||||
if (unitName != null) {
|
||||
readprop = map.get(unitName);
|
||||
writeprop = readprop;
|
||||
if (readprop == null) {
|
||||
readprop = map.get(unitName + ".read");
|
||||
writeprop = map.get(unitName + ".write");
|
||||
}
|
||||
}
|
||||
if ((unitName == null || unitName.isEmpty()) || readprop == null) {
|
||||
String key = null;
|
||||
for (Map.Entry<String, Properties> en : map.entrySet()) {
|
||||
key = en.getKey();
|
||||
readprop = en.getValue();
|
||||
writeprop = readprop;
|
||||
break;
|
||||
}
|
||||
if (key != null && (key.endsWith(".read") || key.endsWith(".write"))) {
|
||||
if (key.endsWith(".read")) {
|
||||
writeprop = map.get(key.substring(0, key.lastIndexOf('.')) + ".write");
|
||||
} else {
|
||||
readprop = map.get(key.substring(0, key.lastIndexOf('.')) + ".read");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (readprop == null) throw new RuntimeException("not found persistence properties (unit:" + unitName + ")");
|
||||
this.name = unitName;
|
||||
this.conf = url;
|
||||
this.readPool = new JDBCPoolSource(this, "read", readprop);
|
||||
this.writePool = new JDBCPoolSource(this, "write", writeprop);
|
||||
this.cacheForbidden = "NONE".equalsIgnoreCase(readprop.getProperty("shared-cache-mode"));
|
||||
}
|
||||
|
||||
public DataDefaultSource(String unitName, Properties readprop, Properties writeprop) {
|
||||
this.name = unitName;
|
||||
this.conf = null;
|
||||
@@ -106,58 +55,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
|
||||
this.cacheForbidden = "NONE".equalsIgnoreCase(readprop.getProperty("shared-cache-mode"));
|
||||
}
|
||||
|
||||
public static Map<String, DataDefaultSource> create(final InputStream in) {
|
||||
Map<String, Properties> map = loadProperties(in);
|
||||
Map<String, Properties[]> maps = new HashMap<>();
|
||||
map.entrySet().stream().forEach((en) -> {
|
||||
if (en.getKey().endsWith(".read") || en.getKey().endsWith(".write")) {
|
||||
String key = en.getKey().substring(0, en.getKey().lastIndexOf('.'));
|
||||
if (maps.containsKey(key)) return;
|
||||
boolean read = en.getKey().endsWith(".read");
|
||||
Properties rp = read ? en.getValue() : map.get(key + ".read");
|
||||
Properties wp = read ? map.get(key + ".write") : en.getValue();
|
||||
maps.put(key, new Properties[]{rp, wp});
|
||||
} else {
|
||||
maps.put(en.getKey(), new Properties[]{en.getValue(), en.getValue()});
|
||||
}
|
||||
});
|
||||
Map<String, DataDefaultSource> result = new HashMap<>();
|
||||
maps.entrySet().stream().forEach((en) -> {
|
||||
result.put(en.getKey(), new DataDefaultSource(en.getKey(), en.getValue()[0], en.getValue()[1]));
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
static Map<String, Properties> loadProperties(final InputStream in0) {
|
||||
final Map<String, Properties> map = new LinkedHashMap();
|
||||
Properties result = new Properties();
|
||||
boolean flag = false;
|
||||
try (final InputStream in = in0) {
|
||||
XMLStreamReader reader = XMLInputFactory.newFactory().createXMLStreamReader(in);
|
||||
while (reader.hasNext()) {
|
||||
int event = reader.next();
|
||||
if (event == XMLStreamConstants.START_ELEMENT) {
|
||||
if ("persistence-unit".equalsIgnoreCase(reader.getLocalName())) {
|
||||
if (!result.isEmpty()) result = new Properties();
|
||||
map.put(reader.getAttributeValue(null, "name"), result);
|
||||
flag = true;
|
||||
} else if (flag && "property".equalsIgnoreCase(reader.getLocalName())) {
|
||||
String name = reader.getAttributeValue(null, "name");
|
||||
String value = reader.getAttributeValue(null, "value");
|
||||
if (name == null) continue;
|
||||
result.put(name, value);
|
||||
} else if (flag && "shared-cache-mode".equalsIgnoreCase(reader.getLocalName())) {
|
||||
result.put(reader.getLocalName(), reader.getElementText());
|
||||
}
|
||||
}
|
||||
}
|
||||
in.close();
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public final String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -304,11 +304,11 @@ public final class EntityInfo<T> {
|
||||
this.cache = null;
|
||||
}
|
||||
if (conf == null) conf = new Properties();
|
||||
this.containSQL = conf.getProperty(JDBCPoolSource.JDBC_CONTAIN_SQLTEMPLATE, "LOCATE(${keystr}, ${column}) > 0");
|
||||
this.notcontainSQL = conf.getProperty(JDBCPoolSource.JDBC_NOTCONTAIN_SQLTEMPLATE, "LOCATE(${keystr}, ${column}) = 0");
|
||||
this.containSQL = conf.getProperty(Sources.JDBC_CONTAIN_SQLTEMPLATE, "LOCATE(${keystr}, ${column}) > 0");
|
||||
this.notcontainSQL = conf.getProperty(Sources.JDBC_NOTCONTAIN_SQLTEMPLATE, "LOCATE(${keystr}, ${column}) = 0");
|
||||
|
||||
this.tablenotexistSqlstates = ";" + conf.getProperty(JDBCPoolSource.JDBC_TABLENOTEXIST_SQLSTATES, "42000;42S02") + ";";
|
||||
this.tablecopySQL = conf.getProperty(JDBCPoolSource.JDBC_TABLECOPY_SQLTEMPLATE, "CREATE TABLE ${newtable} LIKE ${oldtable}");
|
||||
this.tablenotexistSqlstates = ";" + conf.getProperty(Sources.JDBC_TABLENOTEXIST_SQLSTATES, "42000;42S02") + ";";
|
||||
this.tablecopySQL = conf.getProperty(Sources.JDBC_TABLECOPY_SQLTEMPLATE, "CREATE TABLE ${newtable} LIKE ${oldtable}");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
*/
|
||||
package org.redkale.source;
|
||||
|
||||
import static org.redkale.source.DataDefaultSource.*;
|
||||
import java.io.*;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -17,6 +16,7 @@ import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.logging.Level;
|
||||
import javax.sql.*;
|
||||
import static org.redkale.source.Sources.*;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -27,26 +27,6 @@ import javax.sql.*;
|
||||
*/
|
||||
public class JDBCPoolSource {
|
||||
|
||||
static final String JDBC_CONNECTIONSMAX = "javax.persistence.connections.limit";
|
||||
|
||||
static final String JDBC_CONTAIN_SQLTEMPLATE = "javax.persistence.contain.sqltemplate";
|
||||
|
||||
static final String JDBC_NOTCONTAIN_SQLTEMPLATE = "javax.persistence.notcontain.sqltemplate";
|
||||
|
||||
static final String JDBC_TABLENOTEXIST_SQLSTATES = "javax.persistence.tablenotexist.sqlstates";
|
||||
|
||||
static final String JDBC_TABLECOPY_SQLTEMPLATE = "javax.persistence.tablecopy.sqltemplate";
|
||||
|
||||
static final String JDBC_URL = "javax.persistence.jdbc.url";
|
||||
|
||||
static final String JDBC_USER = "javax.persistence.jdbc.user";
|
||||
|
||||
static final String JDBC_PWD = "javax.persistence.jdbc.password";
|
||||
|
||||
static final String JDBC_DRIVER = "javax.persistence.jdbc.driver";
|
||||
|
||||
static final String JDBC_SOURCE = "javax.persistence.jdbc.source";
|
||||
|
||||
private static final Map<String, AbstractMap.SimpleEntry<WatchService, List<WeakReference<JDBCPoolSource>>>> maps = new HashMap<>();
|
||||
|
||||
private final AtomicLong usingCounter = new AtomicLong();
|
||||
@@ -230,7 +210,7 @@ public class JDBCPoolSource {
|
||||
Thread.sleep(2000L);
|
||||
if (d == f.lastModified()) break;
|
||||
}
|
||||
final Map<String, Properties> m = loadProperties(new FileInputStream(file));
|
||||
final Map<String, Properties> m = loadPersistenceXml(new FileInputStream(file));
|
||||
key.pollEvents().stream().forEach((event) -> {
|
||||
if (event.kind() != ENTRY_MODIFY) return;
|
||||
if (!((Path) event.context()).toFile().getName().equals(f.getName())) return;
|
||||
|
||||
136
src/org/redkale/source/Sources.java
Normal file
136
src/org/redkale/source/Sources.java
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.source;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
import javax.xml.stream.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public final class Sources {
|
||||
|
||||
public static final String DATASOURCE_CONFPATH = "DATASOURCE_CONFPATH";
|
||||
|
||||
public static final String JDBC_DATASOURCE_CLASS = "javax.persistence.datasource";
|
||||
|
||||
public static final String JDBC_CONNECTIONSMAX = "javax.persistence.connections.limit";
|
||||
|
||||
public static final String JDBC_CONTAIN_SQLTEMPLATE = "javax.persistence.contain.sqltemplate";
|
||||
|
||||
public static final String JDBC_NOTCONTAIN_SQLTEMPLATE = "javax.persistence.notcontain.sqltemplate";
|
||||
|
||||
public static final String JDBC_TABLENOTEXIST_SQLSTATES = "javax.persistence.tablenotexist.sqlstates";
|
||||
|
||||
public static final String JDBC_TABLECOPY_SQLTEMPLATE = "javax.persistence.tablecopy.sqltemplate";
|
||||
|
||||
public static final String JDBC_URL = "javax.persistence.jdbc.url";
|
||||
|
||||
public static final String JDBC_USER = "javax.persistence.jdbc.user";
|
||||
|
||||
public static final String JDBC_PWD = "javax.persistence.jdbc.password";
|
||||
|
||||
public static final String JDBC_DRIVER = "javax.persistence.jdbc.driver";
|
||||
|
||||
public static final String JDBC_SOURCE = "javax.persistence.jdbc.source";
|
||||
|
||||
private Sources() {
|
||||
}
|
||||
|
||||
public static DataSource createDataSource(final String unitName) throws IOException {
|
||||
return createDataSource(unitName, System.getProperty(DATASOURCE_CONFPATH) == null
|
||||
? DataDefaultSource.class.getResource("/META-INF/persistence.xml")
|
||||
: new File(System.getProperty(DATASOURCE_CONFPATH)).toURI().toURL());
|
||||
}
|
||||
|
||||
public static DataSource createDataSource(final String unitName, URL url) throws IOException {
|
||||
if (url == null) url = Sources.class.getResource("/persistence.xml");
|
||||
InputStream in = url.openStream();
|
||||
if (in == null) return null;
|
||||
Map<String, Properties> map = loadPersistenceXml(in);
|
||||
Properties readprop = null;
|
||||
Properties writeprop = null;
|
||||
if (unitName != null) {
|
||||
readprop = map.get(unitName);
|
||||
writeprop = readprop;
|
||||
if (readprop == null) {
|
||||
readprop = map.get(unitName + ".read");
|
||||
writeprop = map.get(unitName + ".write");
|
||||
}
|
||||
}
|
||||
if ((unitName == null || unitName.isEmpty()) || readprop == null) {
|
||||
String key = null;
|
||||
for (Map.Entry<String, Properties> en : map.entrySet()) {
|
||||
key = en.getKey();
|
||||
readprop = en.getValue();
|
||||
writeprop = readprop;
|
||||
break;
|
||||
}
|
||||
if (key != null && (key.endsWith(".read") || key.endsWith(".write"))) {
|
||||
if (key.endsWith(".read")) {
|
||||
writeprop = map.get(key.substring(0, key.lastIndexOf('.')) + ".write");
|
||||
} else {
|
||||
readprop = map.get(key.substring(0, key.lastIndexOf('.')) + ".read");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (readprop == null) throw new IOException("Cannot find (resource.name = '" + unitName + "') DataSource");
|
||||
String impl = readprop.getProperty(JDBC_DATASOURCE_CLASS, DataDefaultSource.class.getName());
|
||||
if (DataDefaultSource.class.getName().equals(impl)) return new DataDefaultSource(unitName, readprop, writeprop);
|
||||
try {
|
||||
Class ds = Class.forName(impl);
|
||||
for (Constructor d : ds.getConstructors()) {
|
||||
Class<?>[] paramtypes = d.getParameterTypes();
|
||||
if (paramtypes.length == 1 && paramtypes[0] == Properties.class) {
|
||||
return (DataSource) d.newInstance(readprop);
|
||||
} else if (paramtypes.length == 2 && paramtypes[0] == String.class && paramtypes[1] == Properties.class) {
|
||||
return (DataSource) d.newInstance(unitName, readprop);
|
||||
} else if (paramtypes.length == 3 && paramtypes[0] == String.class && paramtypes[1] == Properties.class && paramtypes[2] == Properties.class) {
|
||||
return (DataSource) d.newInstance(unitName, readprop, writeprop);
|
||||
}
|
||||
}
|
||||
throw new IOException("DataSource impl class (" + impl + ") have no Constructor by (Properties prop) or (String name, Properties prop) or (String name, Properties readprop, Propertieswriteprop)");
|
||||
} catch (IOException ex) {
|
||||
throw ex;
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
static Map<String, Properties> loadPersistenceXml(final InputStream in0) {
|
||||
final Map<String, Properties> map = new LinkedHashMap();
|
||||
Properties result = new Properties();
|
||||
boolean flag = false;
|
||||
try (final InputStream in = in0) {
|
||||
XMLStreamReader reader = XMLInputFactory.newFactory().createXMLStreamReader(in);
|
||||
while (reader.hasNext()) {
|
||||
int event = reader.next();
|
||||
if (event == XMLStreamConstants.START_ELEMENT) {
|
||||
if ("persistence-unit".equalsIgnoreCase(reader.getLocalName())) {
|
||||
if (!result.isEmpty()) result = new Properties();
|
||||
map.put(reader.getAttributeValue(null, "name"), result);
|
||||
flag = true;
|
||||
} else if (flag && "property".equalsIgnoreCase(reader.getLocalName())) {
|
||||
String name = reader.getAttributeValue(null, "name");
|
||||
String value = reader.getAttributeValue(null, "value");
|
||||
if (name == null) continue;
|
||||
result.put(name, value);
|
||||
} else if (flag && "shared-cache-mode".equalsIgnoreCase(reader.getLocalName())) {
|
||||
result.put(reader.getLocalName(), reader.getElementText());
|
||||
}
|
||||
}
|
||||
}
|
||||
in.close();
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,7 @@
|
||||
*/
|
||||
package org.redkale.test.source;
|
||||
|
||||
import org.redkale.source.DataDefaultSource;
|
||||
import org.redkale.source.DataSource;
|
||||
import org.redkale.source.*;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -15,7 +14,7 @@ import org.redkale.source.DataSource;
|
||||
public class JDBCTest {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
DataSource source = new DataDefaultSource(); //耗时:37415
|
||||
DataSource source = Sources.createDataSource(""); //耗时:37415
|
||||
int count = 1000;
|
||||
LoginTestRecord last = null;
|
||||
long s = System.currentTimeMillis();
|
||||
|
||||
Reference in New Issue
Block a user