MyBatis框架

第1章 框架概述

  • 1.1软件开发常用结构

    • 1.1.1三层架构
      三层架构包括:界面层(User Interface Iayer)、业务逻辑层(Business Logic Iayer)、数据访问层(Data access Iayer)


      三层的职责

      三层对应的包
      界面层:controller包(servlet)
      业务逻辑层:service包(XXXService类)
      数据访问层:dao包(XXXDao类)

      三层中类的交互
      用户使用界面层->业务逻辑层->数据访问层(持久层)->数据库(MySQL)

      三层对应的框架
      界面层——servlet——springmvc(框架)
      业务逻辑层——service类——spring(框架)
      数据访问层——dao类——mybatis(框架)

  • 1.2框架是什么

    • 1.2.1框架定义


      框架的定义
  • 1.3JDBC编程

    • 1.3.2使用JDBC 的缺陷


      使用JDBC的缺陷
  • 1.4MyBatis框架概述


    MyBatis SQL Mapper Framework for Java
    1)sql mapper:sql映射
    可以把数据库表中的一行数据映射为一个Java对象。操作这个对象就相当于操作表中的数据。
    2)Data Access Objects(DAOs):数据访问,对数据库执行增删改查。

    mybatis提供能哪些功能:
    1)提供能Connection、Statement、ResultSet的能力,不用开发人员创建这些对象。
    2)提供执行sql语句的能力,不用开发人员执行sql。
    3)提供了循环sql,把sql的结果转为Java对象、List集合的能力。
    4)提供了关闭资源的能力,不用你关闭Connection、Statement、ResultSet。
    即开发人员提供sql语句——mybatis处理sql——开发人员得到List集合或Java对象(表中的数据)
    总结:mybatis是一个sql映射框架,提供数据库的操作能力。增强的JDBC,使用mybatis让开发人员集中精神写sql就可以了,不必关心Connection、Statement、ResultSet的创建、销毁、sql的执行。

第2章 MyBatis框架快速入门

  • 2.1入门案例
    • 2.1.1使用MyBatis准备

    • 2.1.2搭建MyBatis开发环境
      1)创建mysql数据库和表

//创建并进入数据库ssm
create database ssm;
use ssm;
//创建student表
create table student (
id int(11) primary key not null,
name varchar(255) default null,
email varchar(255) default null,
age int(11)default null
)charset=utf8;
插入数据

2)创建maven工程

选择maven模板

项目名称与路径

创建配置文件根目录

3)加入maven坐标、MySQL驱动坐标和maven插件

    <!--mybatis依赖-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.1</version>
    </dependency>

    <!--mysql驱动-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.23</version>
    </dependency>

  <!--加入maven插件,编译时扫描文件用到-->
  <build>
    <resources>
      <resource>
        <directory>src/main/java</directory><!--所在的目录-->
        <includes><!--包括目录下的.properties、xml文件都会扫描到-->
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
    </resources>
  </build>
修改jdk版本为当前使用版本

加入mybatis依赖与mysql驱动

刷新配置文件

4)创建实体类,如Student——保存表中的一行数据

创建实体类

5)创建持久层Dao接口,定义操作数据库的方法
要查询数据需要返回一个集合,List是Java中比较常用的集合类。这个集合里面应该放Student对象,因为表中的每一行数据都可以看成一个Student对象。

创建持久层Dao接口

6)创建MyBatis使用的配置文件,叫sql映射文件
写sql语句的,一般一个表一个sql映射文件.xml
文件位置:接口所在的目录中
文件名称:与接口保持一致

