天天看點

Java通用資料通路層Fastser-DAL推薦

本着不重複造輪子的原則,基于mybatis、spring jdbc、hibernate等ORM的通用資料通路層,支援基于datasource的讀寫分離、主備自動切換和故障轉移,支援簡單的負載均衡。

源碼位址:http://git.oschina.net/fastser/fastser-dal-all

特性:

  • 基于mybatis、spring jdbc、hibernate等各大orm架構實作通用dal層功能,并可以與已有項目完全相容。同時也可以在已經實作的orm架構之間任意切換,不需要對代碼作任何改動。
  • 實作dal層cache,可以自由設定過期時間。
  • 實作基于多資料源(datasource)的讀寫分離、主備切換、故障轉移、恢複檢測和負載均衡
  • 使用該元件必須遵循以下規則:
    • 在使用DTO時,字段名稱與資料庫表字段一緻,也可以不使用任何DTO類。
    • 不支援連表查詢,主要是單表操作,如果需要連表請與原生orm架構配合使用。

使用場景

随着nosql等新方案的出現,關系型資料庫更多的被用在業務資料存儲中,對于一些像報表等複雜資料處理的工作大部分公司已經不再使用關系型資料庫,而對于業務資料90%以上是不需要連表查詢等複雜操作的,該元件設計目标是将這90%的工作量變成零,避免重複工作,提高開發速度。使用該元件後将不再需要mybatis的自動生成,spring jdbc的sql語句,hibernate的各種注解,因為元件可以忙你處理。同時該元件隻是基于orm架構對所有單表操作的提取和封裝,最終還是由相應的orm架構完成持久化工作,是以不會代替orm的工作。是以論你的項目是新項目,還是老項目都可以使用,不會對原有業務生産任何影響,隻是使你的操作更加便利,不再需要無數dao類,隻要在需要的service中注入即可。元件需要遵循一定的COC規則,請大家注意。

maven

目前元件存放于oschina的maven庫中,請在項目中添加以下位址:http://maven.oschina.net/content/repositories/thirdparty/

    <dependency>
        <groupId>org.fastser</groupId>
        <artifactId>fastser-dal</artifactId>
        <version>1.0.2</version>
    </dependency>

    <dependency>
        <groupId>org.fastser</groupId>
        <artifactId>fastser-dal-mybatis</artifactId>
        <version>1.0.2</version>
    </dependency>
    或者
    <dependency>
        <groupId>org.fastser</groupId>
        <artifactId>fastser-dal-spring-jdbc</artifactId>
        <version>1.0.2</version>
    </dependency>      

jar檔案下載下傳位址:http://www.uncode.cn/fastser-dal/fastser-dal-all-1.0.2.zip

spring內建

動态資料源可以自動處理故障轉移和恢複檢測,讀寫分離時多個讀庫采用随機擷取。緩存可以自定義實作,可以統一開啟或關閉,友善在開發環境使用。

1 DataSource配置

可以使用任意資料庫連接配接池元件,建議使用Druid。配置Fastser-DAL動态資料源,将自動實作讀寫分離、主備自動切換和故障轉移等,建議使用。使用Fastser-DAL動态資料源後,在spring jdbc/mybatis配置中将所有的ref="dataSource"換成ref="dynamicDataSource"即可。

    <!--可選,動态資料源配置 -->
    <bean id="dynamicDataSource" class="org.fastser.dal.datasource.DynamicDataSource">
        <!-- 從資料庫配置,用于讀操作,目前負載均衡機制為随機取一個 -->
        <property name="slaveDataSources">
            <map key-type="java.lang.String">
                <entry key="readDataSourceOne" value-ref="dataSource3"/>
                <entry key="readDataSourceTwo" value-ref="dataSource4"/>
            </map>
        </property>
        <!-- 主資料庫配置 -->
        <property name="masterDataSource" ref="dataSource1" />
        <!-- 備資料庫配置 -->
        <property name="standbyDataSource" ref="dataSource2" />
    </bean>      

