咱們公司開發的產品須要支持oracle和mssql兩種數據庫:a.使用ibatis的產品中,通常預先編寫兩份xml文件內容爲使用不一樣數據庫特性的sql,而後使用ant命令build成兩份;b.使用jdbcTemplate等類在代碼中嵌入sql的產品中,若是使用一堆if..else會讓代碼顯得臃腫,個人作法是面向接口編程,使用java多態的特性,引入工具類,簡化代碼。下面介紹第二種場景的解決辦法。java
第一步,創建兩份properties文件,寫入鍵值對標記當前數據庫類型,而後交由ant工具build,如/WEB-INF/classes/common.properties,寫入dbtype=oracle或dbtype=mssql。sql
第二步,建立屬性文件讀取bean,並在Spring配置文件中引入該bean。數據庫
a.屬性文件讀取bean:編程
public class CustomizedPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer { private static Map ctxPropertiesMap; protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) throws BeansException { super.processProperties(beanFactoryToProcess, props); ctxPropertiesMap = new HashMap(); for (Iterator iterator = props.keySet().iterator(); iterator.hasNext();) { String keyStr = (String) iterator.next(); String value = props.getProperty(keyStr); ctxPropertiesMap.put(keyStr, value); } } public static Object getContextProperty(String name) { return ctxPropertiesMap.get(name); } }
b.Spring配置:oracle
<bean id="propertyConfigurer" class="test.CustomizedPropertyPlaceholderConfigurer"> <property name="ignoreResourceNotFound" value="true" /> <property name="locations"> <list> <value>/WEB-INF/classes/common.properties</value> </list> </property> </bean>
第二步,建立數據庫特性語法轉換接口和oracle、mssql實現類。函數
a.接口類:工具
public interface ConvertTo { public String getDate(); /** * 日期轉換爲字符串(格式:2013-05-16 10:57:49) * @param dateColumn * @return */ public String getFormatDatetime(String dateColumn); /** * 替換空字段爲指定字符 * @param column * @param replaceValue * @return */ public String getIsNULL(String column,String replaceValue); /** * 判斷子串是否存在 * @param sourceString * @param targetString * @return */ public String getInstr(String sourceString, String targetString); /** * 取前n條記錄 * @param sql * @param columnCount * @return */ public String getFirstServeralColumns(String sql, int columnCount); public String getFunction(String sql); public String getStrLink(); public String getFromDual(); }
b.oracle實現類:ui
public class ConvertToOracle implements ConvertTo { public String toDate(String dateText) { return "to_date( " + dateText + " , 'YYYY-MM-DD')"; } public String getFormatDatetime(String dateColumn) { return " to_char( "+dateColumn+" , 'YYYY-MM-DD hh:mm:ss')"; } /** *獲取當前日期的sql串 * @return */ public String getDate(){ return " sysDate "; } public String getIsNULL(String column,String replaceValue) { return " NVL(" + column + "," + replaceValue + ") "; } /** * 判斷子串是否存在 */ public String getInstr(String sourceString, String targetString) { return " INSTR("+sourceString+","+targetString+")>0 "; } /** * 取前n條記錄 * @param sql * @param columnCount * @return */ public String getFirstServeralColumns(String sql, int columnCount) { if(StringUtils.isBlank(sql) && columnCount<0) { return null; } return " SELECT * FROM ("+sql+") VIVID WHERE ROWNUM<="+columnCount +" "; } /** * 返回函數 */ public String getFunction(String sql) { if(StringUtils.isBlank(sql)) { return null; } return " TABLE("+sql+") "; } public String getStrLink() { return " || "; } public String getFromDual() { return " from dual "; } }
c.mssql實現類:code
public class ConvertToSQL implements ConvertTo { public String getFormatDatetime(String dateColumn) { return " CONVERT(varchar(100), "+dateColumn+", 120)"; } /** * 獲取當前日期的sql串 * * @return */ public String getDate() { return " getDate() "; } public String getIsNULL(String column, String replaceValue) { return " isNull(" + column + "," + replaceValue + ") "; } /** * 判斷子串是否存在 */ public String getInstr(String sourceString, String targetString) { return " CHARINDEX("+targetString+","+sourceString+")>0 "; } /** * 取前n條記錄 * @param sql * @param columnCount * @return */ public String getFirstServeralColumns(String sql, int columnCount) { if(StringUtils.isBlank(sql) && columnCount<0) { return null; } return " SELECT TOP "+columnCount+" * FROM ("+sql+") VIVID "; } /** * 返回函數 */ public String getFunction(String sql) { if(StringUtils.isBlank(sql)) { return null; } return sql; } public String getStrLink() { return " + "; } public String getFromDual() { return ""; } }
第三步,建立接口調用輔助類。orm
<!-- lang: java --> public class ConvertHelper { private static Map convertToMap; private ConvertHelper() { } private static synchronized void syncInit() { if(convertToMap==null) { convertToMap = new HashMap(); convertToMap.put("oracle", new ConvertToOracle()); convertToMap.put("mssql", new ConvertToSQL()); } } private static Map getConvertToMap() { if(convertToMap==null) { syncInit(); } return convertToMap; } public static ConvertTo getConvertTo(){ String dbtype = PropertyPlaceholderConfigurer.getProperty("dbtype"); return (ConvertTo)getConvertToMap().get(dbtype); } }
第四步,如何使用。
業務代碼中獲取ConvertTo對象,直接調用相關方法。如獲取前5條用戶數據:
ConvertTo convertTo = ConvertHelper.getConvertTo();
String mSql = getFirstServeralColumns('SELECT * FROM TEST_USERS',10);