MyBatis框架学习(4)

SQL映射文件

内容为雷丰阳老师的SSM框架内容记录

1.增删改标签

<insert id="insertEmployee" databaseId="">
            INSERT INTO mybatis_0325.t_employee(empname, gender, email)
            VALUE(#{empName}, #{gender}, #{email})
</insert>

在这里插入图片描述

实现获取到插入数据后的自增id:

 <!--
            让MyBatis将自动增长的id赋值给传入的employee对象的id属性
            useGeneratedKeys="true":告诉mybatis我要使用sql中的自动增长;原生jdbc获取自增主键的方法
            keyProperty="":告诉mybatis我要将获得到的自动增长的值赋给谁
       -->
      <insert id="insertEmployee" useGeneratedKeys="true"  keyProperty="id">
            INSERT INTO mybatis_0325.t_employee(empname, gender, email)
            VALUE(#{empName}, #{gender}, #{email})
      </insert>

对于一些不能使用自增长的数据库:

<!-- 在对于不能使用自增属性的数据库的时候可以这样 -->
      <insert id="insertEmployee2">
            <!-- 查询主键
                  order="BEFORE":before就是在核心sql语句执行前先进行查询    after就是之后再执行
                  在核心sql语句执行之一个sql先查到id;将查到的id赋给JavaBean的哪一个属性
                  
                  selectKey order="BEFORE" resultType="integer"  keyProperty="id"
                  再核心sql执行之前我创建一个integer类型的id来存增长的id
             -->
            <selectKey order="BEFORE" resultType="integer"  keyProperty="id">
                  select max(id)+1 from t_employee
            </selectKey>
            INSERT INTO mybatis_0325.t_employee(id,empname, gender,  email)
            VALUE(#{id}, #{empName}, #{gender}, #{email})
      </insert>

2.查标签

<!--
            查询传参到底能传那些
       -->
      <!-- public Employee getEmpById(Integer id); -->
      <select id="getEmpById" resultType="com.neu.bean.Employee">
            select * from t_employee where id = #{id}
      </select>
      
      <!-- public Employee getEmpByIdAndName(Integer id, String  empName); -->
      <!--
            select * from t_employee where id = #{id} and empname =  #{empName}
            
            Caused by: BindingException:
            Parameter 'id' not found. Available parameters are [0, 1,  param1, param2]
       -->
      <select id="getEmpByIdAndName" resultType="com.neu.bean.Employee">
            <!-- select * from t_employee where id = #{param1} and  empname = #{param2} -->
            select * from t_employee where id = #{id} and empname =  #{empName}
      </select>
      
      <!-- public Employee getEmployeeByIdAndName(Map<String, Object>  map); -->
      <select id="getEmployeeByIdAndName"  resultType="com.neu.bean.Employee">
            select * from t_employee where id = #{id} and empname =  #{empName}
      </select>
现象:
              1)单个参数:
                                基本类型:
                                      取值:#{随便写}
                                      传入pojo
              2)多个参数:
                          1.    public Employee getEmpByIdAndName(Integer id, String empName)
                                取值:#{参数名}无效了;
                                可用:0,1(参数的索引)或者param1,param2(第几个参数paramN)
                                原因:只要传入了多个参数;mybatis会自动地将这些参数封装在一个map中;
                                         而封装使用的key就是参数的索引和参数的第几个标识
                                      Map<String, Object> map = new HashMap<>();
                                      map.put("1",传入的值);   map.put("2",传入的值);
                                      #{key}就是从这个map中取值;
                                      
                          2.    @Param(""):为参数指定key;命名参数,我们以后也推荐这么做
                                我们可以告诉mybatis,封装参数map的时候别乱来,我们可以指定key
                                public Employee getEmpByIdAndName(@Param("id")Integer id, @Param("empName")String empName);
                                      
              3)传入了map:将多个要使用的参数封装起来
                                取值:#{key}
                                EmployeeDao:
                                                  public Employee getEmployeeByIdAndName(Map<String, Object> map);
                                MyBatisTest:
                                                  Map<String, Object> map = new HashMap<String, Object>();
                                                  map.put("id", 1);
                                                  map.put("empName", "admin");
                                                  Employee mapEmployee = employeeDao.getEmployeeByIdAndName(map);
              
              4)传入了pojo(JavaBean):
                                取值:#{pojo的属性名}
                                
                                参数内传入的是Employee对象
                                Employee getEmpByIdAndLastName(Employee emp);
                                select * from t_employee where id = #{id} and empname = #{empName}
                                
                                
                                
              多个参数:自动封装map
              method01(@Param("id")Integer id, String empName, Employee employee);
              Integer id -> #{id}
              String empName -> #{param2}
              Employee employee(取出这个对象里面的email) -> #{param3.email}
                                
              无论传入什么参数都要能正确的取值:
                    #{key/属性名}
  
              ①#{key}取值得时候可以设置一些规则;     
                    #{id, jdbcType=INEGER};
                    javaType(java类型), jdbcType(jdbc类型), mode(数据库存储过程), numericScale(保留几位小数点), resultMap(结果集), typeHandler, jdbcTypeName,expression
                    
                    只有jdbcType才可能是需要被指定的;
                          默认不指定jdbcType;mysql没问题;oracle没问题
                          万一传入的数据时null;mysql没问题,【oracle没办法了,他不知道是什么类型】
  
        
        实际上mybatis中,两种取值方式:
              #{属性名}:是参数预编译的方式,参数的位置都是用?替代,参数后来都是预编译设置进去的;安全,不会出现sql注入问题
              ${属性名}:不是参数预编译,而是直接和sql语句进行拼串;不安全
                    //id=1 or 1 = 1 or and empname=
                    传入一个'1 or 1 = 1 or'
                    
                    有:sql语句只有此参数位置是支持预编译的
                    log_2017_12、log_2018_1;
                    select * from log_2018_1 where id = ? and empname = ?
                    
                    例子:
                          map.put("tableName", "t_employee");
                          select * from ${tableName} where id = #{id} and empname = #{empName}
                    
              一般都是使用#{};安全
              在不在支持参数预编译的位置要进行取值就只用${};
              
              id = #{id} and empname = #{empName}:
              select * from t_employee where id = ? and empname = ?
              
              id = ${id} and empname = #{empName}:
              select * from t_employee where id = 1 and empname = ?

查询方法内部是list集合:

sql映射文件:
      <!-- public List<Employee> getAllEmps(); -->
      <!-- resultType:如果返回的是集合,那么就写集合里面元素的类型 -->
      <select id="getAllEmps" resultType="com.neu.bean.Employee">
            select * from t_employee
      </select>


      测试文件:
      @Test
      public void test03() {
            SqlSession openSession = sqlSessionFactory.openSession();
            try{
                  EmployeeDao employeeDao =  openSession.getMapper(EmployeeDao.class);
                  List<Employee> list = employeeDao.getAllEmps();
                  for(Employee emp : list){
                        System.out.println(emp);
                  }
            }finally{
                  openSession.close();
            }
      }
      

查询方法返回到map集合:

查询单个放到map中:
dao类:
       /**
       * id empname           gender            email       login_account
       * 1  admin         0         admin@qq.com                  a
       * @param id
       * @return
       *
       * 列名作为key,值作为value
       */
      public Map<String, Object> getEmpByIdReturnMap(Integer id);



     xml文件:
      <!-- 查询返回一个map -->
      <!-- public Map<String, Object> getEmpByIdReturnMap(Integer id);  -->
      <select id="getEmpByIdReturnMap" resultType="map">
            select * from t_employee where id = #{id}
      </select>



     测试类:
//                查询单条封装map
//                Map<String, Object> map =  employeeDao.getEmpByIdReturnMap(1);
//                System.out.println(map);
查询多个方到map中


      dao类:
      /**
       * key就是这个记录的主键
       * value就是这条记录封装好的对象
       * @return
       *
       * @MapKey("id")
       * 把查处的记录的id得值作为key封装这个map
       */
      @MapKey("id")
      public Map<Integer, Employee> getAllEmpByIdReturnMap();



      xml文件:
      <!-- 查询多个返回一个map,查询多个的情况下,集合里面写元素的类型 -->
      <!-- public Map<Integer, Employee> getAllEmpByIdReturnMap(); -->
      <select id="getAllEmpByIdReturnMap"  resultType="com.neu.bean.Employee">
            select * from t_employee
      </select>



      测试类:
            //查询多条记录封装map
                  Map<Integer, Employee> map =  employeeDao.getAllEmpByIdReturnMap();
                  System.out.println(map);
                  Employee employee = map.get(1);
                  Integer id = employee.getId();
                  System.out.println(id);

