osgi實戰項目(osmp)一步一步玩轉osgi之jdbc(6)

    已經有很長一段時間沒有更新了,年末了比較忙,最近不少新加入的朋友在問jdbc這段,今天抽點空講一下osmp-jdbc的封裝。java

 

    osmp的jdbc相比其它框架的來說主要有如下幾點不一樣。mysql

 

  • 基於druid的多數據源管理
  • 支持多種類型的數據庫,目前支持mysql,oracle,mssql。
  • 提供數據源動態建立和消毀
  • 提供基於動態sql管理和解析
  • 提供相似於mybaties的springTemplate的dao封裝

   最開始的時候個人想法很簡單,給我一個數據庫連接,給我一個sql語句,我就能給你想要的數據,結合osgi的動態性來實現。spring

 

先從動態數據源來講,從resources/META-INF/spring/jdbc-context.xml 配置文件當中咱們能夠看到,spring配置文件加載後,咱們實例化了 com.osmp.jdbc.service.SqlStatementManager,   com.osmp.jdbc.service.SqlStatementMonitor,   com.osmp.jdbc.service.DataSourceManager,   com.osmp.jdbc.service.DataSourceMonitor這四個類,分別爲sql語句管理,sql語句監控,數據源管理,數據源監控。sql

 

DataSourceMonitor(數據源監控)實現spring 的 InitializingBean和 DisposableBean接口,實例化傳入了數據源配置目錄和數據源管理兩個參數,bean初始時經過傳入的數據源配置目錄獲取全部配置並解析後實例化DruidDataSource 添加到DataSourceManager中。 同時啓了一個線程監控數據源配置目錄,若是一旦有新增的配置後解析並添加到數據源管理裏。代碼以下數據庫

 

 

