/* named * JEF - Copyright 2009-2010 Jiyi (mr.jiyi@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jef.database; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.sql.DataSource; import jef.common.Callback; import jef.common.log.LogUtil; import jef.common.pool.PoolStatus; import jef.database.cache.Cache; import jef.database.cache.CacheDummy; import jef.database.cache.CacheImpl; import jef.database.datasource.SimpleDataSource; import jef.database.dialect.AbstractDialect; import jef.database.dialect.DatabaseDialect; import jef.database.dialect.type.AutoIncrementMapping; import jef.database.innerpool.IConnection; import jef.database.innerpool.IPool; import jef.database.innerpool.IUserManagedPool; import jef.database.innerpool.PartitionSupport; import jef.database.innerpool.PoolService; import jef.database.innerpool.RoutingManagedConnectionPool; import jef.database.jmx.JefFacade; import jef.database.meta.AbstractMetadata; import jef.database.meta.ITableMetadata; import jef.database.meta.MetaHolder; import jef.database.meta.Reference; import jef.database.routing.PartitionResult; import jef.database.support.DbOperatorListener; import jef.database.support.DbOperatorListenerContainer; import jef.database.support.DefaultDbOperListener; import jef.database.support.MetadataEventListener; import jef.tools.Assert; import jef.tools.JefConfiguration; import jef.tools.StringUtils; import jef.tools.reflect.BeanUtils; import org.easyframe.enterprise.spring.TransactionMode; /** * 数据库操作句柄 * * DbClient是非事务状态下的数据库连接,每次操作后自动提交不能回滚。但可以执行建表、删表等DDL语句。 * * @author jiyi */ public class DbClient extends Session implements SessionFactory { /** * 命名查询 */ protected NamedQueryHolder namedQueries; /** * 数据库操作监听器 */ private DbOperatorListener listener; /** * Sequence管理器 */ private SequenceManager sequenceManager; /** * 事务支持类型 */ private TransactionMode txType = TransactionMode.JPA; /** * 连接池和metadata服务 */ private IUserManagedPool connPool; /** * 构造当前对象的DataSource 也可能是RoutingDataSource */ private DataSource ds; /** * 全局缓存 */ private Cache golbalCache; /** * 启动一个事务。 * * <h3>Example</h3> * * <pre> * <tt> * Transaction session=dbClient.startTransaction();//开启一个事务 * String sql = "delete from ROOT where THE_NAME=:val"; * try{ * session.executeSql("delete from table where id=?", id);//执行SQL语句 * session.commit(); //提交事务 * }catch(SQLException e){ * session.rollback(); //回滚事务 * } * </tt> * </pre> * * @return 事务处理对象,继承了Session中的方法。 * @see Session * @see Transaction */ public Transaction startTransaction() { return new TransactionImpl(this, null, false); } /** * @param timeout * 事务超时时间,单位秒 * @param isolationLevel * 事务隔离级别 <li>TRANSACTION_READ_COMMITTED =1</li> <li> * TRANSACTION_READ_UNCOMMITTED = 2</li> <li> * TRANSACTION_REPEATABLE_READ = 4</li> <li> * TRANSACTION_SERIALIZABLE =8</li> <li>ISOLATION_DEFAULT = -1</li> * * @param readOnly * 是否为只读事务。部分数据库支持只读事务。可以针对只读进行优化。具体优化哪些特性取决于数据库。 * @return Transaction对象 */ public Transaction startTransaction(int timeout, int isolationLevel, boolean readOnly) { return new TransactionImpl(this, timeout, isolationLevel, readOnly, false); } /** * 使用Datasource 构造DbClient * * @param datasource * 数据源信息 如果datasource已经是一个连接池,那么不会再启动内嵌的连接池,否则会使用内建的连接池 */ public DbClient(DataSource datasource) { this(datasource, JefConfiguration.getInt(DbCfg.DB_CONNECTION_POOL, 3), JefConfiguration.getInt(DbCfg.DB_CONNECTION_POOL_MAX, 50), null); } /** * 使用DataSource构造DbClient * * @param datasource * 数据源信息 * @param max * 内建连接池的最大值,如果DataSource已经是一个连接池,那么内建连接池不会启动,此参数无效。 */ public DbClient(DataSource datasource, int min, int max, TransactionMode txType) { try { if (txType != null) this.txType = txType; if(datasource==null){ datasource=getDefaultDataSource(); } init(datasource, min,max); JefFacade.registeEmf(this, null); } catch (SQLException e) { throw new RuntimeException(e); } } /** * 构造,会使用jef.properties中配置的信息来连接数据库。 * @deprecated use new DbClientBuilder().build() to create a new DbClient. */ public DbClient() { this(getDefaultDataSource(), JefConfiguration.getInt(DbCfg.DB_CONNECTION_POOL, 3), JefConfiguration.getInt(DbCfg.DB_CONNECTION_POOL_MAX, 50), null); } /* * (non-Javadoc) * * @see jef.database.Session#createNamedQuery(java.lang.String, * java.lang.Class) */ @Override public <T> NativeQuery<T> createNamedQuery(String name, Class<T> resultWrapper) { if (namedQueries == null) initNQ(); NQEntry nc = namedQueries.get(name); if (nc == null) { throw new IllegalArgumentException("The query which named [" + name + "] was not found."); } return selectTarget(MetaHolder.getMappingSite(nc.getTag())).createNativeQuery(nc, resultWrapper); } /* * (non-Javadoc) * * @see jef.database.Session#createNamedQuery(java.lang.String, * jef.database.meta.ITableMetadata) */ @Override public <T> NativeQuery<T> createNamedQuery(String name, ITableMetadata resultMeta) { if (namedQueries == null) initNQ(); NQEntry nc = namedQueries.get(name); if (nc == null) { throw new IllegalArgumentException("The query which named [" + name + "] was not found."); } return selectTarget(MetaHolder.getMappingSite(nc.getTag())).createNativeQuery(nc, resultMeta); } /** * 检测一个命名查询是否存在 * @param name * @return */ public boolean hasNamedQuery(String name){ if (namedQueries == null) initNQ(); NQEntry nc = namedQueries.get(name); return nc!=null; } /** * 增加一个数据库操作监听器 操作监听器是可以为各种数据库操作编写事件的一个自定义的类。 * * @param lis */ public void addEventListener(DbOperatorListener lis) { DbOperatorListener old = getListener(); if (old == DefaultDbOperListener.getInstance()) { this.listener = lis; } else if (old instanceof DbOperatorListenerContainer) { ((DbOperatorListenerContainer) old).add(lis); } else { this.listener = new DbOperatorListenerContainer(old, lis); } } protected synchronized void initNQ() { namedQueries = new NamedQueryHolder(this); } @Override protected Cache getCache() { return golbalCache; } /** * {@inheritDoc} */ @Override protected DbOperatorListener getListener() { if (listener == null) { String clz = JefConfiguration.get(DbCfg.DB_OPERATOR_LISTENER); if (StringUtils.isNotEmpty(clz)) { try { listener = (DbOperatorListener) BeanUtils.newInstance(Class.forName(clz)); } catch (ClassNotFoundException e) { LogUtil.exception(e); } } if (listener == null) { listener = DefaultDbOperListener.getInstance(); } } return listener; } protected String getTransactionId(String key) { StringBuilder sb = new StringBuilder(); //2016/7/8 优化,Map hash查找仅发生一次。 ConnectInfo info=connPool.getInfo(key); sb.append('[').append(info.profile.getName()).append(':').append(info.dbname).append('@').append(Thread.currentThread().getId()).append(']'); return sb.toString(); } @Override protected OperateTarget selectTarget(String dbKey) { if (connPool == null) { throw new IllegalAccessError("The database client was closed!"); } if (StringUtils.isEmpty(dbKey)) dbKey = null; return new OperateTarget(this, dbKey); } @Override public DbClient getNoTransactionSession() { return this; } /** * 得到指定表的所有分表 * * @param meta * 表元模型 * @return 从数据库扫描得到的分表 */ public PartitionResult[] getSubTableNames(ITableMetadata meta) { return getPartitionSupport().getSubTableNames(meta); } public boolean isOpen() { return connPool != null; } protected void finalize() throws Throwable { if (connPool != null) { LogUtil.show("Database will auto shut down at Java finalize thread. to avoid this message, you should manually close the DbClient."); close(); } super.finalize(); } public SequenceManager getSequenceManager() { return sequenceManager; } /* * 初始化 */ protected void init(DataSource ds,int min, int max) throws SQLException { DbUtils.tryAnalyzeInfo(ds, true);// 尝试解析并处理连接参数。 this.ds = ds; this.connPool = PoolService.getPool(ds,min, max, txType); Assert.notNull(connPool); LogUtil.info("Init DB Connection:" + connPool.getInfo(null)); afterPoolReady(); } /* * initlize:连接建立完成后执行初始化检查 */ private void afterPoolReady() throws SQLException { // 初始化处理器 DatabaseDialect profile = this.getProfile(null); this.preProcessor = new SqlProcessor.PrepareImpl(profile, this); this.selectp = SelectProcessor.get(profile, this); this.insertp = InsertProcessor.get(profile, this); this.updatep = UpdateProcessor.get(profile, this); this.deletep = DeleteProcessor.get(profile, this); this.sequenceManager = new SequenceManager(this); //设置全局缓存 if(ORMConfig.getInstance().getCacheLevel2()>0) { this.golbalCache=new CacheImpl(preProcessor, selectp, ORMConfig.getInstance().getCacheLevel2(),"GLOBAL"); }else { this.golbalCache=CacheDummy.getInstance(); } //设置分区加载器 this.pm = new PartitionMetadata(connPool); // 配置好的初始化选项 String str = JefConfiguration.get(DbCfg.DB_INIT_STATIC); if (StringUtils.isNotBlank(str)) { for (String clzName : StringUtils.split(str, ',')) { try { Class.forName(clzName); } catch (ClassNotFoundException e) { throw new RuntimeException("Class not found: " + e.getMessage()); } } } // Named Query初始化 String queryTable = JefConfiguration.get(DbCfg.DB_QUERY_TABLE_NAME); if (StringUtils.isNotEmpty(queryTable)) { MetaHolder.initMetadata(NamedQueryConfig.class, null, queryTable); try { refreshTable(MetaHolder.getMeta(NamedQueryConfig.class), null);// 创建表 } catch (SQLException e) { LogUtil.warn("Named Query Table:" + queryTable + " was not refreshed. Error:" + e.getMessage()); } } // 在每个数据库上都要执行的初始化任务 this.connPool.registeDbInitCallback(new C(this)); } /** * 回调对象 * * @author Administrator * */ private static class C implements Callback<String, SQLException> { private DbClient session; C(DbClient session) { this.session = session; } public void call(String key) throws SQLException { for (String tableName : JefConfiguration.get(DbCfg.DB_TABLES).split(",")) { try { tableName = tableName.trim(); if (tableName.length() > 0) { Class<?> c = Class.forName(tableName); Object o = c.newInstance(); if (o instanceof IQueryableEntity) { if (session.createTable((IQueryableEntity) o)) { LogUtil.show("JEF has created table " + tableName + " automaticlly."); } } } } catch (Exception e) { LogUtil.exception(e); } } DbMetaData meta = session.getMetaData(key); boolean showVersion = JefConfiguration.getBoolean(DbCfg.DB_SHOW_JDBC_VERSION, true); if (showVersion) { LogUtil.show(meta.getDbVersion()); } } } /** * Get the database metadata handler of assigned datasource. if there's only * one datasource, input null is fine. * * @param dbkey * the name of datasource. input null to access the metadata of * default datasource. * @return * @throws SQLException */ public DbMetaData getMetaData(String dbkey){ return connPool.getMetadata(dbkey); } /** * Check if the table exists. * <p> * * If there are multiple datasources , use {@link #getMetaData(String)} then * call {@link DbMetaData#getExistTable(String)} to check. * * @param tableName * 支持Schema重定向 * @return * @throws SQLException * * */ public boolean existTable(String tableName) throws SQLException { Assert.notNull(tableName); tableName = MetaHolder.toSchemaAdjustedName(tableName); return getMetaData(null).existTable(tableName); } /** * 给定一个对象,计算这个对象所对应的数据库表并判断这些表是否存在。(在分表分库条件下,一个查询对象可以对应多张表) * * @param obj * 检测的查询对象 * @return 不存在的表名称 * @throws SQLException */ public Collection<String> existTable(IQueryableEntity obj) throws SQLException { PartitionResult[] result = DbUtils.toTableNames(obj, null, null, getPartitionSupport()); List<String> s = new ArrayList<String>(); for (PartitionResult pr : result) { DbMetaData meta = getMetaData(pr.getDatabase()); if (meta != null) { for (String table : pr.getTables()) { if (!meta.existTable(table)) { s.add(table); } } } } return s; } /** * 删除表 * * @param meta * 要删除的表 * @return 删除的表数量 * @throws SQLException */ public int dropTable(ITableMetadata meta) throws SQLException { PartitionResult[] pr = DbUtils.toTableNames(meta, getPartitionSupport(), 4); return dropTable0(pr, meta); } /** * 删除表 * * @param cls * 要删除的表(对应的class)。如果是分库分表的class,会对应多张表 * @return 删除的表数量 * @throws SQLException */ public int dropTable(Class<?>... cls) throws SQLException { int count = 0; for (Class<?> c : cls) { ITableMetadata meta = MetaHolder.getMeta(c); count += dropTable(meta); } return count; } /** * 删除表 * * @param obj * 要删除的表对应的查询对象 * @return 删除的表数量 * @throws SQLException */ public int dropTable(IQueryableEntity obj) throws SQLException { PartitionResult[] pr = DbUtils.toTableNames(obj, null, obj.getQuery(), getPartitionSupport()); ITableMetadata meta = MetaHolder.getMeta(obj); return dropTable0(pr, meta); } /** * 删除表 (支持schema重定向) * * @param tablename * 表名 * @param seqNames * 要关联删除的Sequence名称 * @return * @throws SQLException */ public int dropTable(String tablename, String... seqNames) throws SQLException { tablename = MetaHolder.toSchemaAdjustedName(tablename); if (seqNames != null) { for (int i = 0; i < seqNames.length; i++) { seqNames[i] = MetaHolder.toSchemaAdjustedName(seqNames[i]); } } PartitionResult pr = new PartitionResult(tablename); return dropTable0(new PartitionResult[] { pr }, null, seqNames); } /** * 删除指定表上的全部约束(主外键) * * @param tablename * 支持schema重定向 * @throws SQLException */ public void dropAllConstraint(String tablename) throws SQLException { getMetaData(null).dropAllConstraint(tablename); } /** * 执行 truncate table XXXX 命令,快速清光表的数据 * * @param meta * 表名 * @param route * 路由结果。该表对应的所有实例。 * */ public int truncate(ITableMetadata meta, PartitionResult[] route) throws SQLException { List<SQLException> errors = new ArrayList<SQLException>(); int total = 0; for (PartitionResult site : route) { DbMetaData dbmeta = connPool.getMetadata(site.getDatabase()); try { dbmeta.truncate(meta, site.getTablesEscaped(dbmeta.getProfile())); total += site.getTables().size(); } catch (SQLException e) { errors.add(e); } } if (!errors.isEmpty()) { throw DbUtils.wrapExceptions(errors); } return total; } /** * 执行 truncate table XXXX 命令,快速清光一张表的数据 * * @param meta * 表结构元数据 * @throws SQLException */ public void truncate(ITableMetadata meta) throws SQLException { PartitionResult[] route; route = DbUtils.toTableNames(meta, getPartitionSupport(), 4); truncate(meta, route); } /** * 执行 truncate table XXXX 命令,快速清光一张表的数据 * * @param meta * 表对应的类 */ public void truncate(Class<? extends IQueryableEntity> meta) throws SQLException { truncate(MetaHolder.getMeta(meta)); } /** * 根据传入的对象和指定的表名创建表,这个方法只会创建一张表 * * @param meta * 表结构元数据 * @param tablename * 表名,支持Schema重定向. * @param dbName * 数据源名 * @return true表示创建成功 * @throws SQLException */ public boolean createTable(ITableMetadata meta, String tablename, String dbName) throws SQLException { tablename = MetaHolder.toSchemaAdjustedName(tablename); dbName = MetaHolder.getMappingSite(dbName); List<SQLException> ex = new ArrayList<SQLException>(); boolean ok = createTable0(meta, ex, new PartitionResult(tablename).setDatabase(dbName)) > 0; if (!ex.isEmpty()) { throw DbUtils.wrapExceptions(ex); } return ok; } /** * 根据传入的对象和指定的表名创建表,这个方法只会创建一张表 * * @param clz * 表实体类 * @param tablename * 表名,支持Schema重定向. * @param dbName * 数据源名 * @return true表示创建成功 * @throws SQLException */ public boolean createTable(Class<? extends IQueryableEntity> clz, String tablename, String dbName) throws SQLException { return createTable(MetaHolder.getMeta(clz), tablename, dbName); } /** * 根据一个对象来创建表。如果是分库分表对象,会创建这个对象对应的表。 * * @param obj * 分库对象 * @return 创建成功返回true,表已经存在无需创建返回false * @throws SQLException */ public boolean createTable(IQueryableEntity obj) throws SQLException { AbstractMetadata meta = MetaHolder.getMeta(obj); PartitionResult[] result = DbUtils.partitionUtil.toTableNames(meta, obj, obj.getQuery(), getPartitionSupport(), false); if (ORMConfig.getInstance().isDebugMode()) { LogUtil.show("Partitions:" + Arrays.toString(result)); } List<SQLException> ex = new ArrayList<SQLException>(); boolean ok = createTable0(meta, ex, result) > 0; if (!ex.isEmpty()) { throw DbUtils.wrapExceptions(ex); } return ok; } /** * 根据传入的类创建表,如果传入的类是分库分表对象,会创建这个对象所有的表。 * * @param cs * 要创建的表对应的class * @return 创建成功的表总数。 * @throws SQLException */ public int createTable(Class<?>... cs) throws SQLException { List<SQLException> ex = new ArrayList<SQLException>(); int n = 0; for (Class<?> c : cs) { ITableMetadata meta = MetaHolder.getMeta(c); PartitionResult[] result = DbUtils.toTableNames(meta, getPartitionSupport(), 2); n += createTable0(meta, ex, result); } if (!ex.isEmpty()) { throw DbUtils.wrapExceptions(ex); } return n; } /** * 根据传入的metadata创建表,如果传入的类是分库分表对象,会创建这个对象所有的表。 * * @param metas * 要创建的表的元数据 * @return 创建成功的表的总数 * @throws SQLException */ public int createTable(ITableMetadata... metas) throws SQLException { int n = 0; List<SQLException> errors = new ArrayList<SQLException>(); for (ITableMetadata meta : metas) { PartitionResult[] result = DbUtils.toTableNames(meta, getPartitionSupport(), 2); n += createTable0(meta, errors, result); } if (!errors.isEmpty()) { throw DbUtils.wrapExceptions(errors); } return n; } /** * 检查并修改数据库中的表,使其和传入的实体模型保持一致。 * * @param clz * 要更新的表对应的类 * @throws SQLException */ public void refreshTable(Class<?> clz) throws SQLException { refreshTable(MetaHolder.getMeta(clz), null); } /** * 检查并修改数据库中的表,使其和传入的实体模型保持一致。 * * @param meta * 要更新的表的元数据 * @param listener * 事件监听器,可以监听刷新过程的事件 * @throws SQLException * @see MetadataEventListener */ public void refreshTable(ITableMetadata meta, MetadataEventListener event) throws SQLException { Assert.notNull(meta, "The table definition which your want to resresh must not null."); ensureOpen(); PartitionResult[] results = DbUtils.toTableNames(meta, this.getPartitionSupport(), 4); for (PartitionResult result : results) { DbMetaData dbmeta = getPool().getMetadata(result.getDatabase()); for (String table : result.getTables()) { if (event == null || event.beforeTableRefresh(meta, table)) { dbmeta.refreshTable(meta, table, event); } } } } /** * 检查并修改数据库中的表,使其和传入的实体模型保持一致。 * * @param clz * 要更新的表对应的类 * @param listener * 事件监听器,可以监听刷新过程的事件 * @throws SQLException */ public void refreshTable(Class<?> clz, MetadataEventListener listener) throws SQLException { refreshTable(MetaHolder.getMeta(clz), listener); } public void close() { } /* * (non-Javadoc) * * @see jef.database.Session#getProfile(java.lang.String) */ public DatabaseDialect getProfile(String key) { ensureOpen(); return connPool.getProfile(key); } @Override IUserManagedPool getPool() { return connPool; } @Override public Collection<String> getAllDatasourceNames() { ensureOpen(); return connPool.getAllDatasourceNames(); } /** * 是否为路由场合下使用 * * @return true if the datasource is routing datasource */ public boolean isRoutingDataSource() { return connPool.isRouting(); } /** * 是否启用了EF-ORM的内部连接池 * * @return true if the inner pool is enabled. */ public boolean isInnerPoolEnabled() { return !connPool.isDummy(); } /** * 获得内部连接池的统计信息 * * @return */ public String getInnerPoolStatics() { ensureOpen(); if (connPool.isDummy()) { return "InnerPool is Disabled."; } if (connPool.isRouting()) { Map<String, IPool<Connection>> pools = ((RoutingManagedConnectionPool) connPool).getCachedPools(); StringBuilder result = new StringBuilder(); for (Entry<String, IPool<Connection>> entry : pools.entrySet()) { result.append('[').append(entry.getKey()).append(']'); PoolStatus p = entry.getValue().getStatus(); result.append(p.toString()); result.append("\n"); } return result.toString(); } else { return connPool.getStatus().toString(); } } /** * 强制进行命名查询的更新检查 */ public void checkNamedQueryUpdate() { if (namedQueries == null) { initNQ(); } else { namedQueries.checkUpdate(null); } } protected IConnection getConnection() throws SQLException { ensureOpen(); IConnection conn = connPool.poll(); if (!conn.getAutoCommit()) { conn.setAutoCommit(true); } return conn; } protected void releaseConnection(IConnection conn) { conn.close(); } protected String getDbName(String dbKey) { return connPool.getInfo(dbKey).getDbname(); } private int createTable0(ITableMetadata meta, List<SQLException> errors, PartitionResult... route) throws SQLException { int total = 0; for (PartitionResult site : route) { DbMetaData dbmeta = connPool.getMetadata(site.getDatabase()); for (String tablename : site.getTables()) { try { if (dbmeta.createTable(meta, tablename)) total++; } catch (SQLException e) { errors.add(e); } } } if(meta!=null) { for(Reference ref:meta.getRefFieldsByRef().keySet()) { if(ref.getHint()!=null && ref.getHint().getRelationTable()!=null) { try { createTable(ref.getHint().getRelationTable()); } catch (SQLException e) { errors.add(e); } } } } for (Exception e : errors) { LogUtil.exception(e); } if (!errors.isEmpty()) { throw DbUtils.wrapExceptions(errors); } return total; } private int dropTable0(PartitionResult[] prs, ITableMetadata meta, String... otherseq) throws SQLException { List<SQLException> errors = new ArrayList<SQLException>(); int count = 0; for (PartitionResult pr : prs) { DbMetaData metaData = getMetaData(pr.getDatabase()); try { for (String table : pr.getTables()) { metaData.dropTable(table); count++; } if (meta != null) { for (AutoIncrementMapping mapping : meta.getAutoincrementDef()) { sequenceManager.dropSequence(mapping, this.selectTarget(pr.getDatabase())); } } for (String s : otherseq) { metaData.dropSequence(s); } } catch (SQLException e) { errors.add(e); } if (meta != null) metaData.clearTableMetadataCache(meta); } if(meta!=null) { for(Reference ref:meta.getRefFieldsByRef().keySet()) { if(ref.getHint()!=null && ref.getHint().getRelationTable()!=null) { try { dropTable(ref.getHint().getRelationTable()); } catch (SQLException e) { errors.add(e); } } } } for (Exception e : errors) { LogUtil.exception(e); } if (!errors.isEmpty()) { throw DbUtils.wrapExceptions(errors); } return count; } private void ensureOpen() { if (connPool == null) { throw new IllegalStateException("The database client was closed."); } } public TransactionMode getTxType() { return txType; } public DataSource getDataSource() { return ds; } /** * 获取缺省的DataSource配置 * * @return */ private static SimpleDataSource getDefaultDataSource() { String dbPath = JefConfiguration.get(DbCfg.DB_FILEPATH, ""); String dbType = JefConfiguration.get(DbCfg.DB_TYPE, "derby"); int port = JefConfiguration.getInt(DbCfg.DB_PORT, 0); String host = JefConfiguration.get(DbCfg.DB_HOST, ""); String dbName = JefConfiguration.get(DbCfg.DB_NAME); DatabaseDialect features = AbstractDialect.getProfile(dbType); if (features == null) { throw new RuntimeException("The DBMS: " + dbType + "not support yet."); } dbPath = dbPath.replace('\\', '/'); if (dbPath.length() > 0 && !dbPath.endsWith("/")) { dbPath += "/"; } String url = features.generateUrl(host, port, dbPath + dbName); String user = JefConfiguration.get(DbCfg.DB_USER); String password = JefConfiguration.get(DbCfg.DB_PASSWORD); return DbUtils.createSimpleDataSource(url, user, password); } private PartitionMetadata pm; @Override PartitionSupport getPartitionSupport() { return pm; } public void printPool() { System.out.println(getPool().getStatus()); } /* * 从配置中读取命名查询的配置位置(文件) */ private String namedQueryFilename = JefConfiguration.get(DbCfg.NAMED_QUERY_RESOURCE_NAME, "named-queries.xml"); /* * 从配置中读取命名查询的配置位置(数据库表) */ private String namedQueryTablename = JefConfiguration.get(DbCfg.DB_QUERY_TABLE_NAME); /** * 设置命名查询文件的名称 * * @param namedQueryFilename */ public void setNamedQueryFilename(String namedQueryFilename) { if (namedQueries != null) { throw new IllegalStateException("must set before named-query init"); } this.namedQueryFilename = namedQueryFilename; } /** * 设置命名查询表的名称 * * @param namedQueryTablename */ public void setNamedQueryTablename(String namedQueryTablename) { if (namedQueries != null) { throw new IllegalStateException("must set before named-query init"); } this.namedQueryTablename = namedQueryTablename; } String getNamedQueryFile() { return namedQueryFilename; } String getNamedQueryTable() { return namedQueryTablename; } boolean isJpaTx() { return false; } @Override public void shutdown() { try { this.getListener().onDbClientClose(); } catch (Exception e) { LogUtil.exception(e); } this.sequenceManager.close(); try { connPool.close(); JefFacade.unregisteEmf((DbClient) this); } catch (SQLException e) { throw DbUtils.toRuntimeException(e); } finally { connPool = null; } } @Override public Session getSession() { return this; } public void flush() { getCache().evictAll(); } }