//基于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="org.mybatis.example.BlogMapper">
  <!--查询操作-->
  <select id="selectBlog" resultType="Blog">
    select * from Blog where id = #{id}
  </select>
    <!--插入操作-->
    <insert id="insertStudents">
        insert into student values (#{id},#{name},#{email},#{age})
    </insert>
</mapper>
<!--
    sql映射文件:写sql语句的,mybatis会执行这些sql
    1.指定约束文件:<!DOCTYPE mapper/>,
    mybatis-3-mapper.dtd是约束文件的名称,扩展名是dtd。
    作用:检查在当前文件中出现的标签和属性必须符合mybatis的要求。
    2.当前文件的跟标签:<mapper namespace></mapper>
    namespace叫命名空间,唯一值的,可以自定义的字符串。
    要求:使用dao接口的全限定名称。(包括包名、类名)
    3.在当前文件中,可以使用特定的标签,表示数据库的特定操作
    <select>:表示执行查询,放的是select语句
    <update>:表示执行修改,放的是update语句
    <insert>:表示执行添加,放的是insert语句
    <delete>:表示执行删除,放的是delete语句

        select表示查询操作
        id:表示要执行的sql语法的唯一标识,
        mybatis会使用这个id的值来找到要执行的sql语句
        可以自定义,但是要求使用接口中的方法名称
        
        resultType:表示结果类型
        是sql语句执行后得到记录集,
        遍历记录集得到Java对象的类型
        值写的是类型的权限的名称
-->
创建sql映射文件

7)创建mybatis的主配置文件:一个项目就一个主配置文件
主配置文件提供了数据库的连接信息和sql映射文件的位置信息

<?xml version="1.0" encoding="UTF-8" ?>
<!--mybatis的主配置文件:主要定义了数据库的配置信息和sql映射文件的位置-->

<!--指定约束文件-->
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--根标签-->
<configuration>

    <!--环境配置:数据库的连接信息
        default:必须和某个environments的id值一致,
        告诉mybatis使用哪个数据库的连接信息。即访问哪个数据库
        即选择不同环境使用的数据库
    -->
    <environments default="DbMybatis">

        <!--environment:一个数据库信息的配置
            id:一个唯一值,自定义,表示环境的名称
        -->
        <!--
             开发环境
         -->
        <environment id="DbMybatis">

            <!--transactionManager:mybatis的事务类型
                type:
                    1)JDBC:表示使用jdbc中的Connection对象的commit,rollback做事务处理:
                    2)MANAGED:表示把mybatis的事务处理委托给其他容器(可以是服务器软件、框架(spring))
            -->
            <transactionManager type="JDBC"/>

            <!--dataSource:表示数据源,连接数据库的
                type表示数据源的类型
                    1)POOLED表示使用连接池,mybatis会创建PooledDataSource类
                    2)UPOOLED表示不使用连接池,每次执行sql语句,先创建连接,执行sql,再关闭连接。
                                mybatis会创建一个UnPooledDataSource,管理Connection对象的使用
                    3)JNDI:java命名和目录服务(widows的注册表)
            -->
            <dataSource type="POOLED">
                <!--
                    driver、url、username、password是固定的不能自定义
                -->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
                <property name="username" value="root"/>
                <property name="password" value="abc1234."/>
            </dataSource>
        </environment>

        <!--
             测试环境
         -->
        <environment id="">
            <transactionManager type=""/>
            <dataSource type="">
                <property name="driver" value=""/>
                <property name="url" value=""/>
                <property name="username" value=""/>
                <property name="password" value=""/>
            </dataSource>
        </environment>

        <!--
             准生产环境
         -->
        <environment id="">
            <transactionManager type=""/>
            <dataSource type="">
                <property name="driver" value=""/>
                <property name="url" value=""/>
                <property name="username" value=""/>
                <property name="password" value=""/>
            </dataSource>
        </environment>

        <!--
             生产环境
         -->
        <environment id="">
            <transactionManager type=""/>
            <dataSource type="">
                <property name="driver" value=""/>
                <property name="url" value=""/>
                <property name="username" value=""/>
                <property name="password" value=""/>
            </dataSource>
        </environment>

    </environments>
    <!--sql mapper(sql映射文件)的位置-->
    <mappers>
        <!--一个mapper标签指定一个sql映射文件的位置
            从类路径开始的路径信息。 target/class(class后面开始的就是类路径)
        -->
        //第一种方式:指定多个mapper文件
        <mapper resource="com\bjpowernode\dao\StudentDao.xml"/>
        <mapper resource="com\bjpowernode\dao\OrderDao.xml"/>
        //第二种方式:使用包名,name=mapper文件所在的包名。(这个包所有xml文件一次性加载给mybatis)
        <!--mapper文件名称需和接口名称一样,区分大小写
        mapper文件和dao接口在同一目录-->
        <package name="com.bjpowernode.dao"/>
    </mappers>
</configuration>
错误类路径

正确的类路径

8)创建使用mybatis类(通过mybatis访问数据库)
①定义mybatis主配置文件名称
String config = "mybatis.xml";

声明主配置文件的路径

