超详细—狂神Mybatis笔记

mybatis中文手册:mybatis – MyBatis 3 | 简介

思路:搭建环境,导入Mybatis—>编写代码—>测试

1、搭建环境

1.1 创建数据库mybatis和user表

CREATE DATABASE `mybatis`;
USE `mybatis`;
CREATE TABLE `user`(
	`id` INT(20) NOT NULL, 
	`name` VARCHAR(30) DEFAULT NULL, 
	`pwd` VARCHAR(30) DEFAULT NULL, 
	PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8;


INSERT INTO `user`(`id`,`name`,`pwd`) VALUES
(1,'狂神','13456'),
(2,'张三','12345'),
(3,'李四','12346');

  超详细—狂神Mybatis笔记_第1张图片

1.2新建java项目

  • 注意因为我们要用maven仓库,所以要创建maven项目超详细—狂神Mybatis笔记_第2张图片
  • groupid和artifactId被统称为“坐标”是为了保证项目唯一性而提出的,如果你要把你项目弄到maven本地仓库去,你想要找到你的项目就必须根据这两个id去查找。
    groupId和artifactId是maven管理项目包时用作区分的字段,就像是地图上的坐标。
    artifactId:artifactId一般是项目名或者模块名。
    groupId:groupId分为几个字段,例如cn.com.fullstack,前面的com叫【域】,后面的是你自己起的域名。
    groupId一般分为多个段,这里我只说两段,第一段为域,第二段为公司名称。域又分为org、com、cn等等许多,其中org为非营利组织,com为商业组织。举个apache公司的tomcat项目例子:这个项目的groupId是org.apache,它的域是org(因为tomcat是非营利项目),公司名称是apache,artigactId是tomcat。

超详细—狂神Mybatis笔记_第3张图片

  •  注意这里一定要用自己安装的maven路径。
  • 一开始IDEA会默认使用Bundled(Maven 3),这个是直接把下载的jar包放在c盘的。超详细—狂神Mybatis笔记_第4张图片
  •  删除src文件

超详细—狂神Mybatis笔记_第5张图片

  • 新建一个Module,注意新建这个module仍然选Maven项目,我在这里命名为mybatis-01

超详细—狂神Mybatis笔记_第6张图片

 1.3 导入依赖

  •  在pom.xml中导入以下依赖,如框A所示。
  • 导入依赖后,在框B中会提示是否要import,点击import changes。然后就可以在IDEA右侧的Maven Projects中的Dependencies中发现引入了这些依赖。
  • 超详细—狂神Mybatis笔记_第7张图片
  • 超详细—狂神Mybatis笔记_第8张图片
        
        
    
            
            
                mysql
                mysql-connector-java
                5.1.46
            
    
            
            
                org.mybatis
                mybatis
                3.5.2
            
    
            
            
                junit
                junit
                4.12
            
    
        

 什么是dependency?

  • 用了Maven,所需的JAR包就不能再像往常一样,自己找到并下载下来,用IDE导进去就完事了,Maven用了一个项目依赖 (Dependency)的概念,用俗话说,就是我的项目需要用你这个jar包,就称之为我的项目依赖你这个包,换句话说,你这个JAR包就是我这个项目的Dependency。
  • 就比如我已经在github中下载了mybatis,但是我在我的maven项目中并没有用我下载的这个mybatis的jar包,而是通过添加依赖的方式,让maven帮我下载。超详细—狂神Mybatis笔记_第9张图片

删除src,自己新建一个module的好处?

  • 在新建的mybatis-01的module中的pom.xml里会自动创建一个,表明此module的父工程为com.hanT.Mybatis。因此在父工程pom.xml中导入的依赖就不用在子module中导入了。

超详细—狂神Mybatis笔记_第10张图片

  •  同时在父工程的pom.xml中会生成一个:代表它的子module

超详细—狂神Mybatis笔记_第11张图片

 1.4  编写mybatis核心配置文件

  •  来自:mybatis中文文档(这个文档的网页已收藏,重要!)超详细—狂神Mybatis笔记_第12张图片
  •  在module :mybatis01-src-main-resource中创建一个file文件:mybatis-config.xml
  • 将黄框内复制进这个xml文件,删除,并修改(填写)四个标签(跟数据库相关的):
                
                
                
                
  • 改为:
                
                
                
                
  • 这里的driver为驱动,username和password为数据库的账户和密码。

1.5 连接MySQL数据库中的database:mybatis

  • 点击IDEA右侧的DataBase后点击这个 + 号

超详细—狂神Mybatis笔记_第13张图片

  •  选择Data Source — MySQL,进入后输入MySQL的账户名和密码,点击Test Connection。

超详细—狂神Mybatis笔记_第14张图片

  •  successful后点击Schemas
  •  选择所需的mybatis这个database后点OK超详细—狂神Mybatis笔记_第15张图片

 

1.6 编写mybatis工具类

  • 先在mybatis01这个module的src-main-java中new 一个package:com.hanT.utils
  • 在utils这个子包中new一个class:命名为mybatisUtils
public class mybatisUtils {

    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            String resource = "mybatis-config.xml"; //对应resources下的mybatis-config.xml
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        return sqlSession;
    }

}

2、编写代码 

超详细—狂神Mybatis笔记_第16张图片

  •  User为实体类
public class User {
    //注意这三个属性一定要与数据库中user表的字段一致
    private int id;
    private String name;
    private String pwd;

    public User(){

    }

    public User(int id, String name, String pwd) {
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }
}
  • UserDao接口
public interface UserDao {
    public List getUserList();

}
  • UserMapper.xml:相当于替代了UserDao接口的实现类





    
    

3、测试代码以及可能会遇到的问题

  • 在src.test下创建com.hanT.UserDaoTest进行测试
public class UserDaoTest {
    @Test
    public void Test(){

        //第一步:获得SqlSession对象
        SqlSession sqlSession = mybatisUtils.getSqlSession();

        //第二步:执行sql语句,通过UserDao.class获得其对应的实现类的对象mapper
        UserDao mapper = sqlSession.getMapper(UserDao.class);

        //第三步:通过mapper执行其getUserList()方法
        List userList = mapper.getUserList();

        for(User user:userList){
            System.out.println(user);
        }
        
        sqlSession.close();//用完后记者关闭session
    }
}

错误1:绑定异常

超详细—狂神Mybatis笔记_第17张图片

  • 原因是UserMapper.xml中的没有在核心配置文件mybatis-config.xml中绑定。
  • 解决办法是在核心配置文件mybatis-config.xml中加入以下代码:
    
        
    

错误2:初始化异常

超详细—狂神Mybatis笔记_第18张图片

  • 原因是无法识别到com/hanT/dao/UserMapper.xml这个配置文件
  • 解决办法是,在project工程和mybatis01模块的pom.xml文件都加上以下代码:
    
        
            
                src/main/java
                
                    **/*.xml
                    **/*.properties
                
                false
            

        
            src/main/resources
            
                **/*.xml
                **/*.properties
            
            false
        

        
    

4、mybatis实现CRUD(增删改查)

4.1 select * from mybatis.user where id = #{id};
  •  select标签中各个属性的含义:
id:对应接口中的方法名
resultType:查询语句返回结果集的返回值类型(注意就算是以集合形式返回值,也要写集合中存储的具体类型)
parameterType:参数类型,即查询参数#{id}中id的类型。

测试:

    @Test
    public void Test2(){
        SqlSession sqlSession = mybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        User user = mapper.getUserById(1);
        System.out.println(user);
        sqlSession.close();//用完后记者关闭session

    }

