DAL之基於mybatis的客戶端

引子:DAL作爲公司新架構獨立的數據訪問服務開始了研發。DALClient1.0暫基於mybatis3和spring3,實現了數據cache,sql攔截緩存,全局事務管理。後期將實現基於hibernate和OSGI的版本研發。

一、DALClient的配置

1.     web.xml

<!-- Spring監聽器  -->

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener

</listener-class>

</listener>

 

2.     applicationContext-datasource.xml

<!--將配置文件與數據源注入給DalSessionFactoryBean -->

    <bean id="dalSessionFactory" class="com.hc360.dal.DalSessionFactoryBean">

       <property name="configLocation"value="/WEB-INF/conf/mybatis/mybatis-config.xml"></property>

       <property name="dataSource"ref="dataSource" />

       <property name="mapperLocations">

           <list>

    <value>classpath:com/hc360/pay/hcpay/dalmapper/*-mapper.xml</value>

           </list>

       </property>

</bean>

<!-- Spring事務管理,管理service事務 -- >

<bean id="txManager"

       class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

       <property name="dataSource"ref="dataSource" />

    </bean>

 

    <!-- 事務配置-->

    <tx:annotation-driven transaction-manager="txManager"/>

    <tx:advice id="txAdvice" transaction-manager="txManager">

       <tx:attributes>

           <tx:method name="add*"propagation="REQUIRED" rollback-for="Exception"/>

           <tx:method name="update*"propagation="REQUIRED"

              rollback-for="Exception" />

           <tx:method name="del*"propagation="REQUIRED" rollback-for="Exception"/>

           <tx:method name="*"read-only="true" />

       </tx:attributes>

    </tx:advice>

<!-- 初始化Mapper-->

    <bean class="com.hc360.dal.mapper.MapperScannerConfigurer">

       <property name="basePackage"value="com.hc360.pay.hcpay.dal" />

    </bean> 

3.     *-mapper.xml

<mapper namespace="com.hc360.pay.hcpay.dal.AccountRemoteMapper">

        <!-- ORM PO -->

    <resultMap id="accountMap" type="account">

       <result column="id"property="id" />

       <result column="name"property="name" />

       <result column="pwd"property="pwd" />

       <result column="address"property="address" />

       <result column="zip"property="zip" />

       <result column="phone"property="phone" />

    </resultMap>

 

    <!-- sql -->

    <insert id="insert" parameterType="account">

       <selectKey keyProperty="id"resultType="long" order="BEFORE">

           select

           PAY_TRADE_ACCOUNT_SEQ.nextval as id from dual

       </selectKey>

    <![CDATA[

    insert into PAY_TRADE_ACCOUNT (id, name,pwd, address, zip, phone)

    values ( #{id}, #{name}, #{pwd},#{address}, #{zip},  #{phone})

    ]]>

    </insert>

   

    <!-- 使用緩存 -->

    <cache type="com.hc360.dal.cache.MapperCache"/>

</mapper>

 

二、DALClient初始化Mapper

1.     MapperScannerConfigurer.Scanner內部類

protected Set<BeanDefinitionHolder>doScan(String... basePackages)

從basePackage目錄尋找mapper接口,給每個接口實現一個MapperFactoryBean類,相當於每個mapper實例是一個dalsession。

2.     DalSessionDaoSupport

public final void setDalSessionFactory(DalSessionFactorydalSessionFactory)

加載完applicationContext-datasource.xml配置文件有,DalSessionFactoryBean注入創建dalsession

 

@Autowired(required = false)

this.dalSession = new MyDalSession(dalSessionFactory);

3.     MapperFactoryBean

public T getObject()

相當於每個mapperbean是一個被mapperproxy代理了的dalsession

 

ClassLoader classLoader = this.mapperInterface.getClassLoader();

Class<?>[] interfaces = new Class[]{this.mapperInterface};

MapperProxy proxy = new MapperProxy(this.getDalSession());

return (T) Proxy.newProxyInstance(classLoader,interfaces,proxy);

 

三、DALClient的全局事務

1.     MyDalSession.DalSessionInterceptor內部類

public Object invoke(Object proxy, Method method,Object[] args)

將事務交給spring全局事務代理

final DalSession dalSession = DalSessionUtils.getHolderSession(dalSessionFactory);

Object result = method.invoke(dalSession,args);

 

2.     DalSessionUtils

public static  DalSession getHolderSession(DalSessionFactorydalSessionFactory)

將事務交給spring全局事務,holder緩衝着basedalsession,這塊比較繞:mapper實例化爲mydalsession,但被DalSessionUtils代理了,完了還從全局DalSessionHolder緩存中得到BaseDalSession

 

DalSessionHolder holder = (DalSessionHolder)TransactionSynchronizationManager.getResource(dalSessionFactory);

       DalSession dalSession = null;

      

       if (holder != null && holder.isSynchronizedWithTransaction()) {

            holder.requested();

           

           return holder.getDalSession();

        }

       if (TransactionSynchronizationManager.isSynchronizationActive()){

           /**

             * Holder

             */

           dalSession = new BaseDalSession(dalSessionFactory.getConfiguration());

            holder = newDalSessionHolder(dalSession);

            TransactionSynchronizationManager.bindResource(dalSessionFactory,holder);

            TransactionSynchronizationManager.registerSynchronization(newDalSessionSynchronization(holder,dalSessionFactory));

            holder.setSynchronizedWithTransaction(true);

            holder.requested();

       }

       return dalSession;

 

3.     DalSessionUtils.DalSessionSynchronization 內部類

public voidbeforeCommit(boolean readOnly)

全局事務提交

public voidafterCompletion(int status)

全局事務關閉

 

四、DALClient數據訪問

1.     insert插入

如果是插入,獲取一次seq,保存入cache

 

Configuration configuration = dalSession.getConfiguration();

String commandName =declaringInterface.getName() + "." + method.getName();

MappedStatement ms =configuration.getMappedStatement(commandName);

KeyGenerator keyGenerator = ms.getKeyGenerator();

if (SqlCommandType.INSERT == type) {

            if (keyGenerator instanceofSelectKeyGenerator) {

               if(cache != null){

/**

                    * 得到獲得key的sql

                    */

String keysql =((SelectKeyGenerator)keyGenerator).keyStatement.getSqlSource().getBoundSql(null).getSql();

Object object= dalSession.selectKey(keysql);

                   /**

                    * 保存入緩存

                    */

                   cache.putObject(key, object);

               }

            }

            result = dalSession.insert(ms,args);

2.     select查詢

if (SqlCommandType.SELECT == type) {

/**

              * 從緩存取

              */

           Object object =cache.getObject(args[0]);

               result = dalSession.selectOne(ms,args);   

}

 

五、DALClient遊離對象

1.  MapperCache



六、DALClient類視圖




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章