②读取主配置文件
读配置文件

InputStream in=Resources.getResourceAsStream(config);
③创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
④创建SqlSessionFactory对象
SqlSessionFactory factory=builder.build(in);
⑤【重要】获取SqlSession对象,从SqlSessionFactory中获取SqlSession对象
SqlSession sqlSession=factory.openSession();
⑥【重要】指定要执行的sql语句的表示。sql映射文件中的namesapce+“.”+标签的id值
String sqlId="com\bjpowernode\dao\StudentDao.java"+"."+"selectStudents";//查询操作
String sqlId="com\\bjpowernode\\dao\\StudentDao.java.insertStudents";//插入操作
⑦执行sql语句,通过sqlId找到语句
返回值为List的集合

List<Student> studentList = sqlSession.selectList(sqlId);//查询操作

//插入操作
Student student = new Student();
        student.setId(1004);
        student.setName("顾六");
        student.setEmail("xinlang@192.com");
        student.setAge(36);
        int nums = sqlSession.insert(sqlId,student);

MyBatis默认不是自动提交事务,所以在执行sql后,需要手工提交事务
sqlSession.commit();
或者给openSession()方法传true值
⑧输出结果
studentList.forEach(stu -> System.out.println(stu) );

lambda(拉姆表达式)语法
包含三部分:
1、一个括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数
2、一个箭头符号:->
3、方法体,可以是表达式和代码块。
(parameters) -> expression 或者 (parameters) -> { statements; }

for (Student stu:studentList){
            System.out.println("查询的学="+stu);
        }

foreach也叫增强for循环,是for循环的一个特殊简化版。
语法:
for(元素类型 元素名称:遍历数组(集合)(或者能进行迭代的)){
      语句
}

⑨关闭资源
sqlSession.close();

9)配置日志功能
在主配置文件的根标签下添加settings标签

    <!--settings:控制mybatis全局行为的-->
    <settings>
        <!--设置mybatis输出日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
  • 2.2MyBatis对象分析
    1)Resources:mybatis中的一个类,负责读取主配置文件。
    InputStream in= Resources.getResourceAsStream(配置文件地址);
    2)SqlSessionFactoryBuilder:创建SqlSessionFactory对象。
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    SqlSessionFactory factory=builder.build(in);
    3)SqlSessionFactory:重量级对象,程序创建一个对象耗时比较长,使用资源比较多。在整个项目中有一个就够了。
    SqlSessionFactory->接口,接口实现类->DefaultSqlSessionFactory
    SqlSessionFactory作用:获取SqlSession 对象。
    SqlSession sqlSession=factory.openSession();
    openSession()方法说明:
    ①openSession():无参,获取的是非自动提交事务的SqlSession对象。
    ②openSession(boolean):
    openSession(true)获取自动提交事务的SqlSession对象
    openSession(false)获取非自动提交事务的SqlSession对象
    4)SqlSession:是接口,定义了操作数据的方法。例如selectOne()、selectList()、insert()、update()、delete()、commit()......
    SqlSession的实现类DefaultSqlSession
    使用要求:SqlSession对象不是线程安全的,需要在方法内部使用,在执行sql语句之前要使用openSession()获取SqlSession对象。在执行完sql语句后,需要关闭它,执行SqlSession.close()。这样能保证它的使用是线程安全的。

  • 2.3MyBatis使用传统Dao开发

    • 使用工具类
//工具类
public class MyBatisUtils {