4.2  

  • 首先在UserDao接口中添加新方法:
    //3、插入新用户
    void addUser(User user);
  • 在UserMapper.xml中添加标签:
    
        insert into mybatis.user (id, name, pwd) values(#{id},#{name},#{pwd});
    

这段sql中,mybatis框架会自动根据传入的User对象的id name pwd属性值,匹配#{}中的属性,这个设计很方便。 

  • 测试:
    @Test
    public void Test3(){
        SqlSession sqlSession = mybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        mapper.addUser(new User(4,"hantong","125478"));

        sqlSession.commit();//提交事务操作**

        sqlSession.close();
    }

一定要注意的是:增、删、改要先提交事务再关闭session。也就是说要先

sqlSession.commit();

否则不会提交成功,user表中会看不到新插入的记录。

4.3 

  •  首先在UserDao接口中添加新方法:
    //3、插入新用户
    void addUser(User user);
  • 在UserMapper.xml中添加标签:
    
        update mybatis.user set name=#{name},pwd=#{pwd} where id = #{id};
    
update mybatis.user set name=#{name},pwd=#{pwd} where id = #{id};

这段sql中,mybatis框架会自动根据传入的User对象的id name pwd属性值,匹配#{}中的属性,这个设计很方便。

  • 测试:
    @Test
    public void Test4(){
        SqlSession sqlSession = mybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        mapper.updateUser(new User(4,"韩统","123456"));

        sqlSession.commit();//提交事务操作**

        sqlSession.close();
    }

5、体会java反射在mybatis框架中的作用

5.1 由类名的字符串反射得到该类的class对象

//反射代码
Class clazz = Class.forName("com.hanT.pojo.User");


    
  • 在  和resultType="com.hanT.pojo.User"中,框架就是通过反射,把类名的字符串反射得到该类的class对象。

5.2 由方法名和属性名的字符串反射得到此方法、属性的对象

//反射代码
Method method = clazz.getDeclaredMethod("getUserById");
Field field = clazz.getDeclaredField("id");


    
  • 而且反射的牛逼之处在于私有的属性和方法一样可以获取到,例如User的id等属性都是私有的

6、mybatis配置优化 

6.1 mybatis配置之属性优化 

  •  在原工程Mybatis下新建一个新module:mybatis02
  • 并把mybatis01的文件复制到mybatis02中

目标:优化核心配置文件中的这一部分:

超详细—狂神Mybatis笔记_第20张图片

  •  在resource目录下新建配置文件db.properties
  • 注意在properties文件下要把url的转译符号   amp; 去掉。

超详细—狂神Mybatis笔记_第21张图片

  •  在 核心配置文件标签下引入:代表在核心配置文件中引入该外部配置文件。然后修改第二个黄色框内的内容。

  • 注意在中的各个子标签是必须按顺序的!!
  • 中标签的顺序为:
    1 properties
    2 settintg
    3 typeAliases
    4 typeHandlers
    5 objectFactory
    6 objectWrapperFactory
    7 reflectorFactory
    8 plugins
    9 environments
    10 databaseIdProvider
    11 mappers

超详细—狂神Mybatis笔记_第22张图片

  • ${}不是#{},我就是因为写错导致报错:找不到driver

 6.2 mybatis配置之别名优化 

类型别名(:类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。

  • 在核心配置文件中加入标签:这里表示为全限定名com.hanT.pojo.User起别名为User
    
        
    
  • 为com.hanT.pojo.User起别名后,在UserMapper.xml文件中的黄色框内就可以直接使用"User"

超详细—狂神Mybatis笔记_第23张图片

还可以通过扫描包的方式来起别名:

超详细—狂神Mybatis笔记_第24张图片超详细—狂神Mybatis笔记_第25张图片

 

7、映射器(

        我们现在就要来定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 file:/// 形式的 URL),或类名和包名等。例如下面四种方式:



  
  
  


  
  
  


  
  
  


  
  • 目前使用过的是第一种方式:下图 

超详细—狂神Mybatis笔记_第26张图片

简而言之,在这里的作用就是将UserDao和UserMapper.xml文件绑定到一起。

8、作用域(Scope)和生命周期

执行流程:

超详细—狂神Mybatis笔记_第27张图片

  • 作用域和生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发问题。

SqlSessionFactoryBuilder:

  • 一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。

SqlSessionFactory:

  • SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。
  • 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式,保证全局只有一份变量。
  • 说白了SqlSessionFactory可以看做一个连接池。

SqlSession:

  • 每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。
  • sqlSession.close();
    这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。 

超详细—狂神Mybatis笔记_第28张图片

  1. 全局只能有一个SqlSessionFactory
  2. 可以创建多个SqlSession(比如每个线程创建一个等)
  3. 同一个SqlSession可以创建多个Mapper,每个Mapper用来执行一个数据库语句

 

9、ResultMap(结果集映射)

——解决类的属性名和数据库字段名不一致的问题

之前属性名和数据库字段名要求必须保持一致:

超详细—狂神Mybatis笔记_第29张图片

超详细—狂神Mybatis笔记_第30张图片

  • 假如现在User的属性名改为:其中UserName和password与数据库中字段不一致。

超详细—狂神Mybatis笔记_第31张图片

  • 此时就需要修改UserMapper.xml文件
  • 原先的UserMapper.xml文件 select * from mybatis.user where id = #{id};
    •  修改后:
        
        
            
            
            
        
    
        

    超详细—狂神Mybatis笔记_第32张图片

    1、需要新增标签
    2、的属性id与