2 Spring jdbc 實作配置

    <!-- 可選,緩存預設實作,叢集時建議使用分布式緩存自定義實作 -->
    <bean id="dalCache" class="org.fastser.dal.cache.impl.ConcurrentMapCache"></bean>
    <!-- 配置緩存 -->
    <bean id="cacheManager" class="org.fastser.dal.cache.support.SimpleCacheManager">
        <property name="cache" ref="dalCache"></property>
    </bean>
    <!-- 配置資料源解析器 -->
    <bean id="resolveDatabase" class="org.fastser.dal.descriptor.db.impl.SimpleResolveDatabase">
        <property name="dataSource" ref="dataSource" />
        <property name="cacheManager" ref="cacheManager" />
    </bean>

    <!-- spring jdbc實作配置 -->
    <bean id="commonJdbcSupport" class="org.fastser.dal.spring.jdbc.CommonJdbcSupport">
        <property name="dataSource" ref="dataSource" />
    </bean>    
    <bean id="baseDAL" class="org.fastser.dal.spring.jdbc.SpringJDBCDAL">
        <property name="cacheManager" ref="cacheManager" />
        <property name="commonJdbcSupport" ref="commonJdbcSupport" />
        <property name="resolveDatabase" ref="resolveDatabase" />
        <!-- 可選,配置全局不使用緩存,預設為true -->
        <property name="useCache" value="false" />
        <!-- 可選,樂觀鎖,如果配置該項并且表中存在字段名為ver的字段,則該表可使用樂觀鎖機制 -->
        <property name="version" value="ver" />
    </bean>      

3 Mybatis 實作配置

    <!-- 可選,緩存預設實作,叢集時建議使用分布式緩存自定義實作 -->
    <bean id="dalCache" class="org.fastser.dal.cache.impl.ConcurrentMapCache"></bean>
    <!-- 配置緩存 -->
    <bean id="cacheManager" class="org.fastser.dal.cache.support.SimpleCacheManager">
        <property name="cache" ref="dalCache"></property>
    </bean>
    <!-- 配置資料源解析器 -->
    <bean id="resolveDatabase" class="org.fastser.dal.descriptor.db.impl.SimpleResolveDatabase">
        <property name="dataSource" ref="dataSource" />
        <property name="cacheManager" ref="cacheManager" />
    </bean>

    <!-- mybatis實作配置 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />  
    </bean>
    <bean id="commonMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">  
        <property name="sqlSessionFactory" ref="sqlSessionFactory" />  
        <property name="mapperInterface" value="org.fastser.dal.mybatis.CommonMapper" />
    </bean>
    <bean id="baseDAL" class="org.fastser.dal.mybatis.MybatisDAL">
        <property name="cacheManager" ref="cacheManager" />
        <property name="commonMapper" ref="commonMapper" />
        <property name="resolveDatabase" ref="resolveDatabase" />
        <!-- 可選,配置全局不使用緩存,預設為true -->
        <property name="useCache" value="false" />
        <!-- 可選,樂觀鎖,如果配置該項并且表中存在字段名為ver的字段,則該表可使用樂觀鎖機制 -->
        <property name="version" value="ver" />
    </bean>      

API

1 清單查詢

fields需要顯示的字段,queryCriteria查詢條件,seconds緩存時間

    QueryResult selectByCriteria(List<String> fields, QueryCriteria queryCriteria);
    QueryResult selectByCriteria(String[] fields, QueryCriteria queryCriteria);
    QueryResult selectByCriteria(List<String> fields, QueryCriteria queryCriteria, int seconds);
    QueryResult selectByCriteria(String[] fields, QueryCriteria queryCriteria, int seconds);
    QueryResult selectByCriteria(QueryCriteria queryCriteria);
    QueryResult selectByCriteria(QueryCriteria queryCriteria, int seconds);
    QueryResult selectPageByCriteria(List<String> fields, QueryCriteria queryCriteria);
    QueryResult selectPageByCriteria(String[] fields, QueryCriteria queryCriteria);
    QueryResult selectPageByCriteria(List<String> fields, QueryCriteria queryCriteria, int seconds);
    QueryResult selectPageByCriteria(String[] fields, QueryCriteria queryCriteria, int seconds);
    QueryResult selectPageByCriteria(QueryCriteria queryCriteria);
    QueryResult selectPageByCriteria(QueryCriteria queryCriteria, int seconds);      

2 統計查詢

queryCriteria查詢條件,seconds緩存時間

    int countByCriteria(QueryCriteria queryCriteria);
    int countByCriteria(QueryCriteria queryCriteria, int seconds);      

3 主鍵查詢

