Mybatis之mapper接口開發


(一)需求,為什么要使用接口開發?

  1.  在測試用例中,在調用session的方法的時候,都會傳入要調用的SQL的namespace+id名稱,這不是必須的。可以只傳入id即可。但是,如果在mybatis的環境中有多個相同id的映射名稱,就會報錯。所以,一般情況下,調用方法最好還是使用namespace+id。
  2. 但是,namespace+id的使用方式很容易報錯,因為是string類型的,沒有檢查。所以,mybatis提供了一種非常好的設計方式來避免這種問題,即Mapper接口。

   接口開發的規范namespace的值=接口的包名+接口的類名

  注意:

  1、 包名 + 類名 = XXXMapper.xml中namespace的值

  2、 接口中方法名 =  mapper.xml中 具體的SQL語句定義的id值

  3、 方法的返回值和參數要和映射文件中一致(當數據庫的字段名和對象的屬性名一致時,可以用簡單屬性resultType。但是當數據庫中的字段名稱和對象中的屬性名稱不一致時,就需要resultMap                  屬性。

   /*
     <select id="all" resultType="User">

          select * from user

     </select>

     */

     public List<User>  all();    //這是接口中的方法

    

 


 

(二)Mybatis怎么做的?

    @Test
     public void testMapper(){

          SqlSession session = MyBatisUtil.openSession();
          try{
                UserMapper mapper = session.getMapper(UserMapper.class);

                System.out.println(mapper.getClass().getName());

          }finally{
                session.close();
          }
     }

    打印結果:

    $Proxy4

       很簡單了,mybatis為接口做了一個動態代理。在執行UserMapper接口上面的方法時,參考接口的全路徑名,即可找到對應的UserMapper.xml,在執行接口上面的每一個方法的時候,實際上                 就是在執行namespace+id,mybatis在根據定義的方法的元素,選擇調用合適的session的方法來執行,並傳入參數就可以。

     使用Mapper接口的方式,在集成Spring+MyBatis也非常方便。因為我們可以直接把Mapper接口看作domain的dao接口了。


 

(三)接口開發的三個特點

  1、     Mapper接口方法名和mapper.xml中定義sql的id值相同

  2、     Mapper接口方法接收的參數類型和mapper.xml中定義的sql 的parameterType的類型相同

  3、     Mapper接口方法的返回值類型和mapper.xml中定義的sql的resultType的類型相同

 


 

(四)自動匹配規范駝峰規則

  數據庫中我們習慣使用全大寫,多個單詞用下划線隔開,而po對象,習慣使用java駝峰規則。那一個一個手工寫resultMap字段,浪費開發時間。Mybatis可以配置mapUnderscoreToCamelCase,實現自動映射。這個值默認為true。

   1  sqlMapConfig.xml中配置settings 

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE configuration

PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

     <settings>

          <setting name="mapUnderscoreToCamelCase" value="true" />

     </settings>

</configuration>
  1.  在XXXmapper文件中  resultMap配置autoMapping="true"

<resultMap type="cn.tedu.jk.domain.Contract" id="contractRM" autoMapping="true">

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

 </resultMap>

 

注意:主鍵需要單獨寫,其它字段就可以直接利用駝峰規則自動映射。

 


 

(五)SQL模糊查詢

   1  參數中直接加入%%(不好)

      如果要發起一條SQL,where name like #{name},name手動傳入%大%這里就容易發生SQL注入問題

   2  Sql中用CONCAT函數 (推薦) 三種數據庫的字符串拼接

      Sql Server 中沒有Concat函數   拼接  直接用  +  號

         Oracle 和 MySQL 可以用Concat進行拼接

    

  

<!-- where 2-->
     <select id="findone2" resultType="User" parameterType="map">
          select <include refid="cols"></include> 
      from user
<where> id=#{id} and addr=#{addr} and name like concat(concat('%',#{name}),'%') </where>    </select>

 


 

(六)【重點】關聯關系

  1 准備數據

1.3.1.1  用戶表user_info
create table user_info(

id int primary key auto_increment,

user_name varchar(100),

user_addr varchar(200),

user_age int);

set names gbk;

insert into user_info values(null,’韓梅梅’,’上海’,20);

insert into user_info values(null,’王海濤’,’北京’,30);

insert into user_info values(null,’張慎政’,’河南’,10);

1.3.1.2  用戶擴展表user_extra
create table user_extra(

id int primary key auto_increment,

user_id int,

work varchar(100),

salary double);

insert into user_extra values(null,’1’,’程序員’,100000);

insert into user_extra values(null, ’2’,’教師’,1000);

insert into user_extra values(null, ’3’,’CTO’,100000);

1.3.1.3  訂單表orders
create table orders(

id int primary key auto_increment,

user_id int,

order_no int,

order_desc varchar(100),

price double);

insert into orders values(null,1,100,’好評’,1000);

insert into orders values(null,2,200,’優秀’,100);

insert into orders values(null,1,300,’優秀’,100);

insert into orders values(null,1,400,’優秀’,100);

  封裝對象

public class UserInfo {
      //id映射
      private int id;
      //user_name映射
      private String userName;
      //user_addr映射
      private String userAddr;
      //user_age映射
      private int userAge;

    自己生成一下get,set方法,和toString 方法 (Ecilipse快捷鍵 SHIFT+ALT+S)
}

 

public class UserExtra {
      //id映射
      private int id;
      //work映射
      private String work;
      //salary映射
      private double salary;
      //user_id映射(對應user表的id)
      private int userId;
    自己生成一下get,set方法,和toString 方法 (Ecilipse快捷鍵 SHIFT+ALT+S)
}

 

public class Orders {
      //id映射
      private int id;
      //user_id映射
      private int userId;
      //order_no映射
      private int orderNo;
      //order_desc映射
      private String orderDesc;
      //price映射
      private double price;
     自己生成一下get,set方法,和toString 方法 (Ecilipse快捷鍵 SHIFT+ALT+S)
}

     3 根據用戶查詢一對一關系的用戶擴展信息,使用association  +  javaType

     3.1改造UserInfo對象 (將UserExtra對象引入)

public class UserInfo {
      private int id;
      private String userName;
      private String userAddr;
      private int userAge;    

      //一對一  

    private UserExtra userExtra;
    自己生成一下get,set方法,和toString 方法 (Ecilipse快捷鍵 SHIFT+ALT+S)
}

        3.2編寫UserInfoMapper.xml(引入核心配置文件中去!!association  +  javaType

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
      PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.tedu.dao.UserInfoDao">
<!-- 一對一的UserExtra信息
           type=""  把數據封裝給哪個實體對象(全路徑)
           id="userExtraRM" 唯一標志
      -->
      <resultMap type="cn.tedu.pojo.UserInfo"
                      id="userExtraRM">
           <!-- association用來描述一對一關系
                 property="userExtra"  在UserInfo中的屬性
                 javaType=""  關聯對象的類的全路徑...
           -->
      <association property="userExtra" javaType="cn.tedu.pojo.UserExtra">
                 <!-- 描述UserExtra信息... -->
                 <id column="id" property="id" />
                 <result column="work" property="work" />
                 <result column="salary" property="salary" />
                 <result column="user_id" property="userId" />
           </association>
      </resultMap>
    <!-- 根據用戶id查詢用戶詳情 -->
    <!-- 一對一的關聯查詢 resultMap="" 引用上面大的結果集,id值 -->
      <select id="getExtraByUserId"
                 resultMap="userExtraRM">
           select * from
           user_info t1,
           user_extra t2
           where
           t1.id=t2.user_id
           and t1.id=#{id}
      </select>
</mapper>

   3.3 創建UserInfoDAO接口

public interface UserInfoDao {

      //根據用戶id查詢用戶的信息,一對一
      public UserInfo getExtraByUserId(int userId);
 

}

    3.4測試代碼 

public class ORMTest {
//   1,讀取配置文件,創建ssf對象
      SqlSessionFactory ssf;
      @Before
      public void init(){
           try {
                 InputStream inputStream =
                            Resources.getResourceAsStream(
                                       "sqlMapConfig.xml");
                 ssf = new SqlSessionFactoryBuilder()
                            .build(inputStream);
           } catch (IOException e) {
                 e.printStackTrace();
           }
      }
      //測試對象的一對一關系
      @Test
      public void One2One(){
           //創建sqlsession,執行SQL
           SqlSession session = ssf.openSession();
           //接口開發
           UserInfoDao dao = session.getMapper(UserInfoDao.class);
           //調用接口方法
           UserInfo info = dao.getExtraByUserId(1);
           System.out.println(info);
           session.close();
      }
}

   4 一對多  查詢用戶的所有訂單,使用collection  +  ofType

  4.1改造UserInfo對象 (將UserExtra對象引入)

public class UserInfo {
      private int id;
      private String userName;
      private String userAddr;
      private int userAge;
      private UserExtra userExtra;    

    //一對多

      private List<Orders> orders;
   自己生成一下get,set方法,和toString 方法 (Ecilipse快捷鍵 SHIFT+ALT+S)
}

  4.2 改造UserInfoMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
      PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.tedu.dao.UserInfoDao">
 <!-- 一對多的關聯關系 type="" 結果集封裝到哪個對象身上 extends="userInfoRM" 和其他resultMap的關聯關系 -->
      <resultMap type="cn.tedu.pojo.UserInfo"
                 id="ordersRM"
           extends="userInfoRM">
           <!-- 多的一方Orders的對象信息 property="" UserInfo對象中的屬性名 ofType="" 關聯對象Orders的全路徑 -->
           <collection property="orders" ofType="cn.tedu.pojo.Orders">
                 <!-- 描述Orders的信息 -->
                 <id column="id" property="id" />
                 <!-- 普通字段 -->
                 <result column="user_id" property="userId" />
                 <result column="order_no" property="orderNo" />
                 <result column="order_desc" property="orderDesc" />
                 <result column="price" property="price" />
           </collection>
      </resultMap>
</mapper>

 

增加關聯查詢的SQL
注意:結果集中,不要出現同名的字段,否則封裝不成功!!如果出現重復字段,以結果集為准,重新映射column關系。
      <!-- 根據用戶id查詢訂單信息
           resultMap="ordersRM"引用其他resultMap,id值
      -->
      <select id="getOrdersByUserId"
                 resultMap="ordersRM">
           select * from
           user_info t1,
           orders t2
           where t1.id=t2.user_id
           and t1.id=#{id}
      </select>

   4.3改造UserInfoDao接口

public interface UserInfoDao {
      //根據用戶id查詢用戶的信息,一對一
      public UserInfo getExtraByUserId(int userId);
      //據用戶id查詢訂單信息
      public List<UserInfo>
                 getOrdersByUserId(int userId);
}

 4.4改造測試類

      @Test
      public void One2Many(){
           //創建sqlsession,執行SQL
           SqlSession session = ssf.openSession();
           //接口開發
           UserInfoDao dao =
                      session.getMapper(UserInfoDao.class);
           //調用接口方法,根據用戶id查詢訂單
           List<UserInfo> list =
                      dao.getOrdersByUserId(1);
           for (UserInfo userInfo : list) {
                 System.out.println(userInfo);
           }
           session.close();
      }  

 

 


 

 

    相信一萬小時天才理論

      最窮不過要飯,不死終會出頭! 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM