Mybatis的深入

Mybatis的深入

目录

课程介绍

  • 回顾mybatis的自定义再分析和环境搭建+完善基于注解的mybatis
  • mybatis的CRUD(基于代理dao的方式)
  • mybatis的参数深入及结果集的深入
  • mybatis基于传统dao的编写方式(编写dao的实现类)--了解
  • mybatis中主配置文件的介绍(SqlMapConfig.xml)
    • properties标签
    • typeAliases标签
    • mappers标签

配置基于dao代理的CRUD

配置基于dao代理的CRUD很简单,自己不用写dao的实现类,只需要配置两个地方就可以使用dao进行CRUD操作,前提是mybatis的主配置文件已经写好,这个可以看day01环境配置那里。

  1. dao接口添加方法
  2. dao接口对应的映射配置文件添加方法对应的sql语句,还要指明对应方法的参数类型,返回值类型

1. 保存

  • IUserDao接口添加方法 void saveUser(User user);

  • IUserDao.xml添加insert标签:

    • insertid方法名

    • insert标签中需要添加参数类型parameterType,因为该方法有参数传入

    • parameterType属性:如果是自己定义的类,需要全限定类名

    • sql语句需要参数,使用#{value}从形参中按照变量名获取,====================

    • <!--指定命名空间为某个接口,后面不再重复出现-->
      <mapper namespace="com.chajiu.dao.IUserDao" > 
          <!--保存user-->
          <insert id="saveUser" parameterType="com.chajiu.domain.User">  
                insert into user(name,address,sex,birthday) values(#{name},#{address},#{sex},#{birthday});
          </insert>
      </mapper>
      

2. 更新

  • void updateUser(User user);
    
  • <!--更新-->
        <update id="updateUser" parameterType="com.chajiu.domain.User">
            update user set name=#{name},address=#{address},sex=#{sex},birthday=#{birthday} where id=#{id};
        </update>
    

3. 删除

  • void deleteUser(int id);
    
  • 需要提供int id,就给了Integer,这里只要是能表示出int类型的都可以,包括intINT等。

  • <!--删除-->
        <delete id="deleteUser" parameterType="Integer">
            delete from user where id=#{uid};
        </delete>
    

4. 根据id查找用户

  • /**
     * 根据id查找user
     * @param id
     * @return
     */
    User findById(int id);
    
  • 这里方法有返回值,所以要用 resultType指明返回类型,自定义对象需要全限定类名,String之类基本数据类型只要写出那几个字母即可,如 stringintdouble即可,没有严格要求,后面会讲为什么。

  • 同时如果只有一个参数,且是基本类型,则 #{value}中的value随便写都可以,不用和形参名对应

  • <!--根据id查找用户-->
        <select id="findById" parameterType="Integer" resultType="com.chajiu.domain.User">
            select * from user where id = #{id};
        </select>
    

5. 返回List的查询所有用户

  • /**
     * 查询所有user
     * @return
     */
    List<User> findAll();
    
  • 这里返回值 resultType指明为com.chajiu.domain.User,即泛型的实际类型即可。

  • <!--查询所有user-->
    <select id="findAll" resultType="com.chajiu.domain.User">
        select * from user
    </select>
    

6. 模糊查找

  • /**
     * 根据名字模糊查询
     * @param name
     * @return
     */
    List<User> findByName(String name);
    
  • 此处把 '%王%'句子放在了形参里,故调用时需要提供参数为:%王%

  • <!--根据名字模糊查询-->
    <select id="findByName" parameterType="String" resultType="com.chajiu.domain.User">
        select * from user where name like #{name};
    </select>
    

接下来就可以进行测试。

7. 返回一行一列:查询用户总数

  • /**
     * 查询总数
     * @return
     */
    int findTotal();
    
  • 没啥特别,只要指明返回类型即可。

  • <!--查询总数-->
    <select id="findTotal" resultType="int">
        select count(*) from user;
    </select>
    

mybatis dao测试

使用dao需要六步:

  //1. 读取配置文件,生成字节输入流
      
  //2. 获取SqlSessionFactory对象
       
  //3. 获取SqlSession对象
       
  //4. 获取dao的代理对象
  
  //5. 使用代理对象执行方法
  
  //6. 释放资源

如果在每个方法中都写上这些步骤,显得繁琐。因此把重复的代码抽出包装成方法。

@Before注解的方法在 @Test方法执行前执行, @After注解的方法在其之后执行。故正好用于创建 SqlSession和释放资源。(这些注解在junit包中)

package com.chajiu.test;

import com.chajiu.dao.IUserDao;
import com.chajiu.domain.User;
import org.apache.ibatis.io.Resources; //注意Resources导包
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

public class MybatisTest {
    //将测试方法中需要用到的对象声明为成员变量。
    private InputStream in; //未来要关闭
    private SqlSession session;//未来要关闭
    private IUserDao userDao; //未来要调用接口方法

    @Before//用于在测试方法前执行
    public void init() throws IOException {
        //1. 读取配置文件,生成字节输入流
        in= Resources.getResourceAsStream("SqlMapConfig.xml");
        //2. 获取SqlSessionFactory对象
        SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
        SqlSessionFactory factory=builder.build(in);
        //3. 获取SqlSession对象
        session=factory.openSession();
        //4. 获取dao的代理对象
        userDao=session.getMapper(IUserDao.class);
    }

    @After//用于在测试方法执行后执行
    public void destroy() throws IOException {
        //5.设置手动提交事务
        session.commit();

        //6. 关闭
        session.close();
        in.close();
    }


    
    //查询所有
    @Test
    public void testFindAll(){

        //5. 执行查询所有
        List<User> users=userDao.findAll();
        for (User user:users) {
            System.out.println(user);
        }

    }

    //保存
    @Test
    public void testSaveUser(){
        User user=new User();
        user.setName("mybatis");
        user.setAddress("北京市顺义区");
        user.setSex("男");
        user.setBirthday(new Date());

        System.out.println(user);
        //5. 执行保存
        userDao.saveUser(user);
        System.out.println(user);
    }

    //更新
    @Test
    public void testupdateUser(){
        User user=new User();
        user.setName("mybatis_update");
        user.setAddress("北京市顺义区");
        user.setSex("男");
        user.setBirthday(new Date());
        user.setId(4);

        userDao.updateUser(user);
    }

    //删除
    @Test
    public void testDeleteUser(){
        userDao.deleteUser(5);
    }

    //根据id找user
    @Test
    public void testFindById(){
        User user=userDao.findById(2);
        System.out.println(user);
    }

    //根据名字模糊查询
    @Test
    public void testFindByName(){
        List<User> users=userDao.findByName("%y%");
        for(User user:users){
            System.out.println(user);
        }
    }

    //查询总数
    @Test
    public void testFindTotal(){
        System.out.println(userDao.findTotal());
    }

}


mybatis替我们做了什么

  • 读取xml配置文件
  • 注册驱动
  • 数据库的连接
  • 事务的开启(SqlSession还是要先自己构造出来)
  • 创建dao接口的代理对象(用SqlSession)
  • 封装查询结果到对象中

mybatis参数详解

1. parameterType 输入参数类型

可以传递:

  • 简单参数

  • 自定义pojo类型

    • 使用#{}或者${}指定属性名称=======是的,${}也可以
  • 包装类型

    • 若包装了多个自定义pojo对象,如何访问其中的属性?

      #{value}视为parameterType的类中的属性,有类QueryVo包含User

      public class QueryVo {
          private User user;
          //getter 
          //setter
      }
      
    • 则通过#{user.name}访问user的name属性。即视为拼在输入类型后面。

     <!--根据包装对象查询-->
     <select id="findByVo" parameterType="com.chajiu.domain.QueryVo" resultType="com.chajiu.domain.User">
         select * from user where name like #{user.name};
     </select>
    

注意:sql语句中的#{value}value字段必须和实体类中的属性名称对应!!!

OGNL表达式:

  • Object Graphic Navigation Language 对象 图 导航 语言
  • 它是通过对象的取值方法来获取数据,在写法上把get省略了
  • 比如:获取用户名称
    • 类中:user.getUserName()
    • OGNL:user.userName
  • mybatis中为什么不用user.userName,而是直接userName呢?
    • 因为在parameterType中已经指明了属性所属的类,因此不用写对象名

2. resultType 结果类型

  • 输出简单类型

  • 输出pojo对象

    • mybatis如何封装查询结果到pojo呢?

    • 第一种方法:表字段名和pojo属性名对应,自动匹配。不对应的匹配不上为null

    • 第二种方法:表字段名和pojo属性名不对应时,

      • 改sql语句,别的都不用改:

        • 优点:执行效率高
        select id as userId, name as userName, sex as userSex, address as userAddress, birthday as userBirthday from user
        
      • 或者手动配置查询结果字段和实体类属性的映射关系,返回结果改成resultMap

        • 优点:方便开发
          <resultMap id="userMap" type="com.chajiu.domain.User">
                <!--配置主键-->
                <id property="userId" column="id"></id>
                <!--配置非主键-->
                <result property="userName" column="name"></result>
                <result property="userSex" column="sex"></result>
                <result property="userAddress" column="address"></result>
                <result property="userBirthday" column="birthday"></result>
            </resultMap>
            <!--查询所有user-->
            <select id="findAll" resultMap="userMap">
                select * from user
            </select>
        
  • 输出pojo列表

3. properties

原本properties用于配置连接数据库的四个信息:

<dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/chajiu_mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="admin"/>
</dataSource>

现在可以用properties标签把property抽出来,原处property标签的value${name}指向上面的property:=======必须用 ${},不可用 #{}

<configuration>
    <!--添加-->
    <properties >
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/chajiu_mybatis"/>
        <property name="username" value="root"/>
        <property name="password" value="admin"/>
    </properties>
    
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                
                <!--修改-->
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
                
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="com/chajiu/dao/IUserDao.xml"></mapper>
    </mappers>
</configuration>

所以说,

可以在标签内部配置连接数据库的信息,也可以通过属性引用外部配置信息:

  • resource属性:常用

    • 用于指定配置文件的位置,按照类路径的写法写,并必须存在于类路径下
      • <properties resource="jdbcConfig.properties">
  • url属性:

    • 要求 按照url的写法写位置

    • URL:统一资源定位符,他可以唯一标识一个资源的位置

      写法:http://localhost:8080/mybatis_demo/demoServlet

      ​ 协议 主机 端口 URI

      • URI:统一资源标识符,在应用中唯一定位一个资源
    • 所以使用URL属性可以把配置文件放在任意目录,但是路径写为:

      • file:///C:/Users/Alice/IdeaProjects/jdbcConfig.properties
        
      • 使用协议:file://

      • 端口主机省略,故是file:///

    • <properties resource="file:///C:/Users/Alice/IdeaProjects/jdbcConfig.properties">

4. typeAliases标签

用于给实体类取别名,方便在parameterTyperesultType中使用,不用再写全限定类名了,这就是为什么String以及基本数据类型不用写全限定类名的原因,他已经默认配好了别名。

<!--给User类取user的别名-->
<typeAliases>
        <!--给com.chajiu.domain.User取别名user,不区分大小写,也就是说用的时候uSeR也可以-->
        <typeAlias type="com.chajiu.domain.User" alias="user"></typeAlias>
        <!--给一个包下全部类取别名,默认是类名,不区分大小写-->
        <package name="com.chajiu.domain"></package>
</typeAliases>

使用:凡是要指定全限定类名的地方都可以用,比如parameterTyperesultTyperesultMap中的type

5. package 标签

刚才typeAliases中用了package,这样这个包下的类自动有了别名。
在主配置文件的Mappers中,也可以用这个package标签,用于指定dao接口的包,写了这个就不用再写mapperresource以及class了,他会自己去找xml文件,方便开发。

    <mappers>
<!--        <mapper resource="com/chajiu/dao/IUserDao.xml"></mapper>-->
            <!--用于指定dao接口的包,写了这个就不用再写mapper、resource以及class了,他会自己去找xml文件-->
            <package name="com.chajiu.dao"/>
    </mappers>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352

推荐阅读更多精彩内容

  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,509评论 0 4
  • 1. Mybatis的介绍 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由ap...
    itzhouq的笔记阅读 660评论 0 5
  • 复习:课程复习: mybatis是什么?mybatis是一人持久层框架,mybatis是一个不完全的ORM框架。s...
    isuntong阅读 413评论 0 0
  • mybatis开发dao得方法 SqlSession使用范围 SqlSessionFactoryBuilder通过...
    isuntong阅读 400评论 0 0
  • Mybatis简介 MyBatis 是一个可以自定义SQL、存储过程和高级映射的持久层框架。MyBatis 摒除了...
    cuzz_阅读 974评论 1 2