如何開發支持oracle和mssql雙版本數據庫的產品

咱們公司開發的產品須要支持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);

相關文章
相關標籤/搜索