Object帶主鍵對象實體,fields需要顯示的字段,queryCriteria查詢條件,seconds緩存時間,clazz對象執行個體類型,id對象主鍵

    QueryResult selectByPrimaryKey(Object obj);
    QueryResult selectByPrimaryKey(Object obj, int seconds);
    QueryResult selectByPrimaryKey(List<String> fields, Object obj);
    QueryResult selectByPrimaryKey(String[] fields, Object obj);
    QueryResult selectByPrimaryKey(List<String> fields, Object obj, int seconds);
    QueryResult selectByPrimaryKey(String[] fields, Object obj, int seconds);
    QueryResult selectByPrimaryKey(Class<?> clazz, Object id);
    QueryResult selectByPrimaryKey(String table, Object id);
    QueryResult selectByPrimaryKey(Class<?> clazz, Object id, int seconds);
    QueryResult selectByPrimaryKey(String table, Object id, int seconds);
    QueryResult selectByPrimaryKey(List<String> fields, Class<?> clazz, Object id);
    QueryResult selectByPrimaryKey(List<String> fields, String table, Object id);
    QueryResult selectByPrimaryKey(List<String> fields, Class<?> clazz, Object id, int seconds);
    QueryResult selectByPrimaryKey(List<String> fields, String table, Object id, int seconds);      

4 插入

Object帶主鍵對象實體

    int insert(Object obj);      

5 更新

Object帶主鍵對象實體,queryCriteria查詢條件

    int updateByCriteria(Object obj, QueryCriteria queryCriteria);
    int updateByPrimaryKey(Object obj);      

6 删除

Object帶主鍵對象實體,queryCriteria查詢條件,clazz對象執行個體類型,id對象主鍵

    int deleteByPrimaryKey(Object obj);
    int deleteByPrimaryKey(Class<?> clazz, Object id);
    int deleteByPrimaryKey(String table, Object id);
    int deleteByCriteria(QueryCriteria queryCriteria);      

7 其他操作

database資料名稱,tableName表名稱

    void reloadTable(String tableName);
    void clearCache(String tableName);
    void reloadTable(String database, String tableName);
    void clearCache(String database, String tableName);      

8 QueryCriteria方法

    //排序,如:id desc, name
    setOrderByClause(String orderByClause)
    //去重
    setDistinct(boolean distinct)
    //隻查詢一條
    ssetSelectOne(boolean selectOne)
    //第幾頁,首頁為1
    setPageSize(int pageSize)
    //設定表名
    setTable(String table)
    //設定資料庫名稱,一般不需要設定
    setDatabase(String database)
    //使用樂觀鎖時設定版本,隻用于更新操作
    setVersion(Object version)
    //根據DTO對象類型設定名表,此時DTO類名必須與表名一緻
    setTable(Class<?> clazz)      

9 Criteria方法

    andColumnIsNull(String column)
    andColumnIsNotNull(String column)
    andColumnEqualTo(String column, Object value) 
    andColumnNotEqualTo(String column, Object value)
    andColumnGreaterThan(String column, Object value) 
    andColumnGreaterThanOrEqualTo(String column, Object value)
    andColumnLessThan(String column, Object value)
    andColumnLessThanOrEqualTo(String column, Object value)
    andColumnIn(String column, List<Object> values)
    andColumnNotIn(String column, List<Object> values)
    andColumnLike(String column, Object value) 
    andColumnNotLike(String column, Object value)
    andColumnBetween(String column, Object value1, Object value2)
    andColumnNotBetween(String column, Object value1, Object value2)      

使用示例