    /*因为静态块不能用,故需要在静态块外用变量factory保存SqlSessionFactory对象*/
    private  static SqlSessionFactory factory=null;
    static {
        //1.定义mybatis主配置文件名称,从类路径的根开始(target/class)
        String config = "mybatis.xml";
        InputStream in= null;
        try {
            //2.读取主配置文件
            in = Resources.getResourceAsStream(config);
            //3+4.使用SqlSessionFactoryBuilder创建SqlSessionFactory对象
            factory = new SqlSessionFactoryBuilder().build(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession(){
        //5.获取SqlSession对象,从SqlSessionFactory中获取SqlSession对象
        SqlSession sqlSession=null;
        if (factory != null) {
            sqlSession=factory.openSession();
        }
        return sqlSession;
    }

}

//测试类
    @Test
    public void testMyBatisUtils(){
        //5.从工具类获取SqlSession对象
        SqlSession sqlSession= MyBatisUtils.getSqlSession();
        //6.【重要】指定要执行的sql语句的表示。sql映射文件中的namesapce+“.”+标签的id值
        String sqlId="com\\bjpowernode\\dao\\StudentDao.java.insertStudents";
        //7.执行sql语句,通过sqlId找到语句
        Student student = new Student();
        student.setId(1005);
        student.setName("唐七");
        student.setEmail("Google@163.com");
        student.setAge(99);
        int nums = sqlSession.insert(sqlId,student);
        //mybatis默认不是自动提交事务,所以在执行sql后,需要手工提交事务
        sqlSession.commit();
        //8.输出结果
        System.out.println("成功插入" + nums + "条数据!");
        //9.关闭资源
        sqlSession.close();
    }
  • 使用传统Dao
//主配置文件—mybatis
<?xml version="1.0" encoding="UTF-8" ?>
<!--mybatis的主配置文件:主要定义了数据库的配置信息和sql映射文件的位置-->

<!--指定约束文件-->
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--根标签-->
<configuration>

    <!--settings:控制mybatis全局行为的-->
    <settings>
        <!--设置mybatis输出日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <!--环境配置:数据库的连接信息
        default:必须和某个environments的id值一致,
        告诉mybatis使用哪个数据库的连接信息。即访问哪个数据库
    -->
    <environments default="DbMybatis">
        <!--environment:一个数据库信息的配置
            id:一个唯一值,自定义,表示环境的名称
        -->
        <environment id="DbMybatis">
            <!--transactionManager:mybatis的事务类型
                type:JDBC(表示使用jdbc中的Connection对象的commit,rollback做事务处理)
            -->
            <transactionManager type="JDBC"/>
            <!--dataSource:表示数据源,连接数据库的
                type表示数据源的类型,POOLED表示使用连接池
            -->
            <dataSource type="POOLED">
                <!--
                    driver、url、username、password是固定的不能自定义
                -->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
                <property name="username" value="root"/>
                <property name="password" value="abc1234."/>
            </dataSource>
        </environment>
    </environments>
    <!--sql mapper(sql映射文件)的位置-->
    <mappers>
        <!--一个mapper标签指定一个sql映射文件的位置
            从类路径开始的路径信息。 target/class(class后面开始的就是类路径)
        -->
        <mapper resource="com\bjpowernode\dao\StudentDao.xml"/>
    </mappers>
</configuration>


//持久层Dao——sql映射文件StudentDao
<?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="com\bjpowernode\dao\StudentDao.xml">
    <!--查询操作-->
    <select id="selectStudents" resultType="com.bjpowernode.domain.Student">
        select id,name,email,age  from student order by id;
    </select>
</mapper>



//domain实体类——Student
package com.bjpowernode.domain;

public class Student {
    private Integer id;
    private String name;
    private String email;
    private Integer age;

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", age=" + age +
                '}';
    }

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}


//持久层Dao——接口StudentDao
package com.bjpowernode.dao;

import com.bjpowernode.domain.Student;

import java.util.List;

public interface StudentDao {
    List<Student> selectStudents();
}


//工具类utils—MyBatisUtils
package com.bjpowernode.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class MyBatisUtils {

    /*因为静态块不能用,故需要在静态块外用变量factory保存SqlSessionFactory对象*/
    private  static SqlSessionFactory factory=null;
    static {
        //1.定义mybatis主配置文件名称,从类路径的根开始(target/class)
        String config = "mybatis.xml";
        InputStream in= null;
        try {
            //2.读取主配置文件
            in = Resources.getResourceAsStream(config);
            //3+4.使用SqlSessionFactoryBuilder创建SqlSessionFactory对象
            factory = new SqlSessionFactoryBuilder().build(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession(){
        //5.获取SqlSession对象,从SqlSessionFactory中获取SqlSession对象
        SqlSession sqlSession=null;
        if (factory != null) {
            sqlSession=factory.openSession();
        }
        return sqlSession;
    }
}


//持久层Dao——实现类StudentDaoImpl
package com.bjpowernode.dao.Impl;

import com.bjpowernode.dao.StudentDao;
import com.bjpowernode.domain.Student;
import com.bjpowernode.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;

import java.util.List;

public class StudentDaoImpl implements StudentDao {
    @Override
    public List<Student> selectStudents() {
        //获取SqlSession对象
        SqlSession sqlSession=MyBatisUtils.getSqlSession();
        String sqlId="com\\bjpowernode\\dao\\StudentDao.xml.selectStudents";
        //执行sql语句,使用SqlSession类的方法
        List<Student>students=sqlSession.selectList(sqlId);
        //关闭资源
        sqlSession.close();
        return students;
    }
}


//测试类test—MyBatis
package com.bjpowernode;

import com.bjpowernode.dao.Impl.StudentDaoImpl;
import com.bjpowernode.dao.StudentDao;
import com.bjpowernode.domain.Student;
import org.junit.Test;

import java.util.List;

public class TestMyBatis {
    @Test
    public void testSelectStudent(){
        StudentDao dao=new StudentDaoImpl();
        List<Student>studentList=dao.selectStudents();
        for (Student stu:studentList
             ) {
            System.out.println(stu);
        }
    }
}


第3章 MyBatis框架Dao代理(核心)

List<Student> studentList = dao.selectStudent();调用
1.dao对象,类型是StudentDao,全限定名称是:com\bjpowernode\dao\StudentDao.java全限定名称和namespace是一样的。

2.方法名称,selectStudents,整个方法就是mapper文件中的id值,selectStudents

3.通过dao中方法的返回值也可以确定MyBatis要调用的sqlSession的方法
如果返回值是List,调用的是SqlSession.selectList()方法。
如果返回值是int,或者是非Lsit的,看mapper文件中的标签是<insert>、<update>就会调用SqlSession的insert、update等方法

mybatis的动态代理:mybatis根据dao方法调用,获取执行sql语句的信息。
mybatis根据你的dao接口,创建出一个dao接口的实现类,并创建这个类的对象。完成SqlSession调用方法,访问数据库。

    @Test
    public void testSelectStudent(){
        //使用getSqlSession方法调用MyBatisUtils工具类获取SqlSession对象
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        /*
          使用mybatis的动态代理机制,使用SqlSession.getMapper(dao接口)
          getMapper能获取dao接口对应的实现类对象
        */
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        //调用dao的方法,执行数据库的操作
        List<Student> students=dao.selectStudents();
        for(Student stu:students){
            System.out.println("学生="+stu);
        }
    }

3.1原理

1.动态代理:使用SqlSession.getMapper(dao接口.class)获取这个dao接口的对象。
2.传入参数:从Java代码中把数据传入到mapper文件的sql语句中。

3.2深入理解参数

3.21parameterType:

写在mapper文件中的一个属性,表示dao接口中方法的参数的数据类型。
例如StudentDao接口
public Student selectStudentById(Integer id)

属性parameterType它的值是java的数据类型全限定名称或者是mybatis定义的别名
例如: parameterType="java.lang.Integer"或 parameterType="int"

<select id="selectStudentById"  parameterType="java.lang.Integer"  resultType="com.bjpowernode.domain.Student">
        select id,name,email,age from student where id=#{id};
    </select>

不是必需的,因为mybatis通过反射机制能够找到接口参数的数据类型。

3.22传入一个简单参数:

简单类型:mybatis把java的基本数据类型和string都叫简单类型
在mapper文件获取简单类型的一个参数的值,使用语法:#{任意字符串}

//接口
public Student selectStudentById(Integer id)
//使用占位符
select id,name,email,age from student where id=#{id};
//传参
Student student = dao.selectStudentById(1005);

使用#{}后,mybatis执行sql是使用的jdbc中的PreparedStatement对象
由mybatis执行下面的代码
1.mybatis创建Connection、PreparedStatement对象

String sql="select id,name,email,age from student where id=?";
PreparedStatement pst=conn,preparedStatement(sql);
pst.setInt(1,1001);

2.执行slq封装为resultType="com.bjpowernod.domain.Student"这个对象

ResultSet rs=ps.executeQuery();
Student student = new Student();
while(rs.next()){
    //从数据库取表的一行数据,存到一个Java对象属性中
    student.setId(rs.getInt("id")); 
    student.setName(rs.getString("name")); 
    student.setEmail(rs.getString("email")); 
    student.setAge(rs.getInt("age")); 
}
return student;//赋给了 dao方法调用的返回值

3.23多个参数-使用@Param(必须掌握):

接口:
public List<Student> selectMulitParam(String name,Integer age)
在参数名前面使用:
@Param("参数名") 参数类型 参数

mybatis-多个参数的使用@Param-接口

位置:mapper文件中

    <select>
        select * from student where name=#{myname} or age=#{myage}
    </select>
mybatis-多个参数的使用@Param-映射文件
mybatis-多个参数的使用@Param-测试类

3.24多个参数-使用对象(必须掌握):

完整语法:#{实体类中属性名,javaType=类型名称,jdbcType=数据库类型}
javaType:指Java中属性数据类型
jdbcType:指数据库中的数据类型
例如:#{paramName,javaType=java.lang.String,jd
简化语法:#{实体类中属性名}
javaType、jdbcType的值mybatis能通过反射获取,不用提供

mybatis-多个参数的使用对象-实体类

mybatis-多个参数的使用对象-接口

mybatis-多个参数的使用对象-映射文件

mybatis-多个参数的使用对象-测试类
3.25多个参数-按位置(了解):

mybatis 3.4之前,使用#{0},#{1}
mybatis 3.4之后,使用#{arg0},#{arg1}

mybatis-多个参数的按位置传值-接口

mybatis-多个参数的按位置传值-映射文件

mybatis-多个参数的按位置传值-测试类
3.26多个参数-使用Map(了解):
mybatis-多个参数使用Map-接口

mybatis-多个参数使用Map-映射文件

mybatis-多个参数使用Map-测试类
3.27#和$:

'#'占位符:告诉mybatis使用实际的参数值替代。#{...}代替sql语句的“?”,这样更安全、迅速,能避免sql注入。


#的用法

$ 字符串替换:告诉mybatis使用这个符号包含的“字符串”替换所在位置。主要用在替换表面、列名,不同列排序等操作。

mybatis-多个参数使用$进行排序-接口
mybatis-多个参数使用$进行排序-映射文件
mybatis-多个参数使用$进行排序-测试类

# 与 $的区别:

  1. “#”使用?在sql语句中做占位,表示列的值。使用PreparedStatement执行sql,效率高、能避免sql注入更安全。

2."$"不适用占位符,是字符串连接方式,使用Statement对象执行sql,效率低、有sql注入的风险缺乏安全性。常用于替换表名或列名。

//#接口
public Student selectStudentById(Integer id);
//#映射文件
select id,name,email,age from student where id=#{id}
//#测试类
Student student = dao.selectStudentById(1005);
//#测试结果
select id,name,email,age from student where id=? 


//$接口
public Student selectStudentById(@Param("id") Integer id);
//$映射文件
select id,name,email,age from student where id=${id}
//$测试类
Student student = dao.selectStudentById(1005);
//$测试结果
select id,name,email,age from student where id=1005 
相当于
Strig sql="select id,name,email,age from student where id="+"1005 ";

3.3封装MyBatis输出结果(理解)

mybatis的输出结果:mybatis执行了sql语句,得到java对象。
resultType和resultMap二选一,不能同时用

3.3.1 resultType

resultType结果类型:指sql语句执行完毕后,数据转为指定的java对象类型。(java类型是任意的)

resultType结果类型的值:
1.类型的全限定名称。
2.类型的别名
1)定义自定义类型的别名:
第一种方式:
在主配置文件(mybatis.xml)中的根标签(<configuration>)下使用<typeAliases>标签

    <typeAliases>
        <!--
            第一种方式:
            可以指定一个类型一个自定义别名
            type:自定义类的全限定名称
            alias:别名
        -->
        <typeAlias type="com.bjpowernode.domain.Student" alias="stu"/>
    </typeAliases>

第二种方式:
在主配置文件(mybatis.xml)中的根标签(<configuration>)下使用<typeAliases>标签

    <typeAliases>
        <!--
            第二种方式:
            可以指定一个类型一个自定义别名
            name:包名,这个包中的所有类,类名就是别名(类型不区分大小写)
        -->
        <package name="com.bjpowernode.domain"/>
    </typeAliases>

返回Map
1)列名是map的key,列值是map的value
2)最多只能返回一行记录,多一行是错误

//接口
    Map<Object,Object> selectMap(int id);
//映射文件
    <select id="selectMap" resultType="java.util.Map">
         select id,name,email,age from student where id=#{id}
    </select>
//测试
    @Test
    public void testSelectMap(){
        //使用getSqlSession方法调用MyBatisUtils工具类获取SqlSession对象
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        /*
          使用mybatis的动态代理机制,使用SqlSession.getMapper(dao接口)
          getMapper能获取dao接口对应的实现类对象
        */
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        //调用dao的方法,执行数据库的操作
        Map<Object,Object> map=dao.selectMap(1005);
        System.out.println("map="+map);
    }

处理方式:
1.mybatis执行sql语句,然后mybatis调用类的无参数构造方法,创建对象。
2.mybatis把ResultSet指定列值赋给同名的属性。

<select id="selectMulitParam" resultType="com.bjpowernode.domain.Student">
    select id,name,email,age from student
</select>
//等价于jdbc
ResultSet rs=exeouteQuery("select id,name,email,age from student");
Student student=new Student();
while(rs.next()){
    student.setId(rs.getInt("id"));
    student.setName(rs.getString("name"));
}
3.3.2 resultMap

结果映射,指定列名和java对象的属性对应关系。
1.自定义列值赋给哪个属性
2.当列名和属性名不一样时,一定要使用resultMap


使用resultMap
3.3.3实体类属性名和列名不同的处理方式

1.使用列别名和<resultType>
resultType的默认原则是:同名的列值赋值给同名的属性,使用列别名(java对象的属性名)

2.使用<resultMap>

3.4模糊like

第一种模糊查询,在java代码指定like的内容

//接口
    /*第一种模糊查询,在java代码指定like的内容*/
    List<Student> selectLikeOne(String name);
//映射文件
    <select id="selectLikeOne" resultType="com.bjpowernode.domain.Student">
        select id,name,email,age from student where name like #{}
    </select>
//测试类
    @Test
    public void testSelectLikeOne(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        //准备号like的内容
        String name="%李%";
        List<Student> student=dao.selectLikeOne(name);
        for (Student stu:student) {
            System.out.println(student);
        }
        sqlSession.close();
    }

第二种模糊查询,在mapper文件中拼接like的内容

//接口
    /*name就是列值,在mapper中拼接like  “%“李”%”   */
    List<Student> selectLikeTwo(String name);
//映射文件
    <select id="selectLikeTwo" resultType="com.bjpowernode.domain.Student">
        select id,name,email,age from student where name like “%” #{} “%”
    </select>
//测试类
    @Test
    public void testSelectLikeTwo(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        //准备号like的内容
        String name="李";
        //调用dao的方法,执行数据库的操作
        List<Student> student=dao.selectLikeTwo(name);
        for (Student stu:student) {
            System.out.println(student);
        }
        sqlSession.close();
    }

第4章 MyBatis框架动态SQL(理解)

动态sql:sql的内容是变化的,可以根据条件获取到不同的sql语句,主要是where部分发生变化。

4.1环境准备

4.2动态sql之<if>

<if>条件判断语句
语法:
<if test="判断Java对象的属性值">
部分sql语句
</if>

接口

动态sql-if-接口

mapper文件

动态sql-if-mapper文件

测试类

动态sql-if-测试类

注意!:当name存在age不存在时,程序正常运行;当age存在name不存在时,程序报错。因为where or age>1中多了or,出现语法错误。
解决方法:

动态sql-if-解决-因条件而产生的语法问题1

动态sql-if-解决-因条件而产生的语法问题2

4.3动态sql之<where>

<where>用来包含多个<if>的,当多个if有一个成立,<where>会自动增加一个where关键字,并去掉if中多余的and、or等从而 解决<if>因条件不足而产生的语法问题

动态sql-where-接口
动态sql-where-mapper文件
动态sql-where-测试类

4.4动态sql之<foreach>

<foreach>循环jave中的数组,List集合的。主要用在sql的in语句中。
collection:表示接口中的方法参数的类型,如果是数组使用array,如果是list集合使用list
item:自定义的,表示数组和集合成员的变量
open:循环开始的字符
close:循环结束的字符
separator:集合成员之间的分隔符

foreach使用1,List<Integer>

//接口
    List<Student> selectStudentForeachOne(List<Integer> idlist);
//mapper文件
    <select id="selectStudentForeachOne" resultType="com.bjpowernode.domain.Student">
        select * from student where id in
        <foreach collection="list" item="myid" open="(" close=")" separator=",">
            #{myid}
        </foreach>
    </select>
//测试类
    @Test
    public void testSelectStudentForeachOne(){
        SqlSession sqlSession= MybatisUtils.getSqlSession();
        StudentDao dao=sqlSession.getMapper(StudentDao.class);

        List<Integer> list=new ArrayList<>();
        list.add(1001);
        list.add(1002);
        list.add(1003);

        List<Student> students=dao.selectStudentForeachOne(list);
        for(Student stu:students){
            System.out.println("foreach-one==="+stu);
        }
        sqlSession.close();
    }

foreach使用2,List<Student>

//接口
    List<Student> selectStudentForeachTwo(List<Student> stulist);
//mapper文件
    <select id="selectStudentForeachTwo" resultType="com.bjpowernode.domain.Student">
        select * from student where id in
        <foreach collection="list" item="stu" open="(" close=")" separator=",">
            #{stu.id}
        </foreach>
    </select>
//测试类
    @Test
    public void testSelectStudentForeachTwo(){
        SqlSession sqlSession= MybatisUtils.getSqlSession();
        StudentDao dao=sqlSession.getMapper(StudentDao.class);

        List<Student> stulist=new ArrayList<>();
        Student s1=new Student();
        s1.setId(1005);
        stulist.add(s1);

        s1=new Student();
        s1.setId(1006);
        stulist.add(s1);

        List<Student> students=dao.selectStudentForeachTwo(stulist);
        for(Student stu:students){
            System.out.println("foreach-two==="+stu);
        }
        sqlSession.close();
    }

4.5动态sql之代码片段

步骤:
1.先定义
<sql id="自定义名称(唯一)">
sql语句、表名、字段等
</sql>


动态sql-代码片段-定义sql

2.再使用
<include refid="id的值" />


动态sql-代码片段-使用sql

第5章 MyBatis配置文件(了解)

1.数据库的属性配置文件:

把数据库连接信息放到一个单独的文件中。和mybatis主配置文件分开。目的是便于修改、保存、处理多个数据库的信息。
1)在resources目录中定义一个属性配置文件,×××.properties,例如 jdbc.properties
在属性配置文件中,定义数据格式:key-value
key:一般使用,做多级目录的
例如 jdbc.mybatis.driver , jdbc.driver , mydriver
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm
jdbc.username=root
jdbc.password=abc1234.

定义属性配置文件

2)在mybatis的主配置文件,使用<property>指定文件的位置,在需要使用值的地方,${key}

