zoukankan      html  css  js  c++  java
  • 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();
          }  

        相信一万小时天才理论

          最穷不过要饭,不死终会出头! 

  • 相关阅读:
    使用 libevent 和 libev 提高网络应用性能
    An existing connection was forcibly closed by the remote host
    各种浏览器的兼容css
    vs输出窗口,显示build的时间
    sass
    网站设置404错误页
    List of content management systems
    css footer not displaying at the bottom of the page
    强制刷新css
    sp_executesql invalid object name
  • 原文地址:https://www.cnblogs.com/misscai/p/9800241.html
Copyright © 2011-2022 走看看