欢迎您的访问
专注架构,Java,数据结构算法,Python技术分享

SSM第四讲 Mybatis原理及开发流程

一、MyBatis介绍

1.什么是MyBatis

MyBatis 本是apache的一个开源项目iBatis, 2010年 迁移到了google code,并且改名为MyBatis 。是一个基于Java的持久层ORM关系映射框架

MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手工设置参数以及抽取结果集(dao层零实现)。

MyBatis 使用简单的 XML 或注解来配置和映射基本体,将 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

中文官网:

链接

2.ORM关系映射

对象模型表示的对象映射到基于SQL 的关系模型数据库结构中去。这样,我们在具体的操作实体对象的时候,就不需要再去和复杂的SQL 语句打交道,只需简单的操作实体对象的属性和方法。

在这里插入图片描述

3.Mybatis配置流程图

在这里插入图片描述

Resources:资源类,用于读取总配置文件

SqlSessionFactoryBuilder:会话工厂构造类,通过读取的总配置文件构建会话工厂

SqlSessionFactory:会话工厂

SqlSession:会话,就是操作数据库的操作类

4. Mybatis的下载路径

https://github.com/mybatis/mybatis-3/releases

二. 开发流程及原理及

mybatis的 dao零实现操作数据库

-- 学生信息表
CREATE TABLE tb_student
(
stuId bigint NOT NULL AUTO_INCREMENT COMMENT '学生编号',
stuName varchar(50) COMMENT '学生名字',
stuAge int COMMENT '学生年龄',
stuPassword varchar(50) COMMENT '密码',
PRIMARY KEY (stu_id)
) COMMENT = '学生信息表'

 

1. 配置步骤

1.1. 第一步:导入包

新建一个java项目并导入包

在这里插入图片描述

1.2. 第二步:创建一个Mybatis的总配置文件

新建mybatis总配置模板文件

在这里插入图片描述

1、file—setting,左上角输入template
2、在左侧栏找到File And Code Templates
3、中间选中Files
4、点击+号,添加模板
5、输入模板名字:Name:mybatis-cfg.xml (name可以自定义)
6、后缀名extension:xml
7、在面板中间输入内容:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "mybatis-3-config.dtd" >
<configuration>

</configuration>

 

8、把enable live Template(激活模板)勾选上
9、点击Apply—ok
10、选中模板,然后输入xml文件名字mybatis.cfg.xml

在这里插入图片描述

-注意:Mybatis的DTD的Public ID没有写在DTD文件里面,可以在官方文档里面找到

–以后,任何框架如果没有在DTD文件提供Public Id 的都去找官方文档。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "mybatis-3-config.dtd" >
<configuration>
  
  <!-- 配置数据库连接 -->
  <!--
    environments:环境集,可以在里面配置多个environment,一个environment对应一个数据库连接
    mybatis支持配置多个数据库连接,但是只能执行一个
    default属性:作用就是指定默认执行的数据库连接environment标签的id属性
  
   -->
  <environments default="mysql">
  
     <!-- environment 作用:配置数据库连接
       id属性:用于声明一个唯一标识符,符合XML命名规范就可以
     -->
     <environment id="mysql">
       <!-- transactionManager标签:指定事务的类型
        type:设置数据库事务类型
        -任何的静态属性都可以在代码里面找到-
        -大部分框架的配置文件的解释类都放在configuration、builder单词的缩写或全写的包里面
        org.apache.ibatis.builder.xml.XMLConfigBuilder
        -根据代码分析,发现属性的参数是设置在Configuration类里面的
        
        -typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
     -typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);
        
        1.JDBC:使用JDBC的事务提交回滚
        2.MANAGED:不需要事务
        
       -->
       <transactionManager type="JDBC"></transactionManager>
       <!-- dataSource:配置数据源
       
            typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class);
     typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);
     typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);
     JNDI:使用JNDI的数据源,就是在WEB服务器配置一个数据库连接池,如再TOMCAT里面配置一个数据源。就是JNDI数据源
     POOLED:使用数据库连接池,Mybatis内置默认有一个简单的内置连接池
     UNPOOLED:不使用数据库连接,直接使用数据库JDBC直连  
       -->
       
       <dataSource type="POOLED">
          <!-- 静态属性都在三个地方
            1.属性名
            2.属性值
            3.Set方法
           -->
          <!-- 驱动 -->
           <property name="driver" value="com.mysql.jdbc.Driver"/>
           <!-- 连接字符串 -->
           <property name="url" value="jdbc:mysql:///mybatis"/>
           <!-- 用户名 -->
           <property name="username" value="root"/>
           <!-- 密码 -->
           <property name="password" value="123456"/>
       </dataSource>
     </environment>
  </environments>
 
 
</configuration>
 

 

db.properties:

#mysql数据源
mysql.driver=com.mysql.jdbc.Driver
#使用默认的本地ip和默认端口号
mysql.url=jdbc:mysql:///mybatis
mysql.username=root
mysql.password=123456

 

1.3. 第三步:创建一个MybatisUtil获得Session

public class MybatisUtils {
 
    // 注意:基于如果出现多个会话工厂,可能导致事务不同步的问题,所以我们一个项目只使用一个会话工厂
    public static final SqlSessionFactory SSF = createSqlSessionFactory();
    // 需求:实现同一条线程,使用的session是相同的。线程绑定,
    // 创建一个线程绑定变量,将变量放在该对象里面,表示对象同一条线程共享
    private static final ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();

