<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          dexcoder-dal通用數(shù)據(jù)庫訪問層

          聯(lián)合創(chuàng)作 · 2023-09-30 02:13

          核心組件dexcoder-dal使用說明

          如果你不喜歡用Hibernate、Mybaits這類ORM框架,喜歡JdbcTemplate或DbUtils,那么可以試試這個封裝的通用dal,這可能是目前封裝的最方便易用的通用dal層了。

          dexcoder-dal的一些特性:

          1. 一個dao即可以搞定所有的實體類,不必再一個個建立跟實體對應(yīng)的繼承于類似BaseDao這類“通用dao”了。

          2. 各類方法參數(shù)除了Entity外,支持更強大的Criteria方式。

          3. sql的where條件支持一些復(fù)雜的條件,如等于、不等于、or、in、not in甚至是執(zhí)行函數(shù)。

          4. 允許在查詢時指定使用哪個字段進行排序,可以指定多個進行組合升降序自由排序。

          5. 支持在查詢時指定返回字段的白名單和黑名單,可以指定只返回某些字段或不返回某些字段。

          6. select查詢時支持函數(shù),count()、max()、to_char()、甚至是distinct,理論上都可以支持。

          7. 方便強大的分頁功能,無須額外操作,二三行代碼搞定分頁,自動判斷數(shù)據(jù)庫,無須指定。

          8. 可以使用{}和[]完成一些特殊的操作,{}中的代碼將原生執(zhí)行,[]中的代碼會進行命名轉(zhuǎn)換,一般fieldName轉(zhuǎn)columnName。

          9. 支持執(zhí)行自定義sql。

          10. 支持使用類似mybatis的方式執(zhí)行自定義sql。

          11. 支持讀寫分離和動態(tài)數(shù)據(jù)源。

          該通用dao是在使用過程中,針對常規(guī)的泛型dao經(jīng)常遇到的一些不便問題進行了改進。命名上遵循了約定優(yōu)于配置的原則,典型約定如下:

          • 表名約定USER_INFO表實體類名為UserInfo。

          • 字段名約定USER_NAME實體類中屬性名為userName。

          • 主鍵名約定USER_INFO表主鍵名為USER_INFO_ID,同理實體類中屬性名為userInfoId。

          • Oracle序列名約定USER_INFO表對應(yīng)的主鍵序列名為SEQ_USER_INFO

          當(dāng)然,這些你可以在擴展中改變它,但不建議這么做,這本身就是一個良好的規(guī)范。

          要在項目中使用通用dao十分簡單,目前已上maven中央庫,直接在pom.xml中添加依賴:

          <dependency>
              <groupId>com.dexcoder</groupId>
              <artifactId>dexcoder-dal-spring</artifactId>
              <version>2.2.0-beta1</version>
          </dependency>

          然后在spring的配置文件中聲明如下bean:

          <bean id="jdbcDao" class="com.dexcoder.dal.spring.JdbcDaoImpl">
              <property name="jdbcTemplate" ref="jdbcTemplate"/>
          </bean>
          <!--需要分頁時聲明-->
          <bean id="pageControl" class="com.dexcoder.dal.spring.page.PageControl"></bean>

          接下來就可以注入到您的Service或者其它類中使用了。

          下面是一些常用的方法示例,這里的Entity對象為User,對于任何的Entity都是一樣的.

          先來看一下User對象及它繼承的Pageable

          public class User extends Pageable {
              private Long              userId;
              private String            loginName;
              private String            password;
              private Integer           userAge;
              private String            userType;
              private String            email;
              private Date              gmtCreate;
              //......
          }

          Pageable對象,用來保存頁碼、每頁條數(shù)信息以支持分頁

          public class Pageable implements Serializable {
              /** 每頁顯示條數(shù) */
              protected int             itemsPerPage     = 20;
              /** 當(dāng)前頁碼 */
              protected int             curPage          = 1;
          
              //......
          }

          都是普通的JavaBean對象,下面來看看如何進行具體的增刪改查,每種操作都演示了Entity和Criteria兩種方式。

          insert操作

          public void insert() {
              User user = new User();
              user.setLoginName("selfly_a");
              user.setPassword("123456");
              user.setEmail("[email protected]");
              user.setUserAge(18);
              user.setUserType("1");
              user.setGmtCreate(new Date());
              Long id = jdbcDao.insert(user);
              System.out.println("insert:" + id);
          }
          
          public void insert2() {
              Criteria criteria = Criteria.insert(User.class).into("loginName", "selfly_b").into("password", "12345678")
                  .into("email", "[email protected]").into("userAge", 22).into("userType", "2").into("gmtCreate", new Date());
              Long id = jdbcDao.insert(criteria);
              System.out.println("insert:" + id);
          }

          save操作,和insert的區(qū)別在于不處理主鍵,由調(diào)用者指定

          public void save() {
              User user = new User();
              user.setUserId(-1L);
              user.setLoginName("selfly-1");
              user.setPassword("123456");
              user.setEmail("[email protected]");
              user.setUserAge(18);
              user.setUserType("1");
              user.setGmtCreate(new Date());
              jdbcDao.save(user);
          }
          
          public void save2() {
              Criteria criteria = Criteria.insert(User.class).into("userId", -2L).into("loginName", "selfly-2")
                  .into("password", "12345678").into("email", "[email protected]").into("userAge", 22).into("userType", "2")
                  .into("gmtCreate", new Date());
              jdbcDao.save(criteria);
          }

          update操作

          public void update() {
              User user = new User();
              user.setUserId(57L);
              user.setPassword("abcdef");
              user.setGmtModify(new Date());
              jdbcDao.update(user);
          }
          
          public void update2() {
              Criteria criteria = Criteria.update(User.class).set("password", "update222")
                  .where("userId", new Object[] { 56L, -1L, -2L });
              jdbcDao.update(criteria);
          }

          get操作

          public void get1() {
              User u = jdbcDao.get(User.class, 63L);
              Assert.assertNotNull(u);
              System.out.println(u.getUserId() + " " + u.getLoginName() + " " + u.getUserType());
          }
          
          public void get2() {
              //criteria,主要用來指定字段白名單、黑名單等
              Criteria criteria = Criteria.select(User.class).include("loginName");
              User u = jdbcDao.get(criteria, 73L);
              Assert.assertNotNull(u);
              System.out.println(u.getUserId() + " " + u.getLoginName() + " " + u.getUserType());
          }

          delete操作

          public void delete() {
              //會把不為空的屬性做為where條件
              User u = new User();
              u.setLoginName("selfly-1");
              u.setUserType("1");
              jdbcDao.delete(u);
          }
          
          public void delete2() {
              //where條件使用了or
              Criteria criteria = Criteria.delete(User.class).where("loginName", new Object[] { "liyd2" })
                  .or("userAge", new Object[]{64});
              jdbcDao.delete(criteria);
          }
          
          public void delete3() {
              //根據(jù)主鍵
              jdbcDao.delete(User.class, 57L);
          }

          列表查詢操作

          public void queryList() {
              //所有結(jié)果
               List<User> users = jdbcDao.queryList(User.class);
          }
          
          public void queryList1() {
              //以不為空的屬性作為查詢條件
               User u = new User();
              u.setUserType("1");
              List<User> users = jdbcDao.queryList(u);
          }
          
          public void queryList2() {
              //Criteria方式
              Criteria criteria = Criteria.select(User.class).exclude("userId")
                  .where("loginName", new Object[]{"liyd"});
              List<User> users = jdbcDao.queryList(criteria);
          }
          
          public void queryList3() {
              //使用了like,可以換成!=、in、not in等
              Criteria criteria = Criteria.select(User.class).where("loginName", "like",
                  new Object[] { "%liyd%" });
              user.setUserAge(16);
              //這里entity跟criteria方式混合使用了,建議少用
              List<User> users = jdbcDao.queryList(user, criteria.include("userId"));
          }

          count記錄數(shù)查詢,除了返回值不一樣外,其它和列表查詢一致

          public void queryCount() {
              user.setUserName("liyd");
              int count = jdbcDao.queryCount(user);
          }
          
          public void queryCount2() {
              Criteria criteria = Criteria.select(User.class).where("loginName", new Object[] { "liyd" })
                  .or("userAge", new Object[]{27});
              int count = jdbcDao.queryCount(criteria);
          }

          查詢單個結(jié)果

          public void querySingleResult() {
              user = jdbcDao.querySingleResult(user);
          }
          
          public void querySingleResult2() {
              Criteria criteria = Criteria.select(User.class).where("loginName", new Object[] { "liyd" })
                  .and("userId", new Object[]{23L});
              User u = jdbcDao.querySingleResult(criteria);
          }

          指定字段白名單,在任何查詢方法中都可以使用

          public void get(){
              //將只返回userName
              Criteria criteria = Criteria.select(User.class).include("loginName");
              User u = jdbcDao.get(criteria, 23L);
          }

          指定字段黑名單,在任何查詢方法中都可以使用

          public void get4(){
              //將不返回loginName
              Criteria criteria = Criteria.select(User.class).exclude("loginName");
              User u = jdbcDao.get(criteria, 23L);
          }

          指定排序

          public void queryList() {
              //指定多個排序字段,asc、desc
              Criteria criteria = Criteria.select(User.class).exclude("userId")
                  .where("loginName", new Object[]{"liyd"}).asc("userId").desc("userAge");
              List<User> users = jdbcDao.queryList(criteria);
          }

          分頁

          public void queryList1() {
              //進行分頁
              PageControl.performPage(user);
              //分頁后該方法即返回null,由PageControl中獲取
              jdbcDao.queryList(user);
              Pager pager = PageControl.getPager();
              //列表
              List<User> users = pager.getList(User.class);
              //總記錄數(shù)
              int itemsTotal = pager.getItemsTotal();
          }
          
          public void queryList2() {
              //直接傳入頁碼和每頁條數(shù)
              PageControl.performPage(1, 10);
              //使用Criteria方式,并指定排序字段方式為asc
              Criteria criteria = Criteria.select(User.class).include("loginName", "userId")
                  .where("loginName", new Object[]{"liyd"}).asc("userId");
              jdbcDao.queryList(criteria);
              Pager pager = PageControl.getPager();
          }

          不同的屬性在括號內(nèi)or的情況:

          Criteria criteria = Criteria.select(User.class)
                  .where("userType", new Object[] { "1" }).begin()
                  .and("loginName", new Object[] { "selfly" })
                  .or("email", new Object[] { "[email protected]" }).end()
                  .and("password", new Object[] { "123456" });
              User user = jdbcDao.querySingleResult(criteria);

          執(zhí)行函數(shù)

          //max()
          Criteria criteria = Criteria.select(User.class).addSelectFunc("max([userId])");
          Long userId = jdbcDao.queryForObject(criteria);
          
          //count()
          Criteria criteria = Criteria.select(User.class).addSelectFunc("count(*)");
          Long count = jdbcDao.queryForObject(criteria);
          
          //distinct
          Criteria criteria = Criteria.select(User.class).addSelectFunc("distinct [loginName]");
          List<Map<String, Object>> mapList = jdbcDao.queryForList(criteria);

          默認(rèn)情況下,addSelectFunc方法返回結(jié)果和表字段互斥,并且沒有排序,如果需要和表其它字段一起返回并使用排序,可以使用如下代碼:

          Criteria criteria = Criteria.select(User.class).addSelectFunc("DATE_FORMAT(gmt_create,'%Y-%m-%d %h:%i:%s') date",false,true);
          List<Map<String, Object>> mapList = jdbcDao.queryForList(criteria);

          這是在select中執(zhí)行函數(shù),那怎么在update和where條件中執(zhí)行函數(shù)呢?前面提到的{}和[]就可以起到作用了。

          看下面代碼:

          Criteria criteria = Criteria.update(User.class).set("[userAge]", "[userAge]+1")
              .where("userId", new Object[] { 56L });
          jdbcDao.update(criteria);

          以上代碼將執(zhí)行sql:UPDATE USER SET USER_AGE = USER_AGE+1  WHERE USER_ID =  ?,[]中的fieldName被轉(zhuǎn)換成了columnName,

          也可以使用{}直接寫columnName,因為在{}中的內(nèi)容都是不做任何操作原生執(zhí)行的,下面代碼效果是一樣的:

          Criteria criteria = Criteria.update(User.class).set("{USER_AGE}", "{USER_AGE + 1}")
              .where("userId", new Object[] { 56L });
          jdbcDao.update(criteria);

          同理,在where中也可以使用該方式來執(zhí)行函數(shù):

          Criteria criteria = Criteria.select(User.class).where("[gmtCreate]", ">",
              new Object[] { "str_to_date('2015-10-1','%Y-%m-%d')" });
          List<User> userList = jdbcDao.queryList(criteria);

          表別名支持

          有些時候,就算單表操作也必須用到表別名,例如oracle中的xmltype類型。可以在Criteria中設(shè)置表別名:

          Criteria criteria = Criteria.select(Table.class).tableAlias("t").addSelectFunc("[xmlFile].getclobval() xmlFile")
                  .where("tableId", new Object[]{10000002L});
          Object obj = jdbcDao.queryForObject(criteria);
          
          //對應(yīng)的sql
          select t.XML_FILE.getclobval() xmlFile from TABLE t where t.TABLE_ID = ?

          執(zhí)行自定義sql

          在實際的應(yīng)用中,一些復(fù)雜的查詢?nèi)缏?lián)表查詢、子查詢等是省不了的。鑒于這類sql的復(fù)雜性和所需要的各類優(yōu)化,通用dao并沒有直接封裝而是提供了執(zhí)行自定義sql的接口。

          執(zhí)行自定義sql支持兩種方式:直接傳sql執(zhí)行和mybatis方式執(zhí)行。

          直接傳sql執(zhí)行

          該方式可能會讓除了dao層之外的業(yè)務(wù)層出現(xiàn)sql代碼,因此是不推薦的,它適合一些不在項目中的情況。

          何為不在項目中的情況?例如做一個開發(fā)自用的小工具,臨時處理一批業(yè)務(wù)數(shù)據(jù)等這類后期不需要維護的代碼。

          要執(zhí)行自定義sql首先需要在jdbcDao中注入sqlFactory,這里使用SimpleSqlFactory:

          <bean id="jdbcDao" class="com.dexcoder.dal.spring.JdbcDaoImpl">
              <property name="jdbcTemplate" ref="jdbcTemplate"/>
              <property name="sqlFactory" ref="sqlFactory"/>
          </bean>
          <bean id="sqlFactory" class="com.dexcoder.dal.SimpleSqlFactory">
          </bean>

          然后就可以直接傳入sql執(zhí)行了:

          List<Map<String, Object>> list = jdbcDao.queryForSql("select * from USER where login_name = ?",
              new Object[] { "selfly_a99" });

          這個實現(xiàn)比較簡單,參數(shù)Object數(shù)組中不支持復(fù)雜的自定義對象。

          mybatis方式執(zhí)行

          采用了插件式實現(xiàn),使用該方式首先添加依賴:

          <dependency>
              <groupId>com.dexcoder</groupId>
              <artifactId>dexcoder-dal-batis</artifactId>
              <version>2.2.0-beta1</version>
          </dependency>

          之后同樣注入sqlFactory,把上面的SimpleSqlFactory替換成BatisSqlFactoryBean:

          <bean id="jdbcDao" class="com.dexcoder.dal.spring.JdbcDaoImpl">
              <property name="jdbcTemplate" ref="jdbcTemplate"/>
              <property name="sqlFactory" ref="sqlFactory"/>
          </bean>
          <bean id="sqlFactory" class="com.dexcoder.dal.batis.BatisSqlFactoryBean">
              <property name="sqlLocation" value="user-sql.xml"/>
          </bean>

          BatisSqlFactoryBean有一個sqlLocation屬性,指定自定義的sql文件,因為使用了spring的解析方式,所以可以和指定spring配置文件時一樣使用各類通配符。

          user-sql.xml是一個和mybatis的mapper類似的xml文件:

          <?xml version="1.0" encoding="UTF-8" ?>
          <!DOCTYPE mapper
                  PUBLIC "-//dexcoder.com//DTD Mapper 2.0//EN"
                  "http://www.dexcoder.com/dtd/batis-mapper.dtd">
          <mapper namespace="User">
              <sql id="columns">
                  user_id,login_name,password,user_age,user_type
              </sql>
          
              <select id="getUser">
                  select
                  <include refid="columns"/>
                  from user
                  <where>
                      <if test="params[0] != null">
                          user_type = #{params[0].userType}
                      </if>
                      <if test="params[1] != null">
                          and login_name in
                          <foreach collection="params[1]" index="index" item="item" separator="," open="(" close=")">
                              #{item}
                          </foreach>
                      </if>
                  </where>
              </select>
          </mapper>

          然后使用代碼調(diào)用:

          User user = new User();
          user.setUserType("1");
          Object[] names = new Object[] { "selfly_a93", "selfly_a94", "selfly_a95" };
          List<Map<String, Object>> mapList = jdbcDao.queryForSql("User.getUser", "params", new Object[] { user, names });
          for (Map<String, Object> map : mapList) {
              System.out.println(map.get("userId"));
              System.out.println(map.get("loginName"));
          }

          我們調(diào)用queryForSql方法時傳入了三個參數(shù):

          • User.getUser 具體的sql全id,namespace+id。

          • params 自定義sql中訪問參數(shù)的key,如果不傳入默認(rèn)為item。

          • Object[] sql中用到的參數(shù)。訪問具體參數(shù)時可以使用item[0],item[1]對應(yīng)里面相應(yīng)的元素,支持復(fù)雜對象。

          可以看到這里支持復(fù)雜參數(shù),第一個是Userbean對象,第二個是Object數(shù)組,至于獲取方式可以看上面的xml代碼。

          除了傳入的參數(shù)為Object數(shù)組并使用item[0]這種方式訪問相應(yīng)的元素外,其它的和mybatis可以說是一樣的,mybatis支持的動態(tài)sql方式這里也可以支持,因為他本身就是來源于mybatis。

          另外返回結(jié)果中map的key做了LOGIN_NAME到駱駝命名法loginName的轉(zhuǎn)換。

          一些說明

          BatisSqlFactory方式由分析了mybatis源碼后,提取使用了大量mybatis的代碼。

          JdbcDao在聲明時可以根據(jù)需要注入其它幾個參數(shù):

          <bean id="jdbcDao" class="com.dexcoder.dal.spring.JdbcDaoImpl">
              <property name="jdbcTemplate" ref="jdbcTemplate"/>
              <property name="sqlFactory" ref="..."/>
              <property name="nameHandler" ref="..."/>
              <property name="rowMapperClass" value="..."/>
              <property name="dialect" value="..."/>
          </bean>
          • nameHandler 默認(rèn)使用DefaultNameHandler,即遵守上面的約定優(yōu)于配置,如果需要自定義可以實現(xiàn)該接口。

          • sqlFactory 執(zhí)行自定義sql時注入相應(yīng)的sqlFactory。

          • rowMapperClass 默認(rèn)使用了spring的BeanPropertyRowMapper.newInstance(clazz),需要自定義可以自行實現(xiàn),標(biāo)準(zhǔn)spring的RowMapper實現(xiàn)即可。

          • dialect 數(shù)據(jù)庫方言,為空會自動判斷,一般不需要注入。

          瀏覽 37
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          編輯 分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          編輯 分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  啪啪啪网站大全 | 91在线免费视频 | 爱搞视频网站在线观看 | 操BA片| 亚洲欧洲在线无码 |