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();
          }  

        相信一万小时天才理论

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

  • 相关阅读:
    Java uuid生成随机32位
    Java 、C# Excel模板,数据一对多,主从表关系,导入到数据库
    ROS 八叉树地图构建
    操作系统基础信息搜集
    菜鸟的信息安全学习之路
    提权初探
    Windos/Linux 反弹 shell
    初读鸟哥的linux私房菜的收获
    linux中find命令的摘要
    分享一个Flink checkpoint失败的问题和解决办法
  • 原文地址:https://www.cnblogs.com/misscai/p/9800241.html
Copyright © 2011-2022 走看看