Java tutorial
/* * 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.io.File; import java.sql.SQLException; import java.util.Map; import javax.sql.DataSource; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.easyframe.enterprise.spring.TransactionMode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import jef.codegen.EntityEnhancer; import jef.common.log.LogUtil; import jef.database.datasource.MapDataSourceLookup; import jef.database.datasource.RoutingDataSource; import jef.database.datasource.SimpleDataSource; import jef.database.dialect.AbstractDialect; import jef.database.dialect.DatabaseDialect; import jef.database.jpa.JefEntityManagerFactory; import jef.database.meta.MetaHolder; import jef.database.support.DbInitHandler; import jef.database.support.QuerableEntityScanner; import jef.tools.JefConfiguration; /** * ??DbClient * * */ public class DbClientBuilder { private Logger log = LoggerFactory.getLogger(DbClientBuilder.class); /** * ??? Spring????? * * <pre> * <code> * <property name="dataSources"> * <map> * <entry key="dsname1" value-ref="ds1" /> * <entry key="dsname2" value-ref="ds2" /> * </map> * </property> * </code> * </pre> */ private Map<String, DataSource> dataSources; /** * ??? */ protected DataSource dataSource; /** * ??????? */ private String defaultDatasource; /** * */ private int maxPoolSize = JefConfiguration.getInt(DbCfg.DB_CONNECTION_POOL_MAX, 50); /** * ? */ private int minPoolSize = JefConfiguration.getInt(DbCfg.DB_CONNECTION_POOL, 3); /** * ?? */ private String namedQueryFile; /** * ?? */ private String namedQueryTable; /** * ? * * @see #setTransactionMode(String) */ private TransactionMode transactionMode; /** * ??????<br> * ??packagesToScan<br> * ??????"none" * * @deprecated */ private String enhancePackages = "none"; /** * ??,? <code><pre> * <list> * <value>org.easyframe.test</value> * <value>org.easyframe.entity</value> * </list> * </pre></code> */ private String[] packagesToScan; /** * ???? */ private boolean enhanceScanPackages = true; /** * ??? <code><pre> * <list> * <value>org.easyframe.testp.jta.Product</value> * <value>org.easyframe.testp.jta.Users</value> * </list> * </pre></code> */ private String[] annotatedClasses; /** * ????????? */ private String dynamicTables; /** * ??? */ private boolean registeNonMappingTableAsDynamic; /** * ?????? <br> * ? */ private boolean createTable = true; /** * ????? <br> * ? */ private boolean alterTable = true; /** * ?????? <br> * */ private boolean allowDropColumn; /** * ??? * * @see DbInitHandler */ private String dbInitHandler; /** * ???? * <p> * ?class?? <i>class-name</i>.txt?? * ????? */ private boolean initData; /** * ??? */ private boolean useDataInitTable = JefConfiguration.getBoolean(DbCfg.USE_DATAINIT_FLAG_TABLE, false);; /** * ??? */ private String initDataCharset = "UTF-8"; /** * ???? */ private String initDataExtension = JefConfiguration.get(DbCfg.INIT_DATA_EXTENSION, "txt"); /** * ?? */ private String initDataRoot = JefConfiguration.get(DbCfg.INIT_DATA_ROOT, "/"); /** * ? */ protected JefEntityManagerFactory instance; /** * */ public DbClientBuilder() { } /** * * * @param jdbcURL * @param user * @param password * @param maxPool */ public DbClientBuilder(String jdbcURL, String user, String password, int maxPool) { this.dataSource = DbUtils.createSimpleDataSource(jdbcURL, user, password); this.maxPoolSize = maxPool; } /** * ??? * * @param dbType * @param host * @param port * @param pathOrName * @param user * @param password * @return */ public DbClientBuilder(String dbType, String host, int port, String pathOrName, String user, String password) { DatabaseDialect profile = AbstractDialect.getDialect(dbType); if (profile == null) { throw new IllegalArgumentException("The DBMS:[" + dbType + "] is not supported yet."); } String dbURL = profile.generateUrl(host, port, pathOrName); this.dataSource = DbUtils.createSimpleDataSource(dbURL, user, password); } /** * ? * * @param dbName * ??? * @param user * * @param pass * ? * @return * @throws SQLException */ public DbClientBuilder(String dbType, File dbFolder, String user, String password) { int port = JefConfiguration.getInt(DbCfg.DB_PORT, 0); String host = JefConfiguration.get(DbCfg.DB_HOST, ""); DatabaseDialect profile = AbstractDialect.getDialect(dbType); if (profile == null) { throw new IllegalArgumentException("The DBMS:[" + dbType + "] is not supported yet."); } String dbURL = profile.generateUrl(host, port, dbFolder.getAbsolutePath()); this.dataSource = DbUtils.createSimpleDataSource(dbURL, user, password); } /** * ?JDBC??? * * @param jdbcUrl * @param user * @param password * @throws SQLException */ public DbClientBuilder(String jdbcUrl, String user, String password) { this.setDataSource(DbUtils.createSimpleDataSource(jdbcUrl, user, password)); } /** * ?DbClient * * @return DbClient * @see DbClient */ public DbClient build() { if (instance == null) { instance = buildSessionFactory(); } return instance.getDefault(); } /** * ?? * * @return ? * @see TransactionMode */ public String getTransactionMode() { return transactionMode == null ? null : transactionMode.name(); } /** * ???? * <ul> * <li><strong>JPA</strong></li><br> * JPA??Spring * {@linkplain org.springframework.orm.jpa.JpaTransactionManager * JpaTransactionManager}, ef-orm?? * <li><strong>JTA</strong></li><br> * JTA??JTA??????JMS??<br> * ??atomikosJTA? Spring * {@linkplain org.springframework.transaction.jta.JtaTransactionManager * JtaTransactionManager}<br> * ???? * <li><strong>JDBC</strong></li><br> * JDBC?Hibernate?HibernateHibernate * JdbcTemplate? ?DataSourceJDBC Spring * {@linkplain org.springframework.orm.hibernate3.HibernateTransactionManager * HibernateTransactionManager} * {@linkplain org.springframework.jdbc.datasource.DataSourceTransactionManager * DataSourceTransactionManager} * Hibernate/Ibatis/MyBatis/JdbcTemplate? * </ul> * {@code JPA} * * @param txType * ???JPA?JTA?JDBC * * @see TransactionMode */ public DbClientBuilder setTransactionMode(TransactionMode txType) { this.transactionMode = txType; return this; } /** * 0?? * * @param maxConnection * @return */ public DbClientBuilder setMaxPoolSize(int maxConnection) { this.maxPoolSize = maxConnection; return this; } public DataSource getDataSource() { return dataSource; } /** * ?? * * @param dataSource * ?? */ public DbClientBuilder setDataSource(DataSource dataSource) { this.dataSource = dataSource; return this; } /** * ?? * * @param url * @param user * @param password * @return */ public DbClientBuilder setDataSource(String url, String user, String password) { this.dataSource = new SimpleDataSource(url, user, password); return this; } /** * ??? * * @return ???? */ public DbClientBuilder setPackagesToScan(String[] scanPackages) { this.packagesToScan = scanPackages; return this; } /** * * @return */ public boolean isAlterTable() { return alterTable; } /** * ??????? * * @param alterTable * 'true' , EF-ORM will alter tables in database. */ public DbClientBuilder setAlterTable(boolean alterTable) { this.alterTable = alterTable; return this; } /** * ? * * @param debug * @return */ public DbClientBuilder setDebug(boolean debug) { ORMConfig.getInstance().setDebugMode(debug); return this; } /** * ?? * * @return */ public boolean isDebug() { return ORMConfig.getInstance().isDebugMode(); } /** * ? * * @return */ public boolean isCreateTable() { return createTable; } /** * ?????? * * @param createTable * true */ public DbClientBuilder setCreateTable(boolean createTable) { this.createTable = createTable; return this; } public boolean isAllowDropColumn() { return allowDropColumn; } /** * ???? * * @param dynamicTables * ??? */ public DbClientBuilder setDynamicTables(String dynamicTables) { this.dynamicTables = dynamicTables; return this; } public boolean isRegisteNonMappingTableAsDynamic() { return registeNonMappingTableAsDynamic; } public String[] getAnnotatedClasses() { return annotatedClasses; } /** * ??? * * <pre> * <code> * <list> * <value>org.easyframe.testp.jta.Product</value> * <value>org.easyframe.testp.jta.Users</value> * </list> * </code> * </pre> */ public DbClientBuilder setAnnotatedClasses(String[] annotatedClasses) { this.annotatedClasses = annotatedClasses; return this; } public String[] getPackagesToScan() { return packagesToScan; } public boolean isInitData() { return initData; } public DbClientBuilder setInitData(boolean initData) { this.initData = initData; return this; } public void setMinPoolSize(int minPoolSize) { this.minPoolSize = minPoolSize; } /** * ????schema? * * @param registeNonMappingTableAsDynamic */ public DbClientBuilder setRegisteNonMappingTableAsDynamic(boolean registeNonMappingTableAsDynamic) { this.registeNonMappingTableAsDynamic = registeNonMappingTableAsDynamic; return this; } public Map<String, DataSource> getDataSources() { return dataSources; } public String getDefaultDatasource() { return defaultDatasource; } /** * ??????? * * @param defaultDatasource * name of the datasource. */ public DbClientBuilder setDefaultDatasource(String defaultDatasource) { this.defaultDatasource = defaultDatasource; return this; } /** * ??? Spring????? * * <pre> * <code> * <property name="dataSources"> * <map> * <entry key="dsname1" value-ref="ds1" /> * <entry key="dsname2" value-ref="ds2" /> * </map> * </property> * </code> * </pre> */ public DbClientBuilder setDataSources(Map<String, DataSource> datasources) { this.dataSources = datasources; return this; } /** * ?????xml?classpath * * @param namedQueryFile * ???? */ public DbClientBuilder setNamedQueryFile(String namedQueryFile) { this.namedQueryFile = namedQueryFile; return this; } public String getNamedQueryTable() { return namedQueryTable; } /** * ????? * * @param namedQueryTable * ??? */ public DbClientBuilder setNamedQueryTable(String namedQueryTable) { this.namedQueryTable = namedQueryTable; return this; } /** * ???Alter??? * * @param allowDropColumn * true? */ public DbClientBuilder setAllowDropColumn(boolean allowDropColumn) { this.allowDropColumn = allowDropColumn; return this; } public String getEnhancePackages() { return enhancePackages; } /** * ? ?classjarclass * * @deprecated 1.12??instrument?????? * @param enhancePackages * ??? */ public DbClientBuilder setEnhancePackages(String enhancePackages) { this.enhancePackages = enhancePackages; return this; } public String getDynamicTables() { return dynamicTables; } public String getNamedQueryFile() { return namedQueryFile; } protected JefEntityManagerFactory buildSessionFactory() { if (instance != null) return instance; // try enahcen entity if theres 'enhancePackages'. if (enhancePackages != null) { if (!enhancePackages.equalsIgnoreCase("none")) { new EntityEnhancer().enhance(StringUtils.split(enhancePackages, ",")); } } if (enhanceScanPackages && ArrayUtils.isNotEmpty(this.packagesToScan)) { new EntityEnhancer().enhance(packagesToScan); } else if (enhanceScanPackages) { log.warn("EnhanceScanPackages flag was set to true. but property 'packagesToScan' was not assigned"); } JefEntityManagerFactory sf; // check data sources. if (dataSource == null && dataSources == null) { LogUtil.info("No datasource found. Using default datasource in jef.properties."); sf = new JefEntityManagerFactory(null, minPoolSize, maxPoolSize, transactionMode); } else if (dataSource != null) { sf = new JefEntityManagerFactory(dataSource, minPoolSize, maxPoolSize, transactionMode); } else { RoutingDataSource rs = new RoutingDataSource( new MapDataSourceLookup(dataSources).setDefaultKey(this.defaultDatasource)); sf = new JefEntityManagerFactory(rs, minPoolSize, maxPoolSize, transactionMode); } if (namedQueryFile != null) { sf.getDefault().setNamedQueryFilename(namedQueryFile); } if (namedQueryTable != null) { sf.getDefault().setNamedQueryTablename(namedQueryTable); } if (packagesToScan != null || annotatedClasses != null) { QuerableEntityScanner qe = new QuerableEntityScanner(); if (transactionMode == TransactionMode.JTA) { // JTADDL????JTA qe.setCheckSequence(false); } qe.setImplClasses(DataObject.class); qe.setAllowDropColumn(allowDropColumn); qe.setAlterTable(alterTable); qe.setCreateTable(createTable); qe.setInitData(this.initData); qe.setEntityManagerFactory(sf, this.useDataInitTable, this.initDataCharset, this.initDataExtension, this.initDataRoot); if (annotatedClasses != null) qe.registeEntity(annotatedClasses); if (packagesToScan != null) { String joined = StringUtils.join(packagesToScan, ','); qe.setPackageNames(joined); LogUtil.info("Starting scan easyframe entity from package: {}", joined); qe.doScan(); } qe.finish(); } if (dynamicTables != null) { DbClient client = sf.getDefault(); for (String s : StringUtils.split(dynamicTables, ",")) { String table = s.trim(); registe(client, table); } } if (registeNonMappingTableAsDynamic) { DbClient client = sf.getDefault(); try { for (String tableName : client.getMetaData(null).getTableNames()) { if (MetaHolder.lookup(null, tableName) != null) { registe(client, tableName); } } } catch (SQLException e) { LogUtil.exception(e); } } // ?? if (StringUtils.isNotBlank(this.dbInitHandler)) { for (String clzName : StringUtils.split(dbInitHandler, ',')) { try { Object initType = Class.forName(clzName).newInstance(); if (initType instanceof DbInitHandler) { ((DbInitHandler) initType).doDatabaseInit(sf.getDefault()); } } catch (ClassNotFoundException e) { LogUtil.error("InitClass load failure: class not found - " + e.getMessage()); } catch (InstantiationException e) { LogUtil.error("InitClass load failure - ", e); } catch (IllegalAccessException e) { LogUtil.error("InitClass load failure - ", e); } } } return sf; } private void registe(DbClient client, String table) { if (MetaHolder.getDynamicMeta(table) == null) { try { MetaHolder.initMetadata(client, table); LogUtil.show("DynamicEntity: [" + table + "] registed."); } catch (SQLException e) { LogUtil.exception(e); } } } public boolean isCacheDebug() { return ORMConfig.getInstance().isCacheDebug(); } public DbClientBuilder setCacheDebug(boolean cacheDebug) { ORMConfig.getInstance().setCacheDebug(cacheDebug); return this; } public boolean isCacheLevel1() { return ORMConfig.getInstance().isCacheLevel1(); } /** * * @param cache * @return this * @see DbCfg#CACHE_LEVEL_1 */ public DbClientBuilder setCacheLevel1(boolean cache) { ORMConfig.getInstance().setCacheLevel1(cache); return this; } /** * ?? ?????? * * @return * @see DbCfg#CACHE_GLOBAL_EXPIRE_TIME */ public int getGlobalCacheLiveTime() { return ORMConfig.getInstance().getCacheLevel2(); } /** * ?? ?????? * * @param second * @return this * @see DbCfg#CACHE_GLOBAL_EXPIRE_TIME */ public DbClientBuilder setGlobalCacheLiveTime(int second) { ORMConfig.getInstance().setCacheLevel2(second); return this; } public DbClientBuilder setUseSystemOut(boolean flag) { LogUtil.useSlf4j = !flag; return this; } /** * ????? ?? allow_data_initialize * do_init0???? 1??? * * @return whether use the datainit table or not. */ public boolean isUseDataInitTable() { return useDataInitTable; } /** * ????? ?? allow_data_initialize * do_init0???? 1??? * * @param useDataInitTable * whether use the datainit table or not. * @return this */ public DbClientBuilder setUseDataInitTable(boolean useDataInitTable) { this.useDataInitTable = useDataInitTable; return this; } public static DbClientBuilder newBuilder() { return new DbClientBuilder(); } public String getInitDataCharset() { return initDataCharset; } public DbClientBuilder setInitDataCharset(String initDataCharset) { this.initDataCharset = initDataCharset; return this; } public String getDbInitHandler() { return dbInitHandler; } public void setDbInitHandler(String dbInitHandler) { this.dbInitHandler = dbInitHandler; } public boolean isEnhanceScanPackages() { return enhanceScanPackages; } public DbClientBuilder setEnhanceScanPackages(boolean enhanceScanPackages) { this.enhanceScanPackages = enhanceScanPackages; return this; } public String getInitDataExtension() { return initDataExtension; } public DbClientBuilder setInitDataExtension(String initDataExtension) { this.initDataExtension = initDataExtension; return this; } public String getInitDataRoot() { return initDataRoot; } public DbClientBuilder setInitDataRoot(String initDataRoot) { this.initDataRoot = initDataRoot; return this; } }