@Override
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(dataSourceDir, "dataSource文件目錄不能爲空...");
        Assert.notNull(dataSourceManager, "dataSourceManager未初始化...");
        final File resFile = new File(dataSourceDir);
        Assert.isTrue(resFile.exists(), "dataSource文件目錄不存在...");
        filepath2datasourceNameMap.clear();
        for(File file : resFile.listFiles()){
            addDataSource(file.getName());
        }
        new Thread(){
            public void run(){
                try {
                    monitor(resFile);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

 

 

    文件監控使用的是jdk1.7的  WatchService 服務,這裏不做詳細介紹 ,有興趣的同窗本身百度吧。oracle

 

 

private void monitor(File file) throws Exception{
        watchService = FileSystems.getDefault().newWatchService();
        file.toPath().register(watchService, StandardWatchEventKinds.ENTRY_CREATE,StandardWatchEventKinds.ENTRY_DELETE); 
        while(running){
            WatchKey watchKey = watchService.take();
            List<WatchEvent<?>> events = watchKey.pollEvents();
            
            if(events != null){
                for(WatchEvent<?> e : events){
                    //事件處理
                    final WatchEvent<Path> watchEventPath = (WatchEvent<Path>)e; 
                    final Path filename = watchEventPath.context(); 
                    
                    if(e.kind() == StandardWatchEventKinds.ENTRY_CREATE){
                        addDataSource(filename.toString());
                    }else if(e.kind() == StandardWatchEventKinds.ENTRY_DELETE){
                        removeDataSource(filename.toString());
                    }
                }
            }
            if(!watchKey.reset()){
                watchKey.cancel();
                logger.error("移除dataSource文件目錄監控服務");
                break;
            }
        }
        running = false;
        watchService.close();
    }

 

 

只要數據源配置目錄一旦有文件添加、刪除、修改事件發生,都會進行相應的處理,新增、刪除、修改數據源,這也是動態數據源的核心部分,我相信同窗們看了後,在之後的項目當中也可使用 WatchService 服務實現更多動態功能吧。切記WatchService 服務是 JDK1.7之後才提供的功能。app

 

有了數據源後,咱們更進一步的將數據源與springTemplate結合,經過JdbcTemplateManager來管理模板,經過 JdbcTemplateManager 的 addDataSource方法,根據數據庫類型實例化不一樣數據庫的模板並添加到JdbcTemplateManager裏。框架

 

com.osmp.jdbc.service.JdbcTemplateManageride

 

//添加數據源信息
    public void addDataSource(DataSource ds,String catalog,DBType dbType){
        if(ds == null || catalog == null || dbType == null) return;
        BaseTemplate jdbcTemplate = null;
        
        if(dbType.equals(DBType.SQLSERVER)){
            jdbcTemplate = new MSSQLTemplate();
        }else if(dbType.equals(DBType.MYSQL)){
            jdbcTemplate = new MysqlTemplate();
        }else{
            jdbcTemplate = new OracleTemplate();
        }
        jdbcTemplate.setOwnJdbcTemplate(new NamedParameterJdbcTemplate(ds));
        jdbcTemplate.setTransactionManager(new DataSourceTransactionManager(ds));
        //dsTransactionManager.setGlobalRollbackOnParticipationFailure(false); //指定主事務決定回滾
        
        templates.put(catalog.toUpperCase(), jdbcTemplate);
        
    }

 

com.osmp.jdbc.support.JdbcTemplate 封裝了大量的C,R,U,D操做,方便業務開發直接調用。ui

 

如今咱們只須要一個數據源的標識加一句sql,咱們就能夠執行C,R,U,D操做了。

 

 

上面咱們介紹了動態數據源這部分,下面咱們該聊一聊動態sql了。我大概記得當時我是想直接在osgi環境下集成mybaties來着,好像研究了兩週最後我放棄了,基於mybaties的開發習慣,本身寫了一套相似於東東,有點兒重複造輪子吧。

 

其實實現也很簡單:

 

sql配置文件 + 一個sql配置文件解析器 + 一個RowMapper實現類 

 

首先咱們定義了一個dtd文件用以限定sql 配置文件。

 

 

 

 

咱們經過動態數據的方式,SqlStatementMonitor監聽一個目錄做爲sql腳本xml的目錄。當有sql配置腳本xml添加的時候就解析xml文件並保存到SqlStatmentManager裏。

 

一旦有新的sql配置xml被添加後,就會進入SqlStatementMonitor.SqlUpdateTask.run() 方法被解析後加載到SqlStatementManager 裏。

 

//sql文件更新任務
    private class SqlUpdateTask implements Runnable {
        private File file;
        private boolean isDelete;
        public SqlUpdateTask(File file,boolean isDelete){
            this.file = file;
            this.isDelete = isDelete;
        }
        public void run() {
            if(file == null) return;
            String filename = file.getAbsolutePath();
            if(!filename.endsWith(".xml")){
                return;
            }
            sqlStatementManager.removeSqls(filename);
            if(isDelete) return;
            sqlStatementManager.putSql(filename, SqlParserUtils.parse(file));
        }
    }

 

 

SQL配置是類mybaties的配置。最開始想直接mybaties的解析部分,看了一下很難,還不如本身寫了,因此基本上myabties支持的。osmp也基本支持,甚至支持更多的高級特性,好比include advanced等,有待同窗們本身發掘,當時你也能夠本身擴充。這部有興趣的同窗能夠重構,將數據源與sql解析剝離出來。

 

 osmp同時提供 JdbcDao封裝,只須要sql配置xml裏的 id +  數據源名稱就能夠返回數據了。這也對應上面提到的需求,給一個sql + 數據源連接 我返給你結果。。。

 

隨便提一下。對於實體bean 和 ResultSet之間的轉換是經過定義 Column註解來進行的。獲取數據的時候 須要傳入一個 實體.class 經過反射解析@Column 從 ResultSet裏獲取數據 詳見 com.osmp.jdbc.define.tool.ToolsRowMapper

 

 最後看一下 sql xml的定義例子

 

 

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<!DOCTYPE sqls SYSTEM "osmp_sql.dtd">
<sqls>

	<select id="demo.queryuser">
		select * from demo_user 
		<where>
			<if test="name not empty">
				  and name=:name
			</if>
			<if test="age not empty">
				  and age=:age
			</if>
		</where>
	</select>
	
    <insert id="demo.adduser">
        insert into demo_user(id,name,age,remark) values(:id,:name,:age,:remark)  
    </insert>
    
    <delete id="demo.deluser">
		delete demo_user where id=:id
    </delete>
	
   <update id="demo.upuser">
	update demo_user set
        <if test="name not empty">
            name = :name
        </if>
        <if test="age not empty">
            name = :age
        </if>
        <if test="remark not empty">
            remark = :remark
        </if>
        <where>
        	id = :id
        </where>
    </update>
	
    <select id="demo.choose.when">
        select x,y,z from xxx WITH ( NOLOCK )
		where x in 
		(
			select x,y,z from yyy with(nolock)
			where ISNULL(x, '') != ''
			<choose>
				<when test="acctype == 0"><![CDATA[ and x=:x ]]></when>
				<when test="acctype == 1">and y=:y</when>
			</choose>
		)
    </select>
</sqls>
 

 

sql更多高級動態特性還有待朋友們本身去發掘,咱們開發的時候只須要將 此sql的配置xml和 數據源的properties配置 分別放到 ${servicemix_home}/etc/sqls 和 ${servicemix_home}/etc/datasources 目錄下,就會被動態解析保存和動態建立數據源。

 

最後一步,咱們將JdbcFinderManager發佈爲一個osgi的服務供其它的bundle調用。

 

resource/META-INF/spring/jdbc-context.xml

<osgi:service interface="com.osmp.jdbc.support.JdbcFinderManager"
		ref="osmp.JdbcFinderManager">
</osgi:service>

 

 

接下來咱們只須要寫一個簡單的demo調用他們就好了。

 

下一講咱們實戰講解怎麼demo開發一個用戶的增刪改查。

相關文章
相關標籤/搜索