1 User表結構

    CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL COMMENT '使用者名',
  `pwd` varchar(50) DEFAULT NULL '密碼'
  `email` varchar(30) DEFAULT NULL '郵箱',
  `status` int(11) DEFAULT '0' COMMENT '1正常0禁用',
  `age` int(11) DEFAULT NULL '年齡',
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_user_userName` (`userName`)
  ) ENGINE=MyISAM AUTO_INCREMENT=167 DEFAULT CHARSET=utf8;      

2 User.class對象

    import java.io.Serializable;

    public class User implements Serializable {

    private static final long serialVersionUID = 4799201163494761002L;

    public static final String ID = "id";
    public static final String NAME = "name";
    public static final String PWD = "pwd";
    public static final String EMAIL = "email";
    public static final String STATUS = "status";
    public static final String AGE = "age";

    private int id;
    private String name;
    private String pwd;
    private String email;
    private int status;
    private int age;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
 }      

3 BaseDal注入

  • 注解方式
    import org.fastser.dal.core.BaseDAL;
    
    @Service
    public class UserService implements IUserService{
    
        @Autowired
        private BaseDAL baseDAL;
    
        .....
    }      
  • XML方式
    <bean id="userService" class="org.fastser.web.service.UserService">
        <property name="baseDAL" ref="baseDAL"></property>
    </bean>      

4 無DTO示例

  • 清單查詢
    • 示例1
      //建立查詢對象
      QueryCriteria queryCriteria = new QueryCriteria();
      //沒有DTO對象時可以直接設定表名
      //queryCriteria.setTable("user");
      //建立條件封裝對象
      Criteria critera = queryCriteria.createCriteria();
      //設定條件
      critera.andColumnGreaterThan(“age”, 18);
      critera.andColumnEqualTo("status", 1);
      //查詢所有字段并緩存
      QueryResult result =  baseDAL.selectByCriteria(queryCriteria);
      //查詢部分字段緩存60稱
      QueryResult result =  baseDAL.selectByCriteria(new String[]{"name","pwd"},queryCriteria, 60);
      List<Map<String, Object>> users = result.getList();
      //也可以轉成對應的DTO清單
      List<User> users = result.asList(User.class);      
    • 示例2
      //建立查詢對象
      QueryCriteria queryCriteria = new QueryCriteria();
      //設定查詢表,這樣設定時類名必須與表名一緻
      queryCriteria.setTable(“user”);
      //設定分頁
      queryCriteria.setPageIndex(1);
      queryCriteria.setPageSize(20);
      //設定排序
      queryCriteria.setOrderByClause("age desc");
      //分頁查詢并緩存60稱
      QueryResult result =  baseDAL.selectPageByCriteria(queryCriteria, 60);
      List<Map<String, Object>> list = result.getList();
      Map<String, Object>  page = result.getPage();      
  • 主鍵查詢
    • 示例1
      Map<String, Object> user = new HashMap<String, Object>();
      user.put("id", 1);
      //緩存20秒
      QueryResult result =  baseDAL.selectByPrimaryKey(user, 20);
      user = result.get();
      //也可以傳為DTO對象
      User dto = result.as(User.class);      
    • 示例2
      //顯示部分字段,不使用緩存
      QueryResult result =  baseDAL.selectByPrimaryKey(new String[]{"name","pwd"},"user", 1,BaseDal.NO_CAHCE);
      Map<String, Object> user = result.get();      
    • 示例3
      //不使用DTO對象,直接傳表名
      QueryResult result =  baseDAL.selectByPrimaryKey(”user“, 1,BaseDal.NO_CAHCE);
      Map<String, Object> user = result.get();      
    • 示例4
      //聯合主鍵查詢
      QueryCriteria queryCriteria = new QueryCriteria();
      queryCriteria.setTable(“user”);
      Criteria critera = queryCriteria.createCriteria();
      critera.andColumnEqualTo("name", "fastser-dal");
      critera.andColumnEqualTo("pwd", "fastser-dal-mybatis");
      queryCriteria.setSelectOne(true);
      QueryResult result =  baseDAL.selectByCriteria(queryCriteria);
      Map<String, Object> user = result.get();      
  • 插入
    • 示例1
      Map<String, Object> user = new HashMap<String, Object>();
      user.put("name", "fastser");
      user.put("pwd", faster");
      //第一個參數為表名
      int result = baseDAL.insert("user", user);      
  • 更新
    • 示例1
      Map<String, Object> user = new HashMap<String, Object>();
      user.put("name", "fastser-dal-mybatis");
      user.setName("fastser-dal-mybatis");
      QueryCriteria queryCriteria = new QueryCriteria();
      queryCriteria.setTable("user");
      Criteria critera = queryCriteria.createCriteria();
      critera.andColumnEqualTo("name", "fastser");
      int result = baseDAL.updateByCriteria(user, queryCriteria);      
    • 示例2
      Map<String, Object> user = new HashMap<String, Object>();
      user.put("email", "[email protected]");
      user.put("id", 1);
      //第一個參數為表名,user中必須包括所有主鍵字段
      int result = baseDAL.updateByPrimaryKey("user", user);      
  • 删除
    • 示例1
      Map<String, Object> user = new HashMap<String, Object>();
      user.put("email", "[email protected]");
      user.put("id", 1);
      //user中必須包括所有主鍵字段
      int result = baseDAL.deleteByPrimaryKey("user", user);      
    • 示例2
      //第一個參數為表名
      int result = baseDAL.deleteByPrimaryKey(“user”, 165);      
    • 示例3
      QueryCriteria queryCriteria = new QueryCriteria();
      queryCriteria.setTable("user");
      Criteria critera = queryCriteria.createCriteria();
      critera.andColumnEqualTo("name", "fastser");
      int result = baseDAL.deleteByCriteria(queryCriteria);      
  • 其他操作
    • 示例1
      QueryCriteria queryCriteria = new QueryCriteria();
      queryCriteria.setTable("user");
      Criteria critera = queryCriteria.createCriteria();
      critera.andColumnGreaterThan("age", 18);
      critera.andColumnEqualTo("status", 1);
      //數量統計
      int result =  baseDAL.countByCriteria(queryCriteria);      

5 使用DTO示例

  • 清單查詢
    • 示例1
      //建立查詢對象
      QueryCriteria queryCriteria = new QueryCriteria();
      //設定查詢表,這樣設定時類名必須與表名一緻
      queryCriteria.setTable(User.class);
      //建立條件封裝對象
      Criteria critera = queryCriteria.createCriteria();
      //設定條件
      critera.andColumnGreaterThan(User.AGE, 18);
      critera.andColumnEqualTo(User.STATUS, 1);
      //查詢所有字段并緩存
      QueryResult result =  baseDAL.selectByCriteria(queryCriteria);
      //查詢部分字段不緩存
      QueryResult result =  baseDAL.selectByCriteria(new String[]{"name","pwd"},queryCriteria, BaseDal.NO_CACHE);
      List<User> users = result.asList(User.class);      
    • 示例2
      //建立查詢對象
      QueryCriteria queryCriteria = new QueryCriteria();
      //設定查詢表,這樣設定時類名必須與表名一緻
      queryCriteria.setTable(User.class);
      //設定分頁
      queryCriteria.setPageIndex(1);
      queryCriteria.setPageSize(20);
      //設定排序
      queryCriteria.setOrderByClause(User.AGE+" desc");
      //分頁查詢并緩存60稱
      QueryResult result =  baseDAL.selectPageByCriteria(queryCriteria, 60);
      List<User> users = result.asList(User.class);
      Map<String, Object>  page = result.getPage();      
  • 主鍵查詢
    • 示例1
      User user = new User();
      user.setId(1);
      //緩存20秒,有多個主鍵時必須全部設值
      QueryResult result =  baseDAL.selectByPrimaryKey(user, 20);
      user = result.as(User.class);      
    • 示例2
      //顯示部分字段,不使用緩存
      QueryResult result =  baseDAL.selectByPrimaryKey(new String[]{"name","pwd"},User.class, 1,BaseDal.NO_CAHCE);
      User user = result.as(User.class);      
    • 示例3
      //聯合主鍵也可以使用這種方式查詢
      QueryCriteria queryCriteria = new QueryCriteria();
      queryCriteria.setTable(User.class);
      Criteria critera = queryCriteria.createCriteria();
      critera.andColumnEqualTo(User.NAME, "fastser-dal");
      critera.andColumnEqualTo(User.PWD, "fastser-dal-mybatis");
      queryCriteria.setSelectOne(true);
      QueryResult result =  baseDAL.selectByCriteria(queryCriteria);
      User user = result.as(User.class);      
  • 插入
    • 示例1
      User user = new User();
      user.setName("fastser");
      user.setPwd("faster");
      int result = baseDAL.insert(user);      
  • 更新
    • 示例1
      User user = new User();
      user.setName("fastser-dal-mybatis");
      QueryCriteria queryCriteria = new QueryCriteria();
      queryCriteria.setTable(User.class);
      Criteria critera = queryCriteria.createCriteria();
      critera.andColumnEqualTo(User.NAME, "fastser");
      int result = baseDAL.updateByCriteria(user, queryCriteria);      
    • 示例2
      User user = new User();
      user.setEmail("[email protected]");
      user.setId(1);
      //user中必須設值所有主鍵字段
      int result = baseDAL.updateByPrimaryKey(user);      
  • 删除
    • 示例1
      User user = new User();
      user.setId(1);
      //user中必須設值所有主鍵字段
      int result = baseDAL.deleteByPrimaryKey(user);      
    • 示例2
      int result = baseDAL.deleteByPrimaryKey(User.class, 165);      
    • 示例3
      QueryCriteria queryCriteria = new QueryCriteria();
      queryCriteria.setTable(User.class);
      Criteria critera = queryCriteria.createCriteria();
      critera.andColumnEqualTo(User.NAME, "fastser");
      int result = baseDAL.deleteByCriteria(queryCriteria);      
  • 其他操作
    • 示例1
      QueryCriteria queryCriteria = new QueryCriteria();
      queryCriteria.setTable(User.class);
      Criteria critera = queryCriteria.createCriteria();
      critera.andColumnGreaterThan(User.AGE, 18);
      critera.andColumnEqualTo(User.STATUS, 1);
      //數量統計
      int result =  baseDAL.countByCriteria(queryCriteria);