This commit is contained in:
Redkale
2017-03-20 13:25:42 +08:00
parent 73d243aaf1
commit 95b7e819cd
8 changed files with 152 additions and 135 deletions

View File

@@ -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的子类。

View File

@@ -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");

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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}");
}
/**

View File

@@ -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;

View 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;
}
}

View File

@@ -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();