resultMap自定义封装规则

 sql映射文件:

  <mapper namespace="com.neu.dao.CatDao">
      <!-- public Cat getCatById(Integer id);
            resultType="com.neu.bean.Cat":使用默认规则;属性列名一一对应
            resultMap="mycat":查出数据封装结果的时候,使用mycat自定义规则
       -->
      <select id="getCatById" resultMap="mycat" >
            <!-- select id, cname name, cAge age, cgender gender from  t_cat where id = #{id} -->
            select * from t_cat where id = #{id}
      </select>
      
      <!--
            自定义结果集(resultMap):自己定义每一列数据和JavaBean得映射规则
            
            type="":指定为哪个JavaBean自定义封装规则
            id="":唯一标识;让别名在后面引用
            
            id    cName cAge cgender
            1     加菲猫 12          0
       -->
      <resultMap type="com.neu.bean.Cat" id="mycat">
            <!--
                  id:指定主键列的对应规则
                  column:指定哪一个是主键列
                  property:指定cat得哪个属性封装id这一列数据
             -->
            <id property="id" column="id"/>
            <!-- 普通列 -->
            <result property="name" column="cName"/>
            <result property="age" column="cAge"/>
            <result property="gender" column="cgender"/>
      </resultMap>
      
  </mapper>


Test测试文件:
    /**
       * 默认mybatis自动封装结果集
       * 1.按照列名和属性名一一对应(不区分大小写);
       * 2.如果不一一对应:
       *                1.开启驼峰命名法(满足驼峰命名规则  aaa_bbb    aaaBbb)
       *                2.起别名
       */
      @Test
      public void test04() {
            SqlSession openSession = sqlSessionFactory.openSession();
            try{
                  CatDao catDao = openSession.getMapper(CatDao.class);
                  Cat cat = catDao.getCatById(1);
                  System.out.println(cat);
            }finally{
                  openSession.close();
            }
      }
            

级联属性的方式查询出数据:

(当前类中有一个属性是引用外部类的)


  public class Key{    
      private Integer id;     //钥匙id
      private String keyName; //钥匙名
      private Lock lock;      //当前钥匙能开哪个锁
  }

  public class Lock {
      private Integer id;     //锁id
      private String lockName;      //锁名
  }




xml文件:

   <mapper namespace="com.neu.dao.KeyDao">
      <!--
            private Integer id;     //钥匙id
            private String keyName; //钥匙名
            private Lock lock;      //当前钥匙能开哪个锁
            
            id keyname lockid lid lockName
       -->
  
      <!-- public Key getKeyById(Integer id); -->
      <select id="getKeyById" resultMap="myKey">
            SELECT k.id, k.keyName, k.lockId, l.id lid, l.lockName FROM  t_key k
                  LEFT JOIN t_lock l
                  ON k.lockId = l.id
                  WHERE k.id = #{id}
      </select>
      
      <!-- 自定义封装规则:使用级联属性封装出联合查询出的结果 -->
      <!-- <resultMap type="com.neu.bean.Key" id="myKey">
            <id property="id" column="id"/>
            <result property="keyName" column="keyname"/>
            <result property="lock.id" column="lid"/>
            <result property="lock.lockName" column="lockName"/>
      </resultMap> -->
      
      <!-- mybatis推荐的<association property=""></association> -->
      <resultMap type="com.neu.bean.Key" id="myKey">
            <id property="id" column="id"/>
            <result property="keyName" column="keyname"/>
            <!-- 接下来的属性是一个对象,自定义这个对象得封装规则;使用association;表示联合了一个对象 -->
            <!-- javaType:指定这个属性得类型 -->
            <!-- property:写的是JavaBean里的属性; column:写的是你对应数据库要查的字段 -->
            <association property="lock" javaType="com.neu.bean.Lock">
                  <!-- 定义lock属性对应的这个Lock对象如何封装 -->
                  <id property="id" column="lid"/>
                  <result property="lockName" column="lockName"/>
            </association>
      </resultMap>
  </mapper>





Test类:

/**
       * 联合查询情况下
       * 1.使用级联属性封装联合查询后的所有结果
       */
      @Test
      public void test05() {
            SqlSession openSession = sqlSessionFactory.openSession();
            try{
                  KeyDao keyDao = openSession.getMapper(KeyDao.class);
                  Key key = keyDao.getKeyById(2);
                  System.out.println(key);
            }finally{
                  openSession.close();
            }
      }
(当前类中有一个属性是List集合,List集合的类型是外部类)

  public class Lock {
      private Integer id;     //锁id
      private String lockName;      //锁名
      
      //查询锁子的时候把所有的钥匙也查出来
      private List<Key> keys;
      //1-1关联;1-多关联;多-多关联
      //一个key开一把lock;
      //从lock来看key;1-多
      //从key表看lock:多-1
      //多-多:
      //student表 teacher表
      //1-n; n-1; n-n ;外键应该放到那个表
      //1-n:外键一定放在多的一端
      //n-n:中间表存储对应关系

 }


  public class Key{    
      private Integer id;     //钥匙id
      private String keyName; //钥匙名
      private Lock lock;      //当前钥匙能开哪个锁
  }






