改版EntityXInfo

This commit is contained in:
地平线
2015-05-30 15:55:53 +08:00
parent d6dfcb7058
commit 5d8b492503
5 changed files with 273 additions and 155 deletions

View File

@@ -65,7 +65,7 @@ public final class DataJDBCSource implements DataSource {
final List<Class> cacheClasses = new ArrayList<>();
@Resource(name = "property.datasource.nodeid")
private int nodeid;
int nodeid;
@Resource
DataSQLListener writeListener;
@@ -122,8 +122,8 @@ public final class DataJDBCSource implements DataSource {
public DataJDBCSource(final String unitName) throws IOException {
this(unitName, System.getProperty(DATASOURCE_CONFPATH) == null
? DataJDBCSource.class.getResource("/META-INF/persistence.xml")
: new File(System.getProperty(DATASOURCE_CONFPATH)).toURI().toURL());
? DataJDBCSource.class.getResource("/META-INF/persistence.xml")
: new File(System.getProperty(DATASOURCE_CONFPATH)).toURI().toURL());
}
public DataJDBCSource(final String unitName, URL url) throws IOException {
@@ -240,7 +240,7 @@ public final class DataJDBCSource implements DataSource {
private static ConnectionPoolDataSource createDataSource(Properties property) {
try {
return createDataSource(property.getProperty(JDBC_SOURCE, property.getProperty(JDBC_DRIVER)),
property.getProperty(JDBC_URL), property.getProperty(JDBC_USER), property.getProperty(JDBC_PWD));
property.getProperty(JDBC_URL), property.getProperty(JDBC_USER), property.getProperty(JDBC_PWD));
} catch (Exception ex) {
throw new RuntimeException("(" + property + ") have no jdbc parameters", ex);
}
@@ -339,6 +339,10 @@ public final class DataJDBCSource implements DataSource {
}
}
private <T> EntityInfo<T> loadEntityInfo(Class<T> clazz) {
return EntityInfo.load(clazz, this);
}
/**
* 将entity的对象全部加载到Cache中去如果clazz没有被@javax.persistence.Cacheable注解则不做任何事
* <p>
@@ -386,16 +390,16 @@ public final class DataJDBCSource implements DataSource {
if (values.length == 0) return;
try {
final Class<T> clazz = (Class<T>) values[0].getClass();
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
final EntityCache<T> cache = info.inner.getCache();
final String sql = info.insert.sql;
final EntityInfo<T> info = loadEntityInfo(clazz);
final EntityCache<T> cache = info.getCache();
final String sql = info.insertSQL;
if (debug.get()) logger.finest(clazz.getSimpleName() + " insert sql=" + sql);
final PreparedStatement prestmt = info.autoGenerated
? conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS) : conn.prepareStatement(sql);
final Class primaryType = info.getPrimaryType();
? conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS) : conn.prepareStatement(sql);
final Class primaryType = info.getPrimary().type();
final Attribute primary = info.getPrimary();
final boolean distributed = info.distributed;
Attribute<T, ?>[] attrs = info.insert.attributes;
Attribute<T, ?>[] attrs = info.insertAttributes;
String[] sqls = null;
if (distributed && !info.initedPrimaryValue && primaryType.isPrimitive()) {
synchronized (info) {
@@ -415,7 +419,7 @@ public final class DataJDBCSource implements DataSource {
stmt.close();
if (info.distributeTables != null) {
for (final Class t : info.distributeTables) {
EntityXInfo<T> infox = EntityXInfo.load(this, t);
EntityInfo<T> infox = loadEntityInfo(t);
stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT MAX(" + infox.getPrimarySQLColumn() + ") FROM " + infox.getTable());
if (rs.next()) {
@@ -501,8 +505,8 @@ public final class DataJDBCSource implements DataSource {
public <T> void insertCache(T... values) {
if (values.length == 0) return;
final EntityXInfo<T> info = EntityXInfo.load(this, (Class<T>) values[0].getClass());
final EntityCache<T> cache = info.inner.getCache();
final EntityInfo<T> info = EntityInfo.load((Class<T>) values[0].getClass(), this);
final EntityCache<T> cache = info.getCache();
if (cache == null) return;
for (T value : values) {
cache.insert(value);
@@ -541,8 +545,8 @@ public final class DataJDBCSource implements DataSource {
private <T> void delete(final Connection conn, T... values) {
if (values.length == 0) return;
final Class clazz = values[0].getClass();
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
final Attribute primary = info.inner.getPrimary();
final EntityInfo<T> info = loadEntityInfo(clazz);
final Attribute primary = info.getPrimary();
Serializable[] ids = new Serializable[values.length];
int i = 0;
for (final T value : values) {
@@ -556,7 +560,7 @@ public final class DataJDBCSource implements DataSource {
*
* @param <T>
* @param clazz
* @param ids 主键值
* @param ids 主键值
*/
@Override
public <T> void delete(Class<T> clazz, Serializable... ids) {
@@ -582,7 +586,7 @@ public final class DataJDBCSource implements DataSource {
}
private <T> void delete(final Connection conn, Class<T> clazz, Serializable... ids) {
deleteByColumn(conn, clazz, EntityXInfo.load(this, clazz).getPrimaryField(), ids);
deleteByColumn(conn, clazz, loadEntityInfo(clazz).getPrimary().field(), ids);
}
/**
@@ -620,7 +624,7 @@ public final class DataJDBCSource implements DataSource {
private <T> void deleteByColumn(final Connection conn, Class<T> clazz, String column, Serializable... keys) {
if (keys.length == 0) return;
try {
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
final EntityInfo<T> info = loadEntityInfo(clazz);
String sql = "DELETE FROM " + info.getTable() + " WHERE " + info.getSQLColumn(column);
if (keys.length == 1 && !keys[0].getClass().isArray()) {
sql += " = " + formatToString(keys[0]);
@@ -653,7 +657,7 @@ public final class DataJDBCSource implements DataSource {
stmt.close();
if (writeListener != null) writeListener.delete(name, sql);
//------------------------------------
final EntityCache<T> cache = info.inner.getCache();
final EntityCache<T> cache = info.getCache();
if (cache == null) return;
final Attribute<T, ?> attr = info.getAttribute(column);
final Serializable[] keys2 = keys;
@@ -702,16 +706,16 @@ public final class DataJDBCSource implements DataSource {
private <T> void deleteByTwoColumn(final Connection conn, Class<T> clazz, String column1, Serializable key1, String column2, Serializable key2) {
try {
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
final EntityInfo<T> info = loadEntityInfo(clazz);
String sql = "DELETE FROM " + info.getTable() + " WHERE " + info.getSQLColumn(column1) + " = " + formatToString(key1)
+ " AND " + info.getSQLColumn(column2) + " = " + formatToString(key2);
+ " AND " + info.getSQLColumn(column2) + " = " + formatToString(key2);
if (debug.get()) logger.finest(clazz.getSimpleName() + " delete sql=" + sql);
final Statement stmt = conn.createStatement();
stmt.execute(sql);
stmt.close();
if (writeListener != null) writeListener.delete(name, sql);
//------------------------------------
final EntityCache<T> cache = info.inner.getCache();
final EntityCache<T> cache = info.getCache();
if (cache == null) return;
final Attribute<T, ?> attr1 = info.getAttribute(column1);
final Attribute<T, ?> attr2 = info.getAttribute(column2);
@@ -724,8 +728,8 @@ public final class DataJDBCSource implements DataSource {
public <T> void deleteCache(Class<T> clazz, Serializable... ids) {
if (ids.length == 0) return;
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
final EntityCache<T> cache = info.inner.getCache();
final EntityInfo<T> info = loadEntityInfo(clazz);
final EntityCache<T> cache = info.getCache();
if (cache == null) return;
for (Serializable id : ids) {
cache.delete(id);
@@ -764,10 +768,10 @@ public final class DataJDBCSource implements DataSource {
private <T> void update(final Connection conn, T... values) {
try {
Class clazz = values[0].getClass();
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
if (debug.get()) logger.finest(clazz.getSimpleName() + " update sql=" + info.update.sql);
final PreparedStatement prestmt = conn.prepareStatement(info.update.sql);
Attribute<T, ?>[] attrs = info.update.attributes;
final EntityInfo<T> info = loadEntityInfo(clazz);
if (debug.get()) logger.finest(clazz.getSimpleName() + " update sql=" + info.updateSQL);
final PreparedStatement prestmt = conn.prepareStatement(info.updateSQL);
Attribute<T, ?>[] attrs = info.updateAttributes;
String[] sqls = null;
if (writeListener == null) {
for (final T value : values) {
@@ -778,7 +782,7 @@ public final class DataJDBCSource implements DataSource {
prestmt.addBatch();
}
} else {
char[] sqlchars = info.update.sql.toCharArray();
char[] sqlchars = info.updateSQL.toCharArray();
sqls = new String[values.length];
String[] ps = new String[attrs.length];
int index = 0;
@@ -807,7 +811,7 @@ public final class DataJDBCSource implements DataSource {
prestmt.close();
if (writeListener != null) writeListener.update(name, sqls);
//---------------------------------------------------
final EntityCache<T> cache = info.inner.getCache();
final EntityCache<T> cache = info.getCache();
if (cache == null) return;
for (final T value : values) {
cache.update(value);
@@ -854,7 +858,7 @@ public final class DataJDBCSource implements DataSource {
private <T> void updateColumn(Connection conn, Class<T> clazz, Serializable id, String column, Serializable value) {
try {
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
final EntityInfo<T> info = loadEntityInfo(clazz);
String sql = "UPDATE " + info.getTable() + " SET " + info.getSQLColumn(column) + " = " + formatToString(value) + " WHERE " + info.getPrimarySQLColumn() + " = " + formatToString(id);
if (debug.get()) logger.finest(clazz.getSimpleName() + " update sql=" + sql);
final Statement stmt = conn.createStatement();
@@ -862,7 +866,7 @@ public final class DataJDBCSource implements DataSource {
stmt.close();
if (writeListener != null) writeListener.update(name, sql);
//---------------------------------------------------
final EntityCache<T> cache = info.inner.getCache();
final EntityCache<T> cache = info.getCache();
if (cache == null) return;
T rs = cache.update(id, (Attribute<T, Serializable>) info.getAttribute(column), value);
if (cacheListener != null) cacheListener.update(name, clazz, rs);
@@ -909,7 +913,7 @@ public final class DataJDBCSource implements DataSource {
private <T> void updateColumnIncrement(Connection conn, Class<T> clazz, Serializable id, String column, long incvalue) {
try {
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
final EntityInfo<T> info = loadEntityInfo(clazz);
String col = info.getSQLColumn(column);
String sql = "UPDATE " + info.getTable() + " SET " + col + " = " + col + " + (" + incvalue + ") WHERE " + info.getPrimarySQLColumn() + " = " + formatToString(id);
if (debug.get()) logger.finest(clazz.getSimpleName() + " update sql=" + sql);
@@ -918,7 +922,7 @@ public final class DataJDBCSource implements DataSource {
stmt.close();
if (writeListener != null) writeListener.update(name, sql);
//---------------------------------------------------
final EntityCache<T> cache = info.inner.getCache();
final EntityCache<T> cache = info.getCache();
if (cache == null) return;
Attribute<T, Object> attr = (Attribute<T, Object>) info.getAttribute(column);
T value = cache.updateColumnIncrement(id, attr, incvalue);
@@ -964,7 +968,7 @@ public final class DataJDBCSource implements DataSource {
if (columns.length < 1) return;
try {
final Class<T> clazz = (Class<T>) value.getClass();
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
final EntityInfo<T> info = loadEntityInfo(clazz);
StringBuilder setsql = new StringBuilder();
Attribute<T, ?>[] attrs = new Attribute[columns.length];
int i = - 1;
@@ -973,17 +977,17 @@ public final class DataJDBCSource implements DataSource {
if (setsql.length() > 0) setsql.append(',');
attrs[++i] = info.getAttribute(col);
setsql.append(info.getSQLColumn(col)).append(" = ")
.append(formatToString(attrs[i].get(value)));
.append(formatToString(attrs[i].get(value)));
}
String sql = "UPDATE " + info.getTable() + " SET " + setsql + " WHERE " + info.getPrimarySQLColumn() + " = "
+ formatToString(id);
+ formatToString(id);
if (debug.get()) logger.finest(value.getClass().getSimpleName() + ": " + sql);
final Statement stmt = conn.createStatement();
stmt.execute(sql);
stmt.close();
if (writeListener != null) writeListener.update(name, sql);
//---------------------------------------------------
final EntityCache<T> cache = info.inner.getCache();
final EntityCache<T> cache = info.getCache();
if (cache == null) return;
cache.update(value, attrs);
if (cacheListener != null) cacheListener.update(name, clazz, value);
@@ -994,8 +998,8 @@ public final class DataJDBCSource implements DataSource {
public <T> void updateCache(Class<T> clazz, T... values) {
if (values.length == 0) return;
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
final EntityCache<T> cache = info.inner.getCache();
final EntityInfo<T> info = loadEntityInfo(clazz);
final EntityCache<T> cache = info.getCache();
if (cache == null) return;
for (T value : values) {
cache.update(value);
@@ -1003,8 +1007,8 @@ public final class DataJDBCSource implements DataSource {
}
public <T> void reloadCache(Class<T> clazz, Serializable... ids) {
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
final EntityCache<T> cache = info.inner.getCache();
final EntityInfo<T> info = loadEntityInfo(clazz);
final EntityCache<T> cache = info.getCache();
if (cache == null) return;
for (Serializable id : ids) {
T value = find(clazz, null, false, id);
@@ -1081,15 +1085,15 @@ public final class DataJDBCSource implements DataSource {
private <T> Number getSingleResult(final ReckonType type, final Class<T> entityClass, final String column, FilterBean bean) {
final Connection conn = createReadSQLConnection();
try {
final EntityXInfo<T> info = EntityXInfo.load(this, entityClass);
final EntityCache<T> cache = info.inner.getCache();
final EntityInfo<T> info = loadEntityInfo(entityClass);
final EntityCache<T> cache = info.getCache();
if (cache != null && cache.isFullLoaded()) {
Predicate<T> filter = null;
boolean valid = true;
if (bean != null) {
FilterInfo finfo = FilterInfo.load(bean.getClass(), this);
valid = finfo.isValidCacheJoin();
if (valid) filter = finfo.getFilterPredicate(info.inner, bean);
if (valid) filter = finfo.getFilterPredicate(info, bean);
}
if (valid) return cache.getSingleResult(type, column == null ? null : info.getAttribute(column), filter);
}
@@ -1131,24 +1135,21 @@ public final class DataJDBCSource implements DataSource {
}
private <T> T find(Class<T> clazz, final SelectColumn selects, boolean readcache, Serializable pk) {
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
final EntityCache<T> cache = info.inner.getCache();
final EntityInfo<T> info = loadEntityInfo(clazz);
final EntityCache<T> cache = info.getCache();
if (readcache && cache != null) {
T r = cache.find(pk);
if (r != null || cache.isFullLoaded()) return r;
}
final Connection conn = createReadSQLConnection();
try {
if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " find sql=" + info.query.sql.replace("?", String.valueOf(pk)));
final PreparedStatement prestmt = conn.prepareStatement(info.query.sql);
if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " find sql=" + info.querySQL.replace("?", String.valueOf(pk)));
final PreparedStatement prestmt = conn.prepareStatement(info.querySQL);
prestmt.setObject(1, pk);
T rs = null;
ResultSet set = prestmt.executeQuery();
if (set.next()) {
rs = info.createInstance();
for (AttributeX attr : info.query.attributes) {
attr.setValue(selects, rs, set);
}
rs = info.getValue(selects, set);
}
set.close();
prestmt.close();
@@ -1170,7 +1171,7 @@ public final class DataJDBCSource implements DataSource {
*/
@Override
public <T> T[] find(Class<T> clazz, Serializable... ids) {
EntityXInfo<T> info = EntityXInfo.load(this, clazz);
EntityInfo<T> info = loadEntityInfo(clazz);
return findByColumn(clazz, info, null, info.getPrimarySQLColumn(), ids);
}
@@ -1185,7 +1186,7 @@ public final class DataJDBCSource implements DataSource {
*/
@Override
public <T> T findByColumn(Class<T> clazz, String column, Serializable key) {
EntityXInfo<T> info = EntityXInfo.load(this, clazz);
EntityInfo<T> info = loadEntityInfo(clazz);
return findByColumn(clazz, info, null, info.getSQLColumn(column), key)[0];
}
@@ -1202,8 +1203,8 @@ public final class DataJDBCSource implements DataSource {
*/
@Override
public <T> T findByTwoColumn(Class<T> clazz, String column1, Serializable key1, String column2, Serializable key2) {
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
final EntityCache<T> cache = info.inner.getCache();
final EntityInfo<T> info = loadEntityInfo(clazz);
final EntityCache<T> cache = info.getCache();
if (cache != null) {
final Attribute<T, ?> attr1 = info.getAttribute(column1);
final Attribute<T, ?> attr2 = info.getAttribute(column2);
@@ -1213,17 +1214,15 @@ public final class DataJDBCSource implements DataSource {
final Connection conn = createReadSQLConnection();
try {
final String sql = "SELECT * FROM " + info.getTable() + " WHERE " + info.getSQLColumn(column1) + " = ? AND " + info.getSQLColumn(column2) + " = ?";
if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " find sql=" + sql.replaceFirst("\\?", String.valueOf(key1)).replaceFirst("\\?", String.valueOf(key2)));
if (debug.get() && info.isLoggable(Level.FINEST))
logger.finest(clazz.getSimpleName() + " find sql=" + sql.replaceFirst("\\?", String.valueOf(key1)).replaceFirst("\\?", String.valueOf(key2)));
final PreparedStatement prestmt = conn.prepareStatement(sql);
prestmt.setObject(1, key1);
prestmt.setObject(2, key2);
T rs = null;
ResultSet set = prestmt.executeQuery();
if (set.next()) {
rs = info.createInstance();
for (AttributeX attr : info.query.attributes) {
attr.setValue(null, rs, set);
}
rs = info.getValue(null, set);
}
set.close();
prestmt.close();
@@ -1276,8 +1275,8 @@ public final class DataJDBCSource implements DataSource {
@Override
public <T> T[] findByColumn(Class<T> clazz, final SelectColumn selects, String column, Serializable... keys) {
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
final EntityCache<T> cache = info.inner.getCache();
final EntityInfo<T> info = loadEntityInfo(clazz);
final EntityCache<T> cache = info.getCache();
if (cache != null) {
Attribute<T, ?> idattr = info.getAttribute(column);
List<T> list = cache.queryList(selects, (x) -> Arrays.binarySearch(keys, idattr.get(x)) >= 0, null);
@@ -1299,7 +1298,7 @@ public final class DataJDBCSource implements DataSource {
return findByColumn(clazz, info, selects, info.getSQLColumn(column), keys);
}
private <T> T[] findByColumn(Class<T> clazz, final EntityXInfo<T> info, final SelectColumn selects, String sqlcolumn, Serializable... keys) {
private <T> T[] findByColumn(Class<T> clazz, final EntityInfo<T> info, final SelectColumn selects, String sqlcolumn, Serializable... keys) {
if (keys.length < 1) return (T[]) Array.newInstance(clazz, 0);
final Connection conn = createReadSQLConnection();
try {
@@ -1313,10 +1312,7 @@ public final class DataJDBCSource implements DataSource {
T one = null;
ResultSet set = prestmt.executeQuery();
if (set.next()) {
one = info.createInstance();
for (AttributeX attr : info.query.attributes) {
attr.setValue(selects, one, set);
}
one = info.getValue(selects, set);
}
rs[i] = one;
set.close();
@@ -1425,8 +1421,8 @@ public final class DataJDBCSource implements DataSource {
* @return
*/
protected final <T, V> Collection<V> queryColumnCollection(final boolean set, String selectedColumn, Class<T> clazz, String column, FilterExpress express, Serializable key) {
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
final EntityCache<T> cache = info.inner.getCache();
final EntityInfo<T> info = loadEntityInfo(clazz);
final EntityCache<T> cache = info.getCache();
if (cache != null) {
Predicate<T> filter = genFilter(info.getAttribute(column), express, key);
List<T> list = cache.queryList(SelectColumn.createIncludes(selectedColumn), filter, null);
@@ -1506,8 +1502,8 @@ public final class DataJDBCSource implements DataSource {
*/
@Override
public <T> List<T> queryList(Class<T> clazz, final SelectColumn selects, String column, FilterExpress express, Serializable key) {
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
final EntityCache<T> cache = info.inner.getCache();
final EntityInfo<T> info = loadEntityInfo(clazz);
final EntityCache<T> cache = info.getCache();
if (cache != null) {
Predicate<T> filter = genFilter(info.getAttribute(column), express, key);
List<T> rs = cache.queryList(selects, filter, null);
@@ -1522,11 +1518,7 @@ public final class DataJDBCSource implements DataSource {
final Statement ps = conn.createStatement();
final ResultSet set = ps.executeQuery(sql);
while (set.next()) {
final T result = info.createInstance();
for (AttributeX<T, Object> attr : info.query.attributes) {
attr.setValue(sels, result, set);
}
list.add(result);
list.add(info.getValue(sels, set));
}
set.close();
ps.close();
@@ -1538,7 +1530,7 @@ public final class DataJDBCSource implements DataSource {
}
}
private String genSQL(String queryColumn, EntityXInfo info, String column, FilterExpress express, Serializable key) {
private String genSQL(String queryColumn, EntityInfo info, String column, FilterExpress express, Serializable key) {
String sql = "SELECT " + queryColumn + " FROM " + info.getTable();
if (key instanceof Number) {
sql += " WHERE " + info.getSQLColumn(column) + " " + express.value() + " " + key;
@@ -1710,7 +1702,7 @@ public final class DataJDBCSource implements DataSource {
final Sheet<V> rs = new Sheet<>();
if (sheet.isEmpty()) return rs;
rs.setTotal(sheet.getTotal());
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
final EntityInfo<T> info = loadEntityInfo(clazz);
final Attribute<T, V> selected = (Attribute<T, V>) info.getAttribute(selectedColumn);
final List<V> list = new ArrayList<>();
for (T t : sheet.getRows()) {
@@ -1746,18 +1738,18 @@ public final class DataJDBCSource implements DataSource {
*/
@Override
public <T> Sheet<T> querySheet(Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterBean bean) {
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
final EntityCache<T> cache = info.inner.getCache();
final EntityInfo<T> info = loadEntityInfo(clazz);
final EntityCache<T> cache = info.getCache();
if (cache != null) {
Predicate<T> filter = null;
boolean valid = true;
if (bean != null) {
FilterInfo finfo = FilterInfo.load(bean.getClass(), this);
valid = finfo.isValidCacheJoin();
if (valid) filter = finfo.getFilterPredicate(info.inner, bean);
if (valid) filter = finfo.getFilterPredicate(info, bean);
}
if (valid) {
Sheet<T> sheet = cache.querySheet(selects, filter, flipper, FilterInfo.getSortComparator(info.inner, flipper));
Sheet<T> sheet = cache.querySheet(selects, filter, flipper, FilterInfo.getSortComparator(info, flipper));
if (!sheet.isEmpty() || cache.isFullLoaded()) return sheet;
}
}
@@ -1766,7 +1758,8 @@ public final class DataJDBCSource implements DataSource {
final SelectColumn sels = selects;
final List<T> list = new ArrayList();
final String sql = "SELECT a.* FROM " + info.getTable() + " a" + createWhereExpression(info, flipper, bean);
if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " query sql=" + sql + (flipper == null ? "" : (" LIMIT " + flipper.index() + "," + flipper.getSize())));
if (debug.get() && info.isLoggable(Level.FINEST))
logger.finest(clazz.getSimpleName() + " query sql=" + sql + (flipper == null ? "" : (" LIMIT " + flipper.index() + "," + flipper.getSize())));
final PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
final ResultSet set = ps.executeQuery();
if (flipper != null && flipper.index() > 0) set.absolute(flipper.index());
@@ -1775,11 +1768,7 @@ public final class DataJDBCSource implements DataSource {
long total;
while (set.next()) {
i++;
final T result = info.createInstance();
for (AttributeX<T, Object> attr : info.query.attributes) {
attr.setValue(sels, result, set);
}
list.add(result);
list.add(info.getValue(sels, set));
if (limit <= i) break;
}
if (flipper != null) {
@@ -1798,7 +1787,7 @@ public final class DataJDBCSource implements DataSource {
}
}
private <T> String createWhereExpression(final EntityXInfo<T> info, final Flipper flipper, final FilterBean bean) {
private <T> String createWhereExpression(final EntityInfo<T> info, final Flipper flipper, final FilterBean bean) {
if (bean == null && flipper == null) return "";
boolean emptySort = flipper == null || flipper.getSort() == null || flipper.getSort().isEmpty();
StringBuilder where = null;
@@ -1811,7 +1800,7 @@ public final class DataJDBCSource implements DataSource {
if (emptySort) return where == null ? "" : where.toString();
if (where == null) where = new StringBuilder();
where.append(" ORDER BY ");
if (info.same && !join) {
if (info.isNoAlias() && !join) {
where.append(flipper.getSort());
} else {
boolean flag = false;
@@ -2113,9 +2102,9 @@ public final class DataJDBCSource implements DataSource {
}
private static class EntityXInfo<T> {
private static class EntityXXInfo<T> {
private static final ConcurrentHashMap<Class, EntityXInfo> entityxInfos = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<Class, EntityXXInfo> entityxInfos = new ConcurrentHashMap<>();
private final int nodeid;
@@ -2163,7 +2152,7 @@ public final class DataJDBCSource implements DataSource {
}
}
public EntityXInfo(DataJDBCSource source, Class<T> type) {
public EntityXXInfo(DataJDBCSource source, Class<T> type) {
this.inner = EntityInfo.load(type, source);
this.nodeid = source.nodeid;
DistributeTables dt = type.getAnnotation(DistributeTables.class);
@@ -2233,7 +2222,7 @@ public final class DataJDBCSource implements DataSource {
queryattrs.add(attr);
}
} while ((cltmp = cltmp.getSuperclass()) != Object.class);
AttributeX idxattr = new AttributeX(type, idfieldtype, inner.getPrimary(), inner.getPrimaryField());
AttributeX idxattr = new AttributeX(type, idfieldtype, inner.getPrimary(), inner.getPrimary().field());
updateattrs.add(idxattr);
this.autoGenerated = auto;
this.delete = new ActionInfo("DELETE FROM " + inner.getTable() + wheresql, idxattr);
@@ -2259,13 +2248,13 @@ public final class DataJDBCSource implements DataSource {
this.query = new ActionInfo("SELECT * FROM " + inner.getTable() + wheresql, queryattrs);
}
public static <T> EntityXInfo<T> load(DataJDBCSource source, Class<T> clazz) {
EntityXInfo rs = entityxInfos.get(clazz);
public static <T> EntityXXInfo<T> load(DataJDBCSource source, Class<T> clazz) {
EntityXXInfo rs = entityxInfos.get(clazz);
if (rs != null) return rs;
synchronized (entityxInfos) {
rs = entityxInfos.get(clazz);
if (rs == null) {
rs = new EntityXInfo(source, clazz);
rs = new EntityXXInfo(source, clazz);
entityxInfos.put(clazz, rs);
}
return rs;
@@ -2282,7 +2271,7 @@ public final class DataJDBCSource implements DataSource {
public void createPrimaryValue(T src) {
long v = allocationSize > 1 ? (primaryValue.incrementAndGet() * allocationSize + nodeid) : primaryValue.incrementAndGet();
Class p = inner.getPrimaryType();
Class p = inner.getPrimary().type();
if (p == int.class || p == Integer.class) {
getPrimary().set(src, (Integer) ((Long) v).intValue());
} else {
@@ -2290,18 +2279,10 @@ public final class DataJDBCSource implements DataSource {
}
}
public Class getPrimaryType() {
return inner.getPrimaryType();
}
public Attribute<T, Object> getPrimary() {
public Attribute<T, Serializable> getPrimary() {
return inner.getPrimary();
}
public String getPrimaryField() {
return inner.getPrimaryField();
}
public String getTable() {
return inner.getTable();
}

View File

@@ -519,7 +519,7 @@ final class DataJPASource implements DataSource {
final CriteriaBuilder builder = manager.getCriteriaBuilder();
CriteriaUpdate<T> cd = builder.createCriteriaUpdate(clazz);
cd.set(column, value);
cd.where(builder.equal(cd.from(clazz).get(EntityInfo.load(clazz, this).getPrimaryField()), id));
cd.where(builder.equal(cd.from(clazz).get(EntityInfo.load(clazz, this).getPrimary().field()), id));
manager.createQuery(cd).executeUpdate();
}
@@ -565,7 +565,7 @@ final class DataJPASource implements DataSource {
for (String column : columns) {
cd.set(column, info.getAttribute(column).get(value));
}
cd.where(builder.equal(cd.from(clazz).get(info.getPrimaryField()), idattr.get(value)));
cd.where(builder.equal(cd.from(clazz).get(info.getPrimary().field()), idattr.get(value)));
manager.createQuery(cd).executeUpdate();
}
@@ -1037,7 +1037,7 @@ final class DataJPASource implements DataSource {
private <T> List<T> selectList(final Class<T> clazz, final SelectColumn selects, final List<T> list) {
if (selects == null || selects.isEmpty() || list.isEmpty()) return list;
final EntityInfo info = EntityInfo.load(clazz, this);
final Object dftValue = info.getDefaultTypeInstance();
final Object dftValue = info.getCreator().create();
final Map<String, Attribute> map = info.getAttributes();
final List<Attribute> attrs = new ArrayList<>();
if (selects.isExcludable()) {

View File

@@ -5,10 +5,7 @@
*/
package com.wentch.redkale.source;
import com.wentch.redkale.util.Sheet;
import com.wentch.redkale.util.Reproduce;
import com.wentch.redkale.util.Creator;
import com.wentch.redkale.util.Attribute;
import com.wentch.redkale.util.*;
import java.io.*;
import java.lang.reflect.Field;
import java.util.*;
@@ -36,8 +33,9 @@ final class EntityCache<T> {
private final Creator<T> creator;
private final Attribute<T, Object> primary;
private final Attribute<T, Serializable> primary;
//key是field的name
private final Map<String, Attribute<T, ?>> attributes;
private final Reproduce<T, T> reproduce;
@@ -45,7 +43,7 @@ final class EntityCache<T> {
private boolean fullloaded;
public EntityCache(final Class<T> type, Creator<T> creator,
Attribute<T, Object> primary, Map<String, Attribute<T, ?>> attributes) {
Attribute<T, Serializable> primary, Map<String, Attribute<T, ?>> attributes) {
this.type = type;
this.creator = creator;
this.primary = primary;

View File

@@ -7,9 +7,12 @@ package com.wentch.redkale.source;
import com.sun.istack.internal.logging.Logger;
import com.wentch.redkale.util.*;
import java.io.Serializable;
import java.lang.reflect.*;
import java.sql.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.*;
import javax.persistence.*;
@@ -25,32 +28,66 @@ public final class EntityInfo<T> {
private static final Logger logger = Logger.getLogger(EntityInfo.class);
//Entity类的类名
private final Class<T> type;
//类对应的数据表名
private final String table;
private final Creator<T> creator;
private final Class primaryType;
private final Attribute<T, Object> primary;
private final String primaryFieldName;
private final T defaultTypeInstance;
//主键
private final Attribute<T, Serializable> primary;
private final EntityCache<T> cache;
//key是field的name value是Column的别名即数据库表的字段名
//只有field.name 与 Column.name不同才存放在aliasmap里.
private final Map<String, String> aliasmap;
//key是field的name 不是sql字段。
//存放所有与数据库对应的字段, 包括主键
private final Map<String, Attribute<T, ?>> attributes = new HashMap<>();
final String querySQL;
private final Attribute<T, Object>[] queryAttributes; //数据库中所有字段
final String insertSQL;
final Attribute<T, Object>[] insertAttributes; //数据库中所有可新增字段
final String updateSQL;
final Attribute<T, Object>[] updateAttributes; //数据库中所有可更新字段
final String deleteSQL;
private final int logLevel;
//---------------------计算主键值----------------------------
private final int nodeid;
final Class[] distributeTables;
final boolean autoGenerated;
final boolean distributed;
boolean initedPrimaryValue = false;
final AtomicLong primaryValue = new AtomicLong(0);
final int allocationSize;
//------------------------------------------------------------
public static <T> EntityInfo<T> load(Class<T> clazz, final DataSource source) {
EntityInfo rs = entityInfos.get(clazz);
if (rs != null) return rs;
synchronized (entityInfos) {
rs = entityInfos.get(clazz);
if (rs == null) {
final List<Class> cacheClasses = source instanceof DataJDBCSource ? ((DataJDBCSource) source).cacheClasses : null;
rs = new EntityInfo(clazz, cacheClasses);
rs = new EntityInfo(clazz, ((DataJDBCSource) source).nodeid, ((DataJDBCSource) source).cacheClasses);
entityInfos.put(clazz, rs);
if (rs.cache != null && source != null) {
AutoLoad auto = clazz.getAnnotation(AutoLoad.class);
@@ -66,45 +103,112 @@ public final class EntityInfo<T> {
}
}
private EntityInfo(Class<T> type, final List<Class> cacheClasses) {
private EntityInfo(Class<T> type, int nodeid, final List<Class> cacheClasses) {
this.type = type;
//---------------------------------------------
this.nodeid = nodeid;
DistributeGenerator.DistributeTables dt = type.getAnnotation(DistributeGenerator.DistributeTables.class);
this.distributeTables = dt == null ? null : dt.value();
LogLevel ll = type.getAnnotation(LogLevel.class);
this.logLevel = ll == null ? Integer.MIN_VALUE : Level.parse(ll.value()).intValue();
//---------------------------------------------
Table t = type.getAnnotation(Table.class);
this.table = (t == null) ? type.getSimpleName().toLowerCase() : (t.catalog().isEmpty()) ? t.name() : (t.catalog() + '.' + t.name());
this.creator = Creator.create(type);
this.defaultTypeInstance = this.creator.create();
Attribute idAttr0 = null;
Class primaryType0 = null;
String primaryName = null;
Map<String, String> aliasmap0 = null;
Class cltmp = type;
Set<String> fields = new HashSet<>();
List<Attribute<T, ?>> queryattrs = new ArrayList<>();
List<String> insertcols = new ArrayList<>();
List<Attribute<T, ?>> insertattrs = new ArrayList<>();
List<String> updatecols = new ArrayList<>();
List<Attribute<T, ?>> updateattrs = new ArrayList<>();
boolean auto = false;
boolean sqldistribute = false;
int allocationSize0 = 0;
do {
for (Field field : cltmp.getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers())) continue;
if (Modifier.isFinal(field.getModifiers())) continue;
if (field.getAnnotation(Transient.class) != null) continue;
if (fields.contains(field.getName())) continue;
final String fieldname = field.getName();
final Column col = field.getAnnotation(Column.class);
final String sqlfield = col == null || col.name().isEmpty() ? field.getName() : col.name();
final String sqlfield = col == null || col.name().isEmpty() ? fieldname : col.name();
if (!fieldname.equals(sqlfield)) {
if (aliasmap0 == null) aliasmap0 = new HashMap<>();
aliasmap0.put(fieldname, sqlfield);
}
Attribute attr;
try {
attr = Attribute.create(cltmp, sqlfield, field);
attr = Attribute.create(cltmp, field);
} catch (RuntimeException e) {
continue;
}
if (field.getAnnotation(javax.persistence.Id.class) != null) {
if (idAttr0 == null) {
idAttr0 = attr;
primaryType0 = field.getType();
primaryName = field.getName();
if (field.getAnnotation(javax.persistence.Id.class) != null && idAttr0 == null) {
idAttr0 = attr;
GeneratedValue gv = field.getAnnotation(GeneratedValue.class);
auto = gv != null;
if (gv != null && gv.strategy() != GenerationType.IDENTITY) {
throw new RuntimeException(cltmp.getName() + "'s @ID primary not a GenerationType.IDENTITY");
}
DistributeGenerator dg = field.getAnnotation(DistributeGenerator.class);
if (dg != null) {
if (!field.getType().isPrimitive()) throw new RuntimeException(cltmp.getName() + "'s @DistributeGenerator primary must be primitive class type field");
sqldistribute = true;
auto = false;
allocationSize0 = dg.allocationSize();
primaryValue.set(dg.initialValue());
}
if (!auto) {
insertcols.add(sqlfield);
insertattrs.add(attr);
}
} else {
if (col == null || col.insertable()) {
insertcols.add(sqlfield);
insertattrs.add(attr);
}
if (col == null || col.updatable()) {
updatecols.add(sqlfield);
updateattrs.add(attr);
}
}
fields.add(field.getName());
attributes.put(field.getName(), attr);
queryattrs.add(attr);
fields.add(fieldname);
attributes.put(fieldname, attr);
}
} while ((cltmp = cltmp.getSuperclass()) != Object.class);
this.primary = idAttr0;
this.primaryType = primaryType0;
this.primaryFieldName = primaryName;
this.aliasmap = aliasmap0;
{
this.queryAttributes = queryattrs.toArray(new Attribute[queryattrs.size()]);
this.insertAttributes = insertattrs.toArray(new Attribute[insertattrs.size()]);
this.updateAttributes = updateattrs.toArray(new Attribute[updateattrs.size()]);
StringBuilder insertsb = new StringBuilder();
StringBuilder insertsb2 = new StringBuilder();
for (String col : insertcols) {
if (insertsb.length() > 0) insertsb.append(',');
insertsb.append(col);
if (insertsb2.length() > 0) insertsb2.append(',');
insertsb2.append('?');
}
this.insertSQL = "INSERT INTO " + table + "(" + insertsb + ") VALUES(" + insertsb2 + ")";
StringBuilder updatesb = new StringBuilder();
for (String col : updatecols) {
if (updatesb.length() > 0) updatesb.append(',');
updatesb.append(col).append(" = ?");
}
this.updateSQL = "UPDATE " + table + " SET " + updatesb + " WHERE " + getPrimarySQLColumn() + " = ?";
this.deleteSQL = "DELETE FROM " + table + " WHERE " + getPrimarySQLColumn() + " = ?";
this.querySQL = "SELECT * FROM " + table + " WHERE " + getPrimarySQLColumn() + " = ?";
}
this.autoGenerated = auto;
this.distributed = sqldistribute;
this.allocationSize = allocationSize0;
//----------------cache--------------
Cacheable c = type.getAnnotation(Cacheable.class);
boolean cf = (c == null) ? (cacheClasses != null && cacheClasses.contains(type)) : false;
@@ -115,6 +219,15 @@ public final class EntityInfo<T> {
}
}
public void createPrimaryValue(T src) {
long v = allocationSize > 1 ? (primaryValue.incrementAndGet() * allocationSize + nodeid) : primaryValue.incrementAndGet();
if (primary.type() == int.class || primary.type() == Integer.class) {
getPrimary().set(src, (Integer) ((Long) v).intValue());
} else {
getPrimary().set(src, v);
}
}
EntityCache<T> getCache() {
return cache;
}
@@ -131,27 +244,53 @@ public final class EntityInfo<T> {
return table;
}
public Class getPrimaryType() {
return this.primaryType;
}
public Attribute<T, Object> getPrimary() {
public Attribute<T, Serializable> getPrimary() {
return this.primary;
}
public String getPrimaryField() {
return this.primaryFieldName;
}
public Attribute<T, ?> getAttribute(String fieldname) {
return this.attributes.get(fieldname);
}
public T getDefaultTypeInstance() {
return defaultTypeInstance;
public boolean isNoAlias() {
return this.aliasmap == null;
}
//根据field字段名获取数据库对应的字段名
public String getSQLColumn(String fieldname) {
return this.aliasmap == null ? fieldname : aliasmap.getOrDefault(fieldname, fieldname);
}
//数据库字段名
public String getPrimarySQLColumn() {
return getSQLColumn(this.primary.field());
}
public Map<String, Attribute<T, ?>> getAttributes() {
return attributes;
}
public boolean isLoggable(Level l) {
return l.intValue() >= this.logLevel;
}
public T getValue(SelectColumn sels, ResultSet set) throws SQLException {
T obj = creator.create();
for (Attribute<T, Object> attr : queryAttributes) {
if (sels == null || sels.validate(attr.field())) {
Object o = set.getObject(this.getSQLColumn(attr.field()));
if (o != null) {
if (type == long.class) {
o = ((Number) o).longValue();
} else if (type == int.class) {
o = ((Number) o).intValue();
} else if (type == short.class) {
o = ((Number) o).shortValue();
}
}
attr.set(obj, o);
}
}
return obj;
}
}

View File

@@ -226,7 +226,7 @@ public class FilterNode {
if (o instanceof CharSequence) {
sb.append('"').append(o.toString().replace("\"", "\\\"")).append('"');
} else {
sb.append('"').append(o).append('"');
sb.append(o);
}
}
return sb.append(')').toString();
@@ -241,7 +241,7 @@ public class FilterNode {
if (o instanceof CharSequence) {
sb.append('"').append(o.toString().replace("\"", "\\\"")).append('"');
} else {
sb.append('"').append(o).append('"');
sb.append(o);
}
}
return sb.append(')').toString();