    // 1.获得会话工厂
    private static SqlSessionFactory createSqlSessionFactory() {
    try {
        // 1.返回一个Reader对象
        Reader reader = Resources.getResourceAsReader("mybatis-cfg.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sessionFactory = builder.build(reader);
        return sessionFactory;

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return null;
    }

    // 2.获得操作对象,SqlSession对象

    public static SqlSession getSqlSession() {
        //1.判断线程变量里面是否已经有值
        if (threadLocal.get() == null) {
        //2.如果没有值,那么创建一个session对象设置在线程变量里面
        SqlSession session = SSF.openSession();
        threadLocal.set(session);
        }
        //3.返回线程变量里面的session对象
        return threadLocal.get();
    }

    public static void main(String[] args) {
        //同一条线程。对象一样
        //注意事项:如果对象是一个静态的属性的,意味着,整个系统共用一个对象
        //如果放在ThreadLocal对象里面,仅仅是当前线程共用该对象
        System.out.println(MybatisUtils.getSqlSession());
        System.out.println(MybatisUtils.getSqlSession());
    }
 
}
 

 

在这里插入图片描述

Thread与ThreadLocal的伪代码关联关系

在这里插入图片描述

1.4. 第四步:创建实体类


public class Student {
 
    private String stuId;//BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '学生编号',
    private String stuName;//VARCHAR(50) NULL DEFAULT NULL COMMENT '学生名字',
    private String stuAge;//INT(11) NULL DEFAULT NULL COMMENT '学生年龄',
    private String stuPassword;//VARCHAR(50) NULL DEFAULT NULL COMMENT '密码',
    public String getStuId() {
    	return stuId;
    }
    public void setStuId(String stuId) {
    	this.stuId = stuId;
    }
    public String getStuName() {
    	return stuName;
    }
    public void setStuName(String stuName) {
   	 	this.stuName = stuName;
    }
    public String getStuAge() {
    	return stuAge;
    }
    public void setStuAge(String stuAge) {
    	this.stuAge = stuAge;
    }
    public String getStuPassword() {
    	return stuPassword;
    }
    public void setStuPassword(String stuPassword) {
    	this.stuPassword = stuPassword;
    }
}
 

 

1.5. 第五步:创建一个操作接口

public interface StudentMapper {
//需求:实现插入数据到student表
//注意:如果是增删改操作,返回的类型必须是int类型
//返回的是操作影响的行数。
int insert(Student student);
 
}

 

1.6. 第六步:创建映射文件-StudentMapper.xml

创建一个mybatis-mapper.xml模板文件

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd" >
<!-- 注意事项:使用映射接口的配置方式,namespace必须指向接口的类全名 -->
<mapper namespace="cn.mapper.StudentMapper">
 
    <!--
    useGeneratedKeys:作用打开支持ID回填,设置为true
    keyColumn:设置ID回填,ID对象数据库的字段名
    keyProperty:设置ID回填到JavaBean对应的属性名
    
     -->
    <insert id="insert" useGeneratedKeys="true" keyColumn="stuId" keyProperty="stuId" >
       <!-- 注意:如果传递过来的是一个JavaBean对象,那么设置的属性名为,set方法对应的属性名。如:setStuName 对应的是 stuName
        
        -->
       INSERT INTO tb_student (stuName, stuAge, stuPassword) VALUES (#{stuName}, #{stuAge}, #{stuPassword})
    </insert>
 
</mapper>
 

 

1.7. 第七步:总配置文件设置加载映射文件

  <!-- 加载映射文件 -->
  <mappers>
    <mapper resource="cn/mapper/xml/StudentMapper.xml"/>
  </mappers>
 

 

1.8. 第八步:测试代码


 
public class StudentMapperTest {
    @Test
    public void insert(){
        //1.获得操作对象,session
        SqlSession session = MybatisUtils.getSqlSession();
        //2.获得操作接口的动态对象
        StudentMapper studentMapper = session.getMapper(StudentMapper.class);
        Student student=new Student();
        student.setStuName("陈七");
            //3.插入对象
        int count = studentMapper.insert(student);
        //4.提交事务
        session.commit();
        //5.关闭
        session.close();
        System.out.println("返回值:"+count);
        //需求:实现ID回填,就是插入数据后要将数据库的ID设置在实体类对象里面
        System.out.println("ID:"+student.getStuId());
    }
 
}
 

 

1.9. 第九步:Mybatis对properties文件的支持

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "mybatis-3-config.dtd" >
<!-- XMLConfigBuilder是总配置文件的构建类 -->
<configuration>
   <!-- 对propertis的支持 -->
   <properties resource="db.properties"></properties>
 
  <!-- 用于配置数据库的连接参数 ,environments这个标签可以配置多个数据库的连接,default表示默认使用的配置-->
  <environments default="default-msql">
  
    
     <!-- 数据库的连接参数 Configuration查看参数-->
     <!-- 所有框架的静态属性都可以在这个框架的类里面找到,不用死记硬背 -->
     <!-- id:就是一个标识符 -->
     <environment id="default-msql">
        <!-- 事务类型 -->
        <!-- 事务类型有哪些
         JDBC:使用JDBC事务
         MANAGED:不用事务
         -->
        <transactionManager type="JDBC"></transactionManager>
        <!-- 数据源 -->
        <!-- type表示数据库的类型
           JNDI:使用JNDI获得数据源.
           POOLED:使用默认的连接池获得数据源
           UNPOOLED:不用数据源
         
          -->
          <!-- org.apache.ibatis.datasource.pooled.PooledDataSource -->
        <dataSource type="POOLED">
           <!-- 所有的property对应的是一个set方法 -->
           <!-- 四要素 -->
           <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="cn/mapper/xml/StudentMapper.xml"/>
  </mappers>
 
</configuration>
 

 

果然实现的操作层的零实现!!!

2.执行原理

在这里插入图片描述


在这里插入图片描述

a.MyBatis应用程序Configuration对象根据XML配置文件或注解创建SqlSessionFactory工厂,获取一个SqlSession,加载SQL配置信息,生成一个个MappedStatement对象(包括传入参数映射配置、执行的sql语句、结果映射配置),并存储在内存中,

b.SQL解析,SqlSession包含了执行sql所需要的所有方法,可以通过SqlSession实例直接运行映射的sql语句

(调用方法时,会接收到SQL的ID和传入对象,MyBatis会根据SQL的ID找到对应的MappedStatement,然后根据传入的参数对象对MappedStatement进行解析,解析后可以得到最终需要执行的SQL语句和参数)

c.SQL执行,完成对数据的增删改查,得到数据库操作结果

d.结果映射将操作结果按照映射配置进行转换,转换成HashMap、JavaBean等

e.事务提交,用完之后关闭SqlSession,返回结果。

三. log4j的配置

1. 第一步:导入log4j-1.2.17.jar包

在这里插入图片描述

2. 第二步:在src下创建一个log4j.propertis文件

注意:文件名必须为log4j.properties

#--------console-----------
log4j.appender.myconsole=org.apache.log4j.ConsoleAppender
log4j.appender.myconsole.layout=org.apache.log4j.SimpleLayout
#--------HTML-----------
log4j.appender.myfile=org.apache.log4j.FileAppender
log4j.appender.myfile.File=D\:\\error.html
log4j.appender.myfile.layout=org.apache.log4j.HTMLLayout


#默认设置,用于指定默认的记录的日志级别
#日志级别:debug    info    warm   error   fatal(致命错误)
log4j.rootLogger=info,myfile,myconsole
#   输出   mybatis 的sql语句与参数        指定mapper接口所在的位置的输出级别即可
#   log4j.logger.mapper接口所在的包名=TRACE
log4j.logger.com.mapper=TRACE

 

四. 三种操作方式CRUD

CRUD:create read update del

示例的SQL代码

CREATE TABLE `student` (
  `sid` int(11) NOT NULL AUTO_INCREMENT,
  `aid` int(11) DEFAULT NULL,
  `sname` varchar(50) DEFAULT NULL,
  `sex` char(3) DEFAULT NULL,
  `birthday` date DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`sid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

就是Mybatis支持三种风格的操作代码.

1. 使用接口和配置文件操作

就是使用接口+XML映射文件直接操作数据库。代码查看上面的入门示例代码!

2. 使用接口和注解操作(未来)

元数据:就是启动项目是必须的数据.

为什么现在的框架都使用注解来代替xml文件呢?

答:就是因为xml配置文件不是编程语言的语法,所以无法断点调试.使用注解,注解是Java编程语言的语法,断点调试时,可以尽可能排除配置文件的出错

配置步骤:

2.1. 第一步:导入包

在这里插入图片描述

2.2. 第二步:创建一个总配置文件mybatis-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "mybatis-3-config.dtd" >
<!-- XMLConfigBuilder是总配置文件的构建类 -->
<configuration>
  <!-- 用于配置数据库的连接参数 ,environments这个标签可以配置多个数据库的连接,default表示默认使用的配置-->
  <environments default="default-msql">
  
     <!-- 数据库的连接参数 Configuration查看参数-->
     <!-- 所有框架的静态属性都可以在这个框架的类里面找到,不用死记硬背 -->
     <!-- id:就是一个标识符 -->
     <environment id="default-msql">
        <!-- 事务类型 -->
        <!-- 事务类型有哪些
         JDBC:使用JDBC事务
         MANAGED:不用事务
         -->
        <transactionManager type="JDBC"></transactionManager>
        <!-- 数据源 -->
        <!-- type表示数据库的类型
           JNDI:使用JNDI获得数据源.
           POOLED:使用默认的连接池获得数据源
           UNPOOLED:不用数据源
         
          -->
          <!-- org.apache.ibatis.datasource.pooled.PooledDataSource -->
        <dataSource type="POOLED">
           <!-- 所有的property对应的是一个set方法 -->
           <!-- 四要素 -->
           <property name="driver" value="org.gjt.mm.mysql.Driver"/>
           <property name="url" value="jdbc:mysql://localhost:3306/school"/>
           <property name="username" value="root"/>
           <property name="password" value="123456"/>
        </dataSource>
     </environment>
  </environments>
  <!-- 加载映射文件 -->
  <mappers>
    <!-- class属性:加载的是使用注解调用方式的接口 -->
    <mapper class="cn.mapper.StudentMapper"/>
  </mappers>
 
</configuration>
 

 

2.3. 第三步:创建一个MybatisUtils,获得SqlSession操作对象

public class MybatisUtils {
 
    // 注意:基于如果出现多个会话工厂,可能导致事务不同步的问题,所以我们一个项目只使用一个会话工厂
    public static final SqlSessionFactory SSF = createSqlSessionFactory();
    // 需求:实现同一条线程,使用的session是相同的。线程绑定,
    // 创建一个线程绑定变量,将变量放在该对象里面,表示对象同一条线程共享
    private static final ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();

    // 1.获得会话工厂
    private static SqlSessionFactory createSqlSessionFactory() {
    try {
        // 1.返回一个Reader对象
        Reader reader = Resources.getResourceAsReader("mybatis-cfg.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sessionFactory = builder.build(reader);
        return sessionFactory;

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return null;
    }

    // 2.获得操作对象,SqlSession对象

    public static SqlSession getSqlSession() {
        //1.判断线程变量里面是否已经有值
        if (threadLocal.get() == null) {
        //2.如果没有值,那么创建一个session对象设置在线程变量里面
        SqlSession session = SSF.openSession();
        threadLocal.set(session);
        }
        //3.返回线程变量里面的session对象
        return threadLocal.get();
    }

    public static void main(String[] args) {
        //同一条线程。对象一样
        //注意事项:如果对象是一个静态的属性的,意味着,整个系统共用一个对象
        //如果放在ThreadLocal对象里面,仅仅是当前线程共用该对象
        System.out.println(MybatisUtils.getSqlSession());
        System.out.println(MybatisUtils.getSqlSession());
    }
 
}
 

 

2.4. 第四步: 创建一个实体类

 

public class Student {
    private Integer sid;//int(11) not null auto_increment comment '编号',
    private Integer aid;//int(11) null default '0',
    private String sname;//varchar(50) null default null comment '姓名',
    private String sex;//char(3) null default null comment '性别',
    private Date birthday;//date null default null comment '生日',
    private Integer age;//int(11) null default null comment '年龄',
    public Integer getSid() {
    return sid;
    }
    public void setSid(Integer sid) {
    this.sid = sid;
    }
    public Integer getAid() {
    return aid;
    }
    public void setAid(Integer aid) {
    this.aid = aid;
    }
    public String getSname() {
    return sname;
    }
    public void setSname(String sname) {
    System.out.println("-输出名字-"+sname);
    this.sname = sname;
    }
    public String getSex() {
    return sex;
    }
    public void setSex(String sex) {
    this.sex = sex;
    }
    public Date getBirthday() {
    return birthday;
    }
    public void setBirthday(Date birthday) {
    this.birthday = birthday;
    }
    public Integer getAge() {
    return age;
    }
    public void setAge(Integer age) {
    this.age = age;
    }
 
}
 

 

2.5 第五步:创建一个映射接口+操作的注解


 
public interface StudentMapper {
    /**
     * 插入记录
     * @param entity
     * @return
     */
    @Insert(value="INSERT INTO student(AID, SNAME, SEX, BIRTHDAY, AGE) VALUES (#{sid}, #{sname}, #{sex}, #{birthday}, #{age})")
    int insert(Student entity);
    /**
     * 删除记录
     * @param sid
     * @return
     */
    @Delete(value="DELETE FROM student WHERE SID=#{sid}")
    int deleteById(int sid);
    /**
     * 更新记录
     * @param entity
     * @return
     */
    @Update(value="UPDATE student SET AID=#{aid},SNAME=#{sname},SEX=#{sex},BIRTHDAY=#{birthday},AGE=#{age} WHERE SID=#{sid}")
    int update(Student entity);
    /**
     * 查询所有的记录
     * @return
     */
    @Select(value="SELECT * FROM student")
    List<Student> findAll();

}
 

 

2.6. 第六步:测试代码


public class StudentMapperTest {
 
    /* @Test
    public void insert() {
    try {
    //1.获得操作对象
    SqlSession session = DbUtils.getSession();
    //2.使用session.获得映射接口的代理对象,这个代理对象是mybatis通过StudentMapper.xml创建的
    StudentMapper studentMapper = session.getMapper(StudentMapper.class);
    Student student = new Student();
    student.setSname("王五");
    student.setSex("男");
    //调用接口操作数据库
    studentMapper.insert(student);
    //提交
    session.commit();
    session.close();
    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }*/
    
    /* @Test
    public void deleteById(){
    //1.获得操作对象
    SqlSession session = DbUtils.getSession();
    //2.使用session.获得映射接口的代理对象,这个代理对象是mybatis通过StudentMapper.xml创建的
    StudentMapper studentMapper = session.getMapper(StudentMapper.class);
    int count=studentMapper.deleteById(1);
    System.out.println(count);
    session.commit();
    session.close();
    }*/

    /* @Test
    public void update(){
    //1.获得操作对象
    SqlSession session = DbUtils.getSession();
    //2.使用session.获得映射接口的代理对象,这个代理对象是mybatis通过StudentMapper.xml创建的
    StudentMapper studentMapper = session.getMapper(StudentMapper.class);
    Student entity=new Student();
    entity.setSname("赵六");
    entity.setSex("男");
    entity.setAge(20);
    entity.setBirthday(new Date());
    entity.setSid(2);
    //更新记录
    int count=studentMapper.update(entity);
    System.out.println(count);
    session.commit();
    session.close();
    }*/
    @Test
    public void findAll(){
    //1.获得操作对象
    SqlSession session = DbUtils.getSession();
    //2.使用session.获得映射接口的代理对象,这个代理对象是mybatis通过StudentMapper.xml创建的
    StudentMapper studentMapper = session.getMapper(StudentMapper.class);
    List<Student> list = studentMapper.findAll();
    for(Student s:list){
    System.out.print("姓名:"+s.getSname());
    System.out.print(",年龄:"+s.getAge());
    System.out.println(",生日:"+s.getBirthday());
    }

    session.commit();
    session.close();
    }
}
 

 

3.基于配置文件和DAO的操作方式(过去)[可选]

Mybatis也支持基于DAO方式的操作,这种方式是继承ibatis的,方便原来使用ibatis的程序员可以平滑过渡到Mybatis.现在开发很少使用了.

这种开发的方式就是:创建一个映射文件,定义一个任意的命令空间名,通过SqlSession提供的insert,delete,update,selectList等方法操作指定命名空间下的操作.

操作字符串的格式为: 命名空间.操作ID

开发步骤

3.1. 第一步.导入包

在这里插入图片描述

3.2. 第二步:创建一个mybatis-config.xml总配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "mybatis-3-config.dtd" >
<!-- XMLConfigBuilder是总配置文件的构建类 -->
<configuration>
  <!-- 用于配置数据库的连接参数 ,environments这个标签可以配置多个数据库的连接,default表示默认使用的配置-->
  <environments default="default-msql">
  
     <!-- 数据库的连接参数 Configuration查看参数-->
     <!-- 所有框架的静态属性都可以在这个框架的类里面找到,不用死记硬背 -->
     <!-- id:就是一个标识符 -->
     <environment id="default-msql">
        <!-- 事务类型 -->
        <!-- 事务类型有哪些
         JDBC:使用JDBC事务
         MANAGED:不用事务
         -->
        <transactionManager type="JDBC"></transactionManager>
        <!-- 数据源 -->
        <!-- type表示数据库的类型
           JNDI:使用JNDI获得数据源.
           POOLED:使用默认的连接池获得数据源
           UNPOOLED:不用数据源
         
          -->
          <!-- org.apache.ibatis.datasource.pooled.PooledDataSource -->
        <dataSource type="POOLED">
           <!-- 所有的property对应的是一个set方法 -->
           <!-- 四要素 -->
           <property name="driver" value="org.gjt.mm.mysql.Driver"/>
           <property name="url" value="jdbc:mysql://localhost:3306/school"/>
           <property name="username" value="root"/>
           <property name="password" value="123456"/>
        </dataSource>
     </environment>
  </environments>
  <!-- 加载映射文件 -->
  <mappers>
    <!-- class属性:加载的是使用注解调用方式的接口 -->
    <mapper class="cn.mapper.StudentMapper"/>
  </mappers>
 
</configuration>
 

 

3.3. 第三步:创建MybatisUtils帮助类

创建一个MybatisUtils工具类获得SqlSession操作对象

public class MybatisUtils {
 
    // 注意:基于如果出现多个会话工厂,可能导致事务不同步的问题,所以我们一个项目只使用一个会话工厂
    public static final SqlSessionFactory SSF = createSqlSessionFactory();
    // 需求:实现同一条线程,使用的session是相同的。线程绑定,
    // 创建一个线程绑定变量,将变量放在该对象里面,表示对象同一条线程共享
    private static final ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();

    // 1.获得会话工厂
    private static SqlSessionFactory createSqlSessionFactory() {
    try {
        // 1.返回一个Reader对象
        Reader reader = Resources.getResourceAsReader("mybatis-cfg.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sessionFactory = builder.build(reader);
        return sessionFactory;

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return null;
    }

    // 2.获得操作对象,SqlSession对象

    public static SqlSession getSqlSession() {
        //1.判断线程变量里面是否已经有值
        if (threadLocal.get() == null) {
        //2.如果没有值,那么创建一个session对象设置在线程变量里面
        SqlSession session = SSF.openSession();
        threadLocal.set(session);
        }
        //3.返回线程变量里面的session对象
        return threadLocal.get();
    }

    public static void main(String[] args) {
        //同一条线程。对象一样
        //注意事项:如果对象是一个静态的属性的,意味着,整个系统共用一个对象
        //如果放在ThreadLocal对象里面,仅仅是当前线程共用该对象
        System.out.println(MybatisUtils.getSqlSession());
        System.out.println(MybatisUtils.getSqlSession());
    }
 
}
 

 

3.4. 第四步:创建一个实体类Student


 
//ctrl+shift+y 大写转小写
public class Student {
    private Integer sid;//int(11) not null auto_increment comment '编号',
    private Integer aid;//int(11) null default '0',
    private String sname;//varchar(50) null default null comment '姓名',
    private String sex;//char(3) null default null comment '性别',
    private Date birthday;//date null default null comment '生日',
    private Integer age;//int(11) null default null comment '年龄',
    public Integer getSid() {
    return sid;
    }
    public void setSid(Integer sid) {
    this.sid = sid;
    }
    public Integer getAid() {
    return aid;
    }
    public void setAid(Integer aid) {
    this.aid = aid;
    }
    public String getSname() {
    return sname;
    }
    public void setSname(String sname) {
    System.out.println("-输出名字-"+sname);
    this.sname = sname;
    }
    public String getSex() {
    return sex;
    }
    public void setSex(String sex) {
    this.sex = sex;
    }
    public Date getBirthday() {
    return birthday;
    }
    public void setBirthday(Date birthday) {
    this.birthday = birthday;
    }
    public Integer getAge() {
    return age;
    }
    public void setAge(Integer age) {
    this.age = age;
    }
 
}
 

3.5. 第五步:创建一个映射文件StudentMapper

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd" >
<!--
命名空间:
如果使用的不是接口的操作方式,命名空间的作用是作为每个操作文件唯一标识符.
所以,可以随便写了.
那么我们就随便起了一个名字studentDAO给这个映射文件.
我们就可以通过这个名字(命名空间)来操作这个映射文件的操作了.
 -->
<mapper namespace="studentDAO">
   <!-- 操作 在Mybatis里面增删改都是返回影响的行数 int-->
   <insert id="insert">
     <!-- 插入的SQL语句 -->
     <!-- 如果传入实体类,可以使用#{}来获得实体类的属性值.
     
                  注意:#{key},key一定要和set方法一一对应 如: setSname #${sname}
             
      -->
     INSERT INTO student(AID, SNAME, SEX, BIRTHDAY, AGE) VALUES (#{sid}, #{sname}, #{sex}, #{birthday}, #{age})
   </insert>
   
   <!-- 删除记录 -->
   <delete id="deleteById">
        DELETE FROM student WHERE SID=#{sid}
   </delete>
   
   <!-- 传递一个实体过来,更新数据库的记录 -->
   <update id="update">
      UPDATE student SET AID=#{aid},SNAME=#{sname},SEX=#{sex},BIRTHDAY=#{birthday},AGE=#{age} WHERE SID=#{sid}
   </update>
   <!-- reultTye:就是返回的每一条记录的类型.如Studen表,就是Studen对象.
   只要数据库表的字段与实体类的set方法的方法名一一对应,数据会自动关联.如:数据表的字段SNAME sname 会自动关联实体类的setSname
   
   为什么会大写可以关联小写的字段,因为MySQL自动忽略数据库字段的大小写.
    -->
  <select resultType="cn.entity.Student" id="findAll">
     SELECT * FROM student
  </select> 
 
</mapper>
 

 

3.6. 第六步:创建一个DAO操作类

public class StudentDAO {
    /**
     * 插入数据
     * @param entity
     * @return
     */
    public int insert(Student entity){
    //1.获得操作类对象
    SqlSession session = DbUtils.getSession();
    //2.操作
    //session.insert(statement); 没有操作参数的插入,如果没有传入的参数,意味着插入的数据只能写在xml映射文件里面
    //格式为:命名空间.操作的ID,如:studentDAO.insert
    int count=session.insert("studentDAO.insert", entity);
    session.commit();
    session.close();
    return count;
    }
    /**
     * 删除记录
     * @param entity
     * @return
     */
    public int deleteById(int sid){
    //1.获得操作类对象
    SqlSession session = DbUtils.getSession();
    //2.操作
    //session.insert(statement); 没有操作参数的插入,如果没有传入的参数,意味着插入的数据只能写在xml映射文件里面
    //格式为:命名空间.操作的ID,如:studentDAO.insert
    //增删改,的语法是一样,Mybatis并不知道你做的事增删改,它只知道你执行的是SQL语句.
    //但一定要注意,虽然增删改的标签的功能一样,还是建议增使用insert,删使用delete,改使用update
    //session.delete(statement),这个没有参数的删除
    int count=session.delete("studentDAO.deleteById", sid);
    session.commit();
    session.close();
    return count;
    }
    /**
     * 更新记录
     * @param entity
     * @return
     */
    public int update(Student entity){
    //1.获得操作类对象
    SqlSession session = DbUtils.getSession();
    //2.操作
    //session.update(statement); 没有操作参数的插入,如果没有传入的参数,意味着插入的数据只能写在xml映射文件里面
    //格式为:命名空间.操作的ID,如:studentDAO.update
    int count=session.update("studentDAO.update", entity);
    session.commit();
    session.close();
    return count;
    }
    public List<Student> findAll(){
    //1.获得操作类对象
    SqlSession session = DbUtils.getSession();
    //2.操作
    //session.update(statement); 没有操作参数的插入,如果没有传入的参数,意味着插入的数据只能写在xml映射文件里面
    //格式为:命名空间.操作的ID,如:studentDAO.update
    //没有返回参数的
    List<Student> selectList = session.selectList("studentDAO.findAll");
    session.commit();
    session.close();
    return selectList;
    }
}

3.7. 第七步:测试


 
public class StudentDAOTest {

    /* @Test
    public void insert() {
    try {
                 StudentDAO studentDAO = new StudentDAO();
                 Student entity=new Student();
                 entity.setSname("陈七");
                 entity.setBirthday(new Date());
                 entity.setAge(21);
     int count=studentDAO.insert(entity);
     System.out.println(count);
    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }*/
    /* @Test
    public void deleteById(){
            StudentDAO studentDAO = new StudentDAO();
     int count=studentDAO.deleteById(4);
     System.out.println(count);
    }*/

    /* @Test
    public void update(){
          StudentDAO studentDAO = new StudentDAO();
     Student entity=new Student();
             entity.setSname("李四");
             entity.setBirthday(new Date());
            entity.setAge(21);
            entity.setSid(2);
    int count=studentDAO.update(entity);
     System.out.println(count);
    }*/
    //ctrl+shift+/
    @Test
    public void findAll(){
         StudentDAO studentDAO = new StudentDAO();
         List<Student> list = studentDAO.findAll();
    for(Student s:list){
    System.out.print("姓名:"+s.getSname());
    System.out.print(",年龄:"+s.getAge());
    System.out.println(",生日:"+s.getBirthday());
    }

    }
}
 

 

五. 总配置文件说明

在这里插入图片描述

:环境集便签,就是用于配置数据库的连接信息的

:用于配置具体环境参数

:配置使用的事务类型,JDBC

:配置数据源的参数,具体参数参看PooledDataSource的set方法

:配置属性

:配置映射文件信息的

<mapper class|resource>:配置具体指定的mapper文件

class:配置使用注解时指定有注解的映射接口

resource:指定映射文件

:mybatis对propertis文件的支持

:用于配置别名

:用于配置自定义类型处理器.

:配置Mybatis的默认设置的.

总配置文件的标签顺序

<!ELEMENT configuration (properties?, settings?, typeAliases?, typeHandlers?, objectFactory?, objectWrapperFactory?, reflectorFactory?, plugins?, environments?, databaseIdProvider?, mappers?)>

 

这句话的意思就是configuration 标签下的标签的顺序以及标签出现的个数的声明

根据这个声明可以看到顺序为:

1.properties

2.settings

3.typeAliases

4.typeHandlers

5.objectFactory

6.objectWrapperFactory

7.reflectorFactory

8.plugins

9.environments

10.databaseIdProvider

11.mappers

DTD规则文件标签的出现的次数说明

如果声明的标签后?:表示出现0-1次

如果声明的标签后*:表示出现0-N次

如果声明的标签后+:表示出现1-N次

如果声明的标签后什么都没有:表示出现1次

1. 别名typeAliases标签

1.1. 自定义别名

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "mybatis-3-config.dtd" >
<!-- XMLConfigBuilder是总配置文件的构建类 -->
<configuration>
  <!-- 用于配置别名 -->
  <typeAliases>
     <!-- 就是mybatis里面,所有的映射文件,遇到Student返回cn.gzsxt.entity.Student类型 -->
     <typeAlias type="cn.entity.Student" alias="student"/>
  </typeAliases>
 
 
 
  <!-- 用于配置数据库的连接参数 ,environments这个标签可以配置多个数据库的连接,default表示默认使用的配置-->
  <environments default="default-msql">
  
     <!-- 数据库的连接参数 Configuration查看参数-->
     <!-- 所有框架的静态属性都可以在这个框架的类里面找到,不用死记硬背 -->
     <!-- id:就是一个标识符 -->
     <environment id="default-msql">
        <!-- 事务类型 -->
        <!-- 事务类型有哪些
         JDBC:使用JDBC事务
         MANAGED:不用事务
         -->
        <transactionManager type="JDBC"></transactionManager>
        <!-- 数据源 -->
        <!-- type表示数据库的类型
           JNDI:使用JNDI获得数据源.
           POOLED:使用默认的连接池获得数据源
           UNPOOLED:不用数据源
         
          -->
          <!-- org.apache.ibatis.datasource.pooled.PooledDataSource -->
        <dataSource type="POOLED">
           <!-- 所有的property对应的是一个set方法 -->
           <!-- 四要素 -->
           <property name="driver" value="org.gjt.mm.mysql.Driver"/>
           <property name="url" value="jdbc:mysql://localhost:3306/school"/>
           <property name="username" value="root"/>
           <property name="password" value="123456"/>
        </dataSource>
     
     </environment>
  
  </environments>
  <!-- 加载映射文件 -->
  <mappers>
    <mapper resource="mybatis-mapper/StudentMapper.xml"/>
  </mappers>
  
 
 
 
</configuration>
 

 

如果配置成功,在映射文件里面可以直接使用别名

  <select resultType="student" id="findAll">
     SELECT * FROM student
  </select> 

 

别名方式2:去掉包名

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "mybatis-3-config.dtd" >
<!-- XMLConfigBuilder是总配置文件的构建类 -->
<configuration>
  <!-- 用于配置别名 -->
  <!-- 方式一 -->
<!--   <typeAliases> -->
     <!-- 就是mybatis里面,所有的映射文件,遇到Student返回cn.gzsxt.entity.Student类型 -->
<!--      <typeAlias type="cn.entity.Student" alias="student"/> -->
<!--   </typeAliases> -->
 
  <!-- 方式2 -->
  <typeAliases>
     <!-- 意思,就是忽略包名cn.entity -->
     <package name="cn.entity"/>
  </typeAliases>
 
  <!-- 用于配置数据库的连接参数 ,environments这个标签可以配置多个数据库的连接,default表示默认使用的配置-->
  <environments default="default-msql">
  
     <!-- 数据库的连接参数 Configuration查看参数-->
     <!-- 所有框架的静态属性都可以在这个框架的类里面找到,不用死记硬背 -->
     <!-- id:就是一个标识符 -->
     <environment id="default-msql">
        <!-- 事务类型 -->
        <!-- 事务类型有哪些
         JDBC:使用JDBC事务
         MANAGED:不用事务
         -->
        <transactionManager type="JDBC"></transactionManager>
        <!-- 数据源 -->
        <!-- type表示数据库的类型
           JNDI:使用JNDI获得数据源.
           POOLED:使用默认的连接池获得数据源
           UNPOOLED:不用数据源
         
          -->
          <!-- org.apache.ibatis.datasource.pooled.PooledDataSource -->
        <dataSource type="POOLED">
           <!-- 所有的property对应的是一个set方法 -->
           <!-- 四要素 -->
           <property name="driver" value="org.gjt.mm.mysql.Driver"/>
           <property name="url" value="jdbc:mysql://localhost:3306/school"/>
           <property name="username" value="root"/>
           <property name="password" value="123456"/>
        </dataSource>
     
     </environment>
  
  </environments>
  <!-- 加载映射文件 -->
  <mappers>
    <mapper resource="mybatis-mapper/StudentMapper.xml"/>
  </mappers>
  
 
 
 
</configuration>
 

 

对应的映射文件的配置

  <select resultType="Student" id="findAll">
     SELECT * FROM student
  </select> 
 xml

 

1.2. 内置别名

所谓的内置别名,就是Mybatis框架自带别名.

Mybatis已经将常用的数据类型的别名内置声明了.所以这些内置的别名不需要配置就可以直接使用.

内置的别名就是,Mybatis框架默认已经设置的别名.

别名 映射的类型
_byte byte
_long long
_short short
_int int
_integer int
_double double
_float float
_boolean boolean
string java.lang.String
byte Byte
long Long
short Short
int Integer
integer Integer
double Double
float Float
boolean Boolean
date Date
decimal BigDecimal
bigdecimal BigDecimal
object Object
map Map
hashmap HashMap
list List
arraylist ArrayList
collection Collection
iterator Iterator

2. settings标签

Mybatis默认设置了很多默认配置.有时候,我们需求与默认的配置的参数不一样,

我们就需要修改这些默认配置的参数.

如:Mybatis已经对骆驼命名法的支持,但默认是不开启的.可以通过mapUnderscoreToCamelCase参数设置为true支持

表示Mybatis启动可以配置的设置

设置参数 描述 有效值 默认值
cacheEnabled 该配置影响的所有映射器中配置的缓存的全局开关。 true | false TRUE
lazyLoadingEnabled 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。 true | false FALSE
aggressiveLazyLoading 当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载(参考lazyLoadTriggerMethods). true | false false (true in ≤3.4.1)
multipleResultSetsEnabled 是否允许单一语句返回多结果集(需要兼容驱动)。 true | false TRUE
useColumnLabel 使用列标签代替列名。不同的驱动在这方面会有不同的表现, 具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果。 true | false TRUE
useGeneratedKeys 允许 JDBC 支持自动生成主键,需要驱动兼容。 如果设置为 true 则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。 true | false FALSE
autoMappingBehavior 指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示取消自动映射;PARTIAL 只会自动映射没有定义嵌套结果集映射的结果集。 FULL 会自动映射任意复杂的结果集(无论是否嵌套)。 NONE, PARTIAL, FULL PARTIAL
autoMappingUnknownColumnBehavior 指定发现自动映射目标未知列(或者未知属性类型)的行为。 NONE, WARNING, FAILING NONE
NONE: 不做任何反应
WARNING: 输出提醒日志 (‘org.apache.ibatis.session.AutoMappingUnknownColumnBehavior’的日志等级必须设置为 WARN)
FAILING: 映射失败 (抛出 SqlSessionException)
defaultExecutorType 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements); BATCH 执行器将重用语句并执行批量更新。 SIMPLE REUSE BATCH SIMPLE
defaultStatementTimeout 设置超时时间,它决定驱动等待数据库响应的秒数。 任意正整数 Not Set (null)
defaultFetchSize 为驱动的结果集获取数量(fetchSize)设置一个提示值。此参数只可以在查询设置中被覆盖。 任意正整数 Not Set (null)
safeRowBoundsEnabled 允许在嵌套语句中使用分页(RowBounds)。 If allow, set the false. true | false FALSE
safeResultHandlerEnabled 允许在嵌套语句中使用分页(ResultHandler)。 If allow, set the false. true | false TRUE
mapUnderscoreToCamelCase 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 true | false FALSE
localCacheScope MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。 SESSION | STATEMENT SESSION
jdbcTypeForNull 当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER OTHER
lazyLoadTriggerMethods 指定哪个对象的方法触发一次延迟加载。 A method name list separated by commas equals,clone,hashCode,toString
defaultScriptingLanguage 指定动态 SQL 生成的默认语言。 A type alias or fully qualified class name. org.apache.ibatis.scripting.xmltags.XMLLanguageDriver
callSettersOnNulls 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这对于有 Map.keySet() 依赖或 null 值初始化的时候是有用的。注意基本类型(int、boolean等)是不能设置成 null 的。 true | false FALSE
returnInstanceForEmptyRow 当返回行的所有列都是空时,MyBatis默认返回null。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集 (i.e. collectioin and association)。(从3.4.2开始) true | false FALSE
logPrefix 指定 MyBatis 增加到日志名称的前缀。 Any String Not set
logImpl 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING Not set
proxyFactory 指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。 CGLIB | JAVASSIST JAVASSIST (MyBatis 3.3 or above)
vfsImpl 指定VFS的实现 自定义VFS的实现的类全限定名,以逗号分隔。 Not set
useActualParamName 允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的工程必须采用Java 8编译,并且加上-parameters选项。(从3.4.1开始) true | false TRUE
configurationFactory Specifies the class that provides an instance of Configuration. The returned Configuration instance is used to load lazy properties of deserialized objects. This class must have a method with a signature static Configuration getConfiguration(). (Since: 3.2.3) A type alias or fully qualified class name. Not set

如支持骆驼命名法

  <!-- 配置默认的参数 -->
  <settings>
    <!-- 默认支持骆驼命名法 -->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
  </settings>

 

六. mapping映射文件说明

在这里插入图片描述

1. 传入参数

所谓的传入参数指定是Mybatis操作()的传入参数.

Mybatis默认情况下是不支持传入多个参数的.只能传入一个参数.

方案1:将这些参数封装到一个对象里面(JavaBean/Map),再传入.

方案2:给参数设置一个@Param注解支持

为什么不支持多个参数?

因为Java语法1.7以前.是不能通过反射技术获得方法的参数名的.

所以Mybatis只能通过参数的类型来获得参数值.

但Java语法上一个方法可以有多个相同类型的参数.

导致如果Mybatis支持的方法有多个相同的参数时.那么就无法判断参数是哪个参数值了.

有Mybatis映射接口操作的方法只能默认支持一个参数****.

因为使用的是方法的参数的类型来获得参数的,所以在配置文件里面如果获得的值就是方法的参数的值,其实#{随便写},获得的都是这个方法int deleteById(int sid);

结论:

1.默认情况,所有Mybatis映射接口操作的方法只能默认支持一个参数.

2.操作方法的参数是通过类型来取值的.而不是参数名

2. 支持多参数

Mybatis是通过一个参数池概念来支持多参数的.

要使用注解@Param(value=”key”)来将参数放在参数池里面

在这里插入图片描述

接口代码

/**
 * 分页查询
 * @param index
 * @param pageNum
 * @return
 */
List<Student> findAllToPage(@Param(value="index")int index ,@Param(value="pageNum") int pageNum);

 

映射文件代码

  <!-- 分页查询 -->
  <select id="findAllToPage" resultType="Student">
    SELECT * FROM student limit #{index},#{pageNum}
  </select>

 

3. #{}与${}的区别

#{}基于JDBC的PreparedStatement类,?不能作为表名.

${}可以放表名

  <!-- 通过一个操作创建一个表 -->
  <delete id="dropTacle">
     <!-- PreparedStatement决定了表名不能是?,?必须SQL的参数 -->
     drop table ${tableName}
  </delete>

 

/**
 * 删除表
 * @param tableName
 * @return
 */
int dropTacle(@Param("tableName") String tableName);

 

a.#{}表示设置预编译的参数,就是?的参数,所以如果要不固定的表名不能使用#{},只能使用${}

b.KaTeX parse error: Expected ‘EOF’, got ‘#’ at position 12: {}直接把值输出来.而#̲{]是使用?来代替. 所以{}是不安全的.

c.${}只能获得参数池的值,而#{}可以获得方法的参数值,也可以获得参数池的值,如果使用 ${}获得参数的值,这个参数必须要加上@Param

示例:

/**
 * 删除记录
 * @param sid
 * @return
 */
int deleteById(@Param("sid") int sid);

 

   <!-- 删除记录 -->
   <delete id="deleteById">
        <!-- 注意,必须映射接口加上@Param -->
        DELETE FROM student WHERE SID=${sid}
   </delete>

 

如果非必要情况,不要使用${}

问题:那${}有什么用呢?

答:注意基于JDBC的接口的原来的表名是不可以使用?的,?只能用于传入的参数。

如果操作的涉及表名这些非参数的 数据时,需要使用${}

4. 返回数据与实体类的对应关系(resultMap)

有时候,返回的数据的字段和程序的实体类是不同的.Mybatis提供了一个resultMap来手工的配置对应的关系.

ResultMap的作用:

就是用于手工关联实体类与数据库表的字段的关联关系

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd" >
<!-- 命名空间,用于指定动态创建的对象返回的映射接口 -->
<mapper namespace="cn.mapper.StudentMapper">
  <!-- 遇到查询的结果和返回的实体类不对应,需要手工匹配可以使用resultMap -->
  <!--
  autoMapping:默认支持自动映射,如果如果不配置的字段,使用原来实体类的自动映射
  如果为false,表示所有的字段都有一个个配置
  extends:一个ResultMap继承另一个ResultMap
   -->
  <resultMap type="Student" id="studentResultMap"  autoMapping="true">
    <!-- 配置ID字段 -->
    <!--
       javaType="int" :java实体类的类型,不用配置
       jdbcType="int" :数据库的字段的类型,不用配置
       typeHandler="" :Mybatis使用哪个类型解释器来解释,不用配置
     -->
    <id property="sid" column="sid"/>
    <!-- 配置属性字段 -->
    <!--
    property:与实体类的属性对应,setSname
    column:对应是,表的字段名NAME
     -->
    <result property="sname" column="NAME"/>
  </resultMap>

  <!-- 操作 在Mybatis里面增删改都是返回影响的行数 int-->
  <insert id="insert">
    <!-- 插入的SQL语句 -->
    <!-- 如果传入实体类,可以使用#{}来获得实体类的属性值.
    
                 注意:#{key},key一定要和set方法一一对应 如: setSname #${sname}
            
     -->
<!--      INSERT INTO student(AID, SNAME, SEX, BIRTHDAY, AGE) VALUES (#{sid}, #{sname}, #{sex}, #{birthday}, #{age}) -->
     INSERT INTO student(SNAME,  AGE) VALUES (#{sname},#{age})
  </insert>
  
  <!-- 删除记录 -->
<!--    <delete id="deleteById"> -->
       <!-- 如果方法的参数是使用类型来匹配的,那么只有类型相同,里面参数名可以随便写. -->
<!--         DELETE FROM student WHERE SID=#{sid} -->
<!--    </delete> -->

  <!-- 删除记录 -->
  <delete id="deleteById">
       <!-- 如果方法的参数是使用类型来匹配的,那么只有类型相同,里面参数名可以随便写. -->
       DELETE FROM student WHERE SID=${sid}
  </delete>
  
  <!-- 传递一个实体过来,更新数据库的记录 -->
  <update id="update">
     UPDATE student SET AID=#{aid},SNAME=#{sname},SEX=#{sex},BIRTHDAY=#{birthday},AGE=#{age} WHERE SID=#{sid}
  </update>
  <!-- reultTye:就是返回的每一条记录的类型.如Studen表,就是Studen对象.
  只要数据库表的字段与实体类的set方法的方法名一一对应,数据会自动关联.如:数据表的字段SNAME sname 会自动关联实体类的setSname
  
  为什么会大写可以关联小写的字段,因为MySQL自动忽略数据库字段的大小写.
   -->
 <select resultMap="studentResultMap" id="findAll">
    SELECT * FROM student
<!--      SELECT SID, AID, STUDENT_NAME as studentName, SEX, BIRTHDAY, AGE FROM student -->
 </select> 
 <!-- mybatis支持将数据放在map里面 -->
 <select resultType="map" id="findAllByMap">
    SELECT * FROM student
 </select> 
 
 <!-- 分页查询 -->
 <select id="findAllToPage" resultType="Student">
   SELECT * FROM student limit ${index},${pageNum}
 </select>
 
 <!-- 通过一个操作创建一个表 -->
 <insert id="dropTacle">
    <!-- PreparedStatement决定了表名不能是?,?必须SQL的参数 -->
    drop table ${tableName}
 </insert>

</mapper>

 

七. 总结

a.Mybatis是什么

答:Mybatis就是一个持久层框架。意味着它的功能就是增删改查

b. Mybatis实现了什么理念?

答:操作层(持久层)的零实现!!!

c. 什么是零实现?

答:持久层不需要编写实现类,只要接口就可以操作数据库。

d.零实现有什么好处!?

答:大大的减少了持久层的代码,从而提高了开发的效率。Mybatis为开发效率而生!!

e.Mybatis是通过什么方式来实现零实现的呢?

答:通过动态代理技术,实现了接口获得动态对象

通过反射技术,获得XML配置的数据创建多态类对象

f. Mybatis是一个先操作,后映射的框架。

意思就是说,Mybatis是先通过SQL将数据查询出来,将映射到具体的实体类或者Map上面。

映射实体类的方式有三种:

a. 通过手工设置SQL语句的别名与实体类的属性名一一对应

b. 通过Mybatis的自动转换驼峰命名法的方式设置数据表的字段名与属性名的一一对应

c. 通过标签设置表的字段名与实体类的属性名的一一对应

–重点:配置流程图—

三种配置:

a. 配置文件加映射接口的配置(现在)

b. 注解加映射接口的配置(未来)

c. 配置文件加DAO的配置(过去)【可选】

作者:易兮科技 | 来源:https://blog.csdn.net/m0_47157676

赞(0) 打赏
版权归原创作者所有,任何形式转载请联系作者;码农code之路 » SSM第四讲 Mybatis原理及开发流程

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