指定属性配置文件位置

使用属性配置文件

2.mapper文件

1)使用<mapper>指定路径
2)使用<package>指定路径

<!--第一种方式:指定多个mapper文件-->
<mapper resource="com\bjpowernode\dao\StudentDao.xml"/>
<mapper resource="com\bjpowernode\dao\OrderDao.xml"/>
<!--
第二种方式:使用包名,name=mapper文件所在的包名。
(这个包所有xml文件一次性加载给mybatis)
要求:
mapper文件名称需和接口名称一样,区分大小写
mapper文件和dao接口在同一目录
-->
<package name="com.bjpowernode.dao"/>

第6章 扩展

PageHelpe 支持多种数据库:做数据分页的

1)加入maven依赖

<!--maven坐标-->
<dependency>
  <groupId>com.github.pagehelper</groupId>
  <artifactId>pagehelper</artifactId>
  <version>5.1.10</version>
</dependency>

2)加入plugin配置在主配置文件

<!--加入plugin配置在主配置文件
的<environments>标签之前加入-->
<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor"/>
</plugins>
调用PageHelpe 对象分页.png
@Test
public void testSelectPageHelpe(){
    SqlSession sqlSession= MybatisUtils.getSqlSession();
    StudentDao dao=sqlSession.getMapper(StudentDao.class);
    /*加入PageHelpe的方法,分页
    * pageNum:从第几页开始
    * pageSize:一页中有多少行数据
    * 会通过select count(*)得到有多少数据和可以分几页
    * */
    PageHelper.startPage(1,3);
    List<Student>students=dao.selectPageHelpe();
    for(Student stu:students){
        System.out.println("PageHelpe=="+stu);
    }
    sqlSession.close();
}

笔记来源:B站动力节点 mybatis学习视频

视频链接:https://www.bilibili.com/video/BV185411s7Ry

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

推荐阅读更多精彩内容