xml文件:

  <mapper namespace="com.neu.dao.LockDao">
      <!-- public Lock getLockById(Integer id); -->
      <select id="getLockById" resultMap="myLock">
            SELECT l.*, k.id kid, k.keyName FROM t_lock l
                  LEFT JOIN t_key k
                  ON l.id = k.lockId
                  WHERE l.id = #{id}
      </select>
      
      <resultMap type="com.neu.bean.Lock" id="myLock">
            <id property="id" column="id"/>
            <result property="lockName" column="lockName"/>
            
            <!-- collection定义集合元素的封装
                  property:指定哪个属性是集合属性
                  javaType:指定对象类型(association)
                  ofType:指定集合元素的类型
             -->
            <collection property="keys" ofType="com.neu.bean.Key">
                  <!-- 标签体中,指定集合中这个元素的封装规则 -->
                  <id property="id" column="kid"/>
                  <result property="keyName" column="keyName"/>
            </collection>
      </resultMap>
  </mapper>





Test文件:

    @Test
      public void test06() {
            SqlSession openSession = sqlSessionFactory.openSession();
            try{
                  LockDao lockDao =  openSession.getMapper(LockDao.class);
                  Lock lock = lockDao.getLockById(3);
                  System.out.println(lock);
                  List<Key> keys = lock.getKeys();
                  for(Key all : keys){
                        System.out.println("Lock下的所有锁子" + all);
                  }
                  
            }finally{
                  openSession.close();
            }
      }

(分布查询)

KeyDao.xml


      <!-- public Key getKeyByIdSimple(Integer id); -->
      <select id="getKeyByIdSimple" resultMap="myKey02">
            select * from t_key where id = #{id}
      </select>
      
      <resultMap type="com.neu.bean.Key" id="myKey02">
            <id property="id" column="id"/>
            <result property="keyName" column="keyName"/>
            <!--
                  告诉mybatis自己去调用一个查询查锁子
                  select="":指定一个查询sql的唯一表示;mybatis自动调用指定的sql,将查处的lock封装进来
                  public Lock getLockByIdSimple(Integer id);需要传入锁子id
                  告诉mybatis把那一列的值传递过去
                  column:指定将哪一个数据传递过去
             -->
            <association property="lock"
             select="com.neu.dao.LockDa.getLockByIdSimple"
             column="lockid"></association>
      </resultMap>


LockDao.xml
      <!-- public Lock getLockByIdSimple(Integer id); -->
      <select id="getLockByIdSimple" resultType="com.neu.bean.Lock">
            select * from t_lock where id = #{id}
      </select>


Test类
      
      /**
       * 分步查询:
       *    0)、查询要是的时候顺便查出锁子;
       *    1)、Key key = keyDao.getKeyById(1);
       *    2)、Lock lock = lockDao.getLockById(1);
       */
      @Test
      public void test07(){
            SqlSession openSession = sqlSessionFactory.openSession();
            try{
                  KeyDao keyDao = openSession.getMapper(KeyDao.class);
                  Key key = keyDao.getKeyByIdSimple(2);
                  System.out.println(key);
            }finally{
                  openSession.close();
            }
      }

(分布加载中的按需加载和延迟加载)



   两个sql映射文件中不变

      @Test
      public void test07() throws InterruptedException{
            SqlSession openSession = sqlSessionFactory.openSession();
            try{
                  KeyDao keyDao = openSession.getMapper(KeyDao.class);
                  Key key = keyDao.getKeyByIdSimple(1);
                  //严重性能
                  System.out.println(key);
                  //按需加载;需要的时候再去查询;全局开启按需加载策略
                  //延迟加载:不着急加载(查询对象)
                  //假设我现在查钥匙查完后她睡了,然后过一会他想起来了,起来查了
                  Thread.sleep(3000);
                  String lock = key.getLock().getLockName();
                  System.out.println(lock);
                  
            }finally{
                  openSession.close();
            }
      }

mybatis—config.xml多一部分
在这里插入图片描述

在这里插入图片描述

 <!-- 如果有多个列就是用
                  column="{id=id}"
                  key1 = 列名, key2 = 列名
              -->



fetchType="lazy"全局加载懒加载
fetchType="eager"全局加载不懒加载
他只能写在collection和association标签里





<collection property="keys"
             select="com.neu.dao.KeyDao.getKeysByLockId(Integer)"
             column="id" fetchType="lazy"></collection>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值