Mybatis学习笔记

MyBatis 框架

前言

以下笔记内容来自B站动力节点MyBatis教程实战精讲的课程内容,我自己跟着视频的内容对原有笔记进行了适当的增改,仅供参考

第一章 框架的概述

1.三层架构

mvc:web开发中,使用mvc架构模式。 m:数据, v:视图, c:控制器。

​ c控制器: 接收请求,调用service对象,显示请求的处理结果。 当前使用servlet作为控制器

​ v视图: 现在使用jsp, html,css,js。 显示请求的处理结果,把m中数据显示出来。

​ m数据: 来自数据库mysql, 来自文件,来自网络

mvc作用:

​ 1)实现解耦合。

​ 2)让mvc 各负其职。

​ 3)使得系统扩展性更好,更容易维护。

三层架构:

1.界面层(视图层、表现层):接收用户的请求,调用service, 显示请求的处理结果的。 包含了jsp,html,servlet等对象。 对应的包controller,

2.业务逻辑层:处理业务逻辑, 使用算法处理数据的。 把数据返回给界面层。 对应的是service包,和包中的很多的XXXService类。 例如: StudentService , OrderService, ShopService

3.持久层(数据库访问层):访问数据库,或者读取文件,访问网络。获取数据。 对应的包是dao。 dao包中很多的StudentDao, OrderDao, ShopDao等等。

2. 三层架构请求的处理流程

用户发起请求---->界面层----->业务逻辑层---->持久层---->数据库(mysql)

3. 为什么要使用三层?

1,结构清晰、耦合度低, 各层分工明确
2,可维护性高,可扩展性高
3,有利于标准化
4,开发人员可以只关注整个结构中的其中某一层的功能实现
5,有利于各层逻辑的复用

4. 三层架构模式和框架

每一层对应着一个框架

1)界面层—SpringMVC框架

2)业务层—Spring框架

3)持久层—MyBatis框架

5 .框架

  1. 什么是框架(framework)

框架:就是一个软件, 完成了部分的功能。 软件中的类和类之间的方法调用都已经规定好了。 通过这些可以完成某些功能。 框架看做是模版。

框架是可以升级的,改造的。 框架是安全的。

框架是对某一个方面有用的,不是全能的。

6. 框架解决的问题

1)框架能实现技术的整合。

2)提供开发的效率。 降低难度。

7. jdbc访问数据库的优缺点

优点:

  1. 直观,好理解

缺点:

  1. 创建很多对象 Connection ,Statement, ResultSet
  2. 注册驱动
  3. 执行sql语句
  4. 把ResultSet转为 Student , List集合。
  5. 关闭资源
  6. sql语句和业务逻辑代码混在一起

8 MyBatis框架

什么 mybatis: 是一个持久层框架, 原名是ibatis, 2013改名为 MyBatis. MyBatis可以操作数据库,对数据执行增删改查。 看做是高级的jdbc。 解决jdbc的缺点。

mybatis能做什么?

1) 注册驱动 。

2) 创建jdbc中使用的Connection, Statement,ResultSet

  1. 执行sql语句, 得到ResultSet

  2. 处理ResultSet, 把记录集中的数据转为java对象, 同时还能把java对象放入到List集合。

5)关闭资源

6)实现sql语句和java代码的解耦合。

mybatis的文档: https://mybatis.org/mybatis-3/zh/index.html

第二章 MyBatis入门

2.0.1 maven中的配置文件

这里需要注意一下mysql驱动的版本

<dependencies>    
	<dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.9</version>
    </dependency>
    <!-- mysql驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.16</version>
    </dependency>
</dependencies>


<build>
    <!-- 资源插件,处理src/main/java目录中的xml文件 -->
    <resources>
        <resource>
            <directory>src/main/java</directory><!--所在的目录-->
            <includes><!--包括目录下的.properties,.xml  文件都会扫描到-->
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
    </resources>
 </build>

2.1 第一个例子

实现步骤:

0.创建student表(id,name,email,age)

1.新建maven项目

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.5.9</version>
</dependency>

2.修改pom.xml

1)加入依赖 mybatis依赖, mysql驱动, junit

<dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.9</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.16</version>
</dependency>

2)在加入资源插件

<!-- 资源插件,处理src/main/java目录中的xml文件 -->
<resources>
    <resource>
        <directory>src/main/java</directory><!--所在的目录-->
        <includes><!--包括目录下的.properties,.xml  文件都会扫描到-->
            <include>**/*.properties</include>
            <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
    </resource>
</resources>

3.创建实体类Student。定义属性, 属性名和列名保持一致

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

    @Override
    public String toString() {
        return "StudentDao{" +
                "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;
    }
}

4.创建Dao接口, 定义操作数据库的方法。

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

5.创建xml文件(mapper文件), 写sql语句。

mybatis框架推荐是把sql语句和java代码分开

mapper文件:定义和dao接口在同一目录, 一个表一个mapper文件

<?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">
<!--
    1.约束文件
     http://mybatis.org/dtd/mybatis-3-mapper.dtd
     作用:定义和限制当前文件中可以使用的标签和属性,以及标签出现的顺序

    2.mapper:根标签
     namespace:命名空间,必须有值,且是唯一值;推荐使用Dao接口的全限定名称
     作用:参与识别sql语句
    3.在mapper里可以写<insert> <update> <delete> <select>
    -->
<mapper namespace="dao.StudentDao">
    <!--
    查询所有学生
    id:要执行的sql语句的唯一标识,是一个自定义字符串,推荐使用dao接口中的方法名称
    resultType:告诉mybatis,执行sql语句后,把数据赋值给哪个类型的Java对象
     -->
    <select id="selectStudents" resultType="bean.Student">
        select id,name,email,age from student
    </select>

</mapper>

6.创建mybatis的主配置文件(xml文件):有一个, 放在resources目录下

该主配置文件不用过多关心,后续不用

1)定义创建连接实例的数据源(DataSource)对象

  1. 指定其他mapper文件的位置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <!-- 配置数据源,创建connection对象 -->
            <dataSource type="POOLED">
                <!-- 驱动内容 -->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <!-- 连接数据库的url -->
                <property name="url" value="jdbc:mysql://localhost:3306/${数据库名字}?characterEncoding=utf8&amp;
                useUnicode=true&amp;serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 指定其他mapper文件的位置 找到其他mapper文件的目的是找到其他文件的sql语句 -->
    <mappers>
        <!--
        使用mapper的resource属性指定mapper文件的路径
        用/分隔
        从类路径开始:target/classes(类路径)
         -->
        <mapper resource="dao/StudentDao.xml"/>
    </mappers>
</configuration>

7.创建测试的内容。

使用main方法,测试mybatis访问数据库

也可以使用junit 访问数据库

//1.mybatis 主配置文件
String config = "mybatis-config.xml";
//2.读取配置文件
InputStream in = Resources.getResourceAsStream(config);
//3.创建 SqlSessionFactory 对象,目的是获取 SqlSession
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//4.【重要】获取 SqlSession,SqlSession 能执行 sql 语句
SqlSession session = factory.openSession();
//5.【重要】执行 SqlSession 的 selectList()    sql语句:映射文件中的namespace+"."+标签的id值
List<Student> studentList =
    session.selectList("dao.StudentDao.selectStudents");
//6.循环输出查询结果
studentList.forEach( student -> System.out.println(student));
//7.关闭 SqlSession,释放资源
session.close();

8.配置日志功能

在mybatis主配置文件中加入

<settings>
 <setting name="logImpl" value="STDOUT_LOGGING" />
</settings>

2.2 概念

1.自动提交:当你的 sql语句执行完毕后, 提交事务。 数据库更新操作之间保存到数据

2.手动(手工)提交事务:在你需要提交事务的位置, 执行方法,提交事务或者回顾事务。

2.3 MyBatis的一些对象

1) Resources : mybatis框架中的对象, 一个作用读取 主配置信息。

InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");

2)SqlSessionFactoryBuilder:负责创建SqlSessionFactory对象

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);

3)SqlSessionFactory: 重要对象

SqlSessionFactory是重量级对象:创建此对象需要使用更多的资源和时间。 在项目中有一个就可以了。

SqlSessionFactory接口:作用是SqlSession的工厂, 就是创建SqlSession对象。

DefaultSqlSessionFactory实现类

public class DefaultSqlSessionFactory implements SqlSessionFactory { } 

SqlSessionFactory接口中的方法

openSession(): 获取一个默认的SqlSession对象, 默认是需要手工提交事务的。

openSession(boolean): boolean参数表示是否自动提交事务。

​ true: 创建一个自动提交事务的SqlSession

​ false: 等同于没有参数的openSession

  1. SqlSession对象

SqlSession对象是通过SqlSessionFactory获取的。 SqlSession本身是接口

DefaultSqlSession: 实现类

public class DefaultSqlSession implements SqlSession { }

SqlSession作用是提供了大量的执行sql语句的方法:

selectOne:执行sql语句,最多得到一行记录,多余1行是错误。
selectList:执行sql语句,返回多行数据
selectMap:执行sql语句的,得到一个Map结果
insert:执行insert语句
update:执行update语句
delete:执行delete语句
commit:提交事务
rollback:回顾事务

注意SqlSession对象不是线程安全的, 使用的步骤:

①:在方法的内部,执行sql语句之前,先获取SqlSession对象

②:调用SqlSession的方法,执行sql语句

③:关闭SqlSession对象,执行SqlSession.close()

2.4 使用工具类和模版

1)创建工具类

public class MyBatisUtils { 
    //定义  SqlSessionFactory
    private static SqlSessionFactory factory = null;
    //使用 静态块 创建一次  SqlSessionFactory 
    static {
        String config = "mybatis-config.xml";
        InputStream in = null;
        try {
            in = Resources.getResourceAsStream(config);
            factory = new SqlSessionFactoryBuilder().build(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取session对象
     * @return session对象
     */
    public static SqlSession getSqlSession(){
        SqlSession session = null;
        if (factory != null){
            session = factory.openSession(true);
        }
        return session;
    }
}

2 )创建模版,mapper文件模版和mybatis主配置文件模版

创建模版的步骤:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NBL85tUt-1642234070725)(images/image-20201019094212830.png)]

创建模版文件:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j2QZC7Pb-1642234070727)(images/image-20201019094359625.png)]

创建文件选择使用的模版:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hTGnFlzL-1642234070728)(images/image-20201019094616208.png)]

第三章 MyBatis的Dao代理(核心)

3.1 dao代理(动态代理)

3.1.1 mybatis提供代理:

mybatis创建Dao接口的实现类对象, 完成对sql语句的执行。 mybatis创建一个对象代替你的 dao实现类功能。

3.1.2 使用mybatis代理要求

1)mapper文件中的namespace 一定dao接口的全限定名称

2)mapper文件中 标签的id是dao接口方法名称

3.1.3 mybatis代理实现方式

使用SqlSession对象的方法 getMapper(dao.class)

例如: 现在有 StudentDao接口。

SqlSession session  = MyBatisUtils.getSqlSession();
StudentDao dao  = session.getMapper(StudentDao.class);
Student student = dao.selectById(1001);


//上面代码中
StudentDao dao  = session.getMapper(StudentDao.class);
等同于
StudentDao dao  = new StudentDaoImpl();

3.2 理解参数

理解参数是: 通过java程序把数据传入到mapper文件中的sql语句。 参数主要是指dao接口方法的形参

3.2.1 parameterType(可以不写)

parameterType:表示参数的类型, 指定dao方法的形参数据类型。 这个形参的数据类型是给mybatis使用。 mybatis在给sql语句的参数赋值时使用。 PreparedStatement.setXXX( 位置, 值)

第一个用法: java类型的全限定类型名称   parameterType="java.lang.Integer"
第二个用法: mybatis定义的java类型的别名  parameterType="int"

parameterType:mybatis通过反射机制可以获取 dao接口方法参数的类型, 可以不写

<select id="selectById"  parameterType="integer"
                 resultType="com.bjpowernode.domain.Student">
   select id,name,email,age from student where id=#{studentId}
</select>

3.2.2 dao接口方法是一个简单类型的参数

//dao接口的方法形参是一个简单类型的
//简单类型: java基本数据类型和String
Student selectByEmail(String email);
<!--
   dao接口是一个简单类型的参数
   mapper文件,获取这个参数值,使用#{任意字符}
-->
<select id="selectByEmail" resultType="com.bjpowernode.domain.Student">
    select id,name,email,age from student where email=#{studentEmail}
</select>

3.2.3 dao接口方法有多个简单类型的参数

@Param: 命名参数, 在方法的形参前面使用的, 定义参数名。 这个名称可以用在mapper文件中。

dao接口,方法的定义

/*
  多个简单类型的参数
  使用@Param命名参数, 注解是mybatis提供的
  位置:在形参定义的前面
  属性:value 自定义的参数名称
 */
List<Student> selectByNameOrAge(@Param("myname") String name,
                                @Param("myage") Integer age);

mapper文件

<!--
   多个简单类型的参数.
   当使用了@Param命名后,例如@Param("myname").
   在mapper中,使用#{命名的参数}, 例如 #{myname}
-->
<select id="selectByNameOrAge" resultType="com.bjpowernode.domain.Student">
    select id,name,email,age from student where name=#{myname} or age=#{myage}
</select>

3.2.4 dao接口方法使用一个对象作为参数

方法的形参是一个java对象。这个java对象表示多个参数。使用对象的属性值作为参数使用

java对象

public class Student {
    private Integer id;
    private String name;
    private String email;
    private Integer age;
    //set|get方法
}

public class QueryParam {
    private Object p1;
    private Object p2;
    //set|get方法
}

dao接口中的方法定义

/*
 * 一个java对象作为参数( 对象由属性, 每个属性有set,get方法)
 */
List<Student> selectByObject(Student student);

List<Student> selectByQueryParam(QueryParam param);

mapper文件

<!--
   一个java对象作为方法的参数,使用对象的属性作为参数值使用
   简单的语法: #{属性名} , mybatis调用此属性的getXXX()方法获取属性值
-->
<select id="selectByObject" resultType="com.bjpowernode.domain.Student">
    select id,name,email,age from student where name=#{name} or age=#{age}
</select>

<select id="selectByQueryParam" resultType="com.bjpowernode.domain.Student">
     select id,name,email,age from student where name=#{p1} or age=#{p2}
</select>

<!--
负责的语法格式: #{属性名,javaType=java类型的全限定名称,jdbcType=mybatis中定义列的数据类型}
过于麻烦,了解即可
-->
<select id="selectByObject" resultType="com.bjpowernode.domain.Student">
        select id,name,email,age from student where
        name=#{name,javaType=java.lang.String,jdbcType=VARCHAR}
        or
        age=#{age,javaType=java.lang.Integer,jdbcType=INTEGER}
</select>

3.2.5 dao接口中多个简单类型的参数,使用位置(了解)

参数位置: dao接口中方法的形参列表,从左往右,参数位置是 0 , 1, 2…

语法格式:#{arg0} ,#{arg1}

dao接口的方法

/*
   使用位置,获取参数
 */
List<Student> selectByPosition(String name,Integer age);
<!--
   mybatis版本是 3.5.1
   使用位置获取参数值, dao接口方法是多个简单类型的参数
   语法: #{arg0}, #{arg1}....
-->
<select id="selectByPosition" resultType="com.bjpowernode.domain.Student">
    select id,name,email,age from student where name=#{arg0} or age=#{arg1}
</select>

3.2.6 dao接口参数是一个Map(了解)

map作为dao接口的参数, 使用 key 获取参数值,mapper文件中,语法格式 #{key}

/*
   使用Map作为参数
 */
List<Student> selectStudentByMap(Map<String,Object> map);

mapper文件

<!--
   使用Map传递参数,
   在mapper文件中,获取map的值,是通过key获取的,语法:#{key}
-->
<select id="selectStudentByMap" resultType="com.bjpowernode.domain.Student">
     select id,name,email,age from student where name=#{myname} or age=#{myage}
</select>

测试,调用方法的位置

@Test
public void testSelectByMap(){
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    StudentDao dao  = sqlSession.getMapper(StudentDao.class);

    //使用map传递参数
    Map<String,Object> data = new HashMap<>();
    data.put("myname", "李思思");
    data.put("myage", 20);
    List<Student> students = dao.selectStudentByMap(data);

    students.forEach( stu-> System.out.println("stu="+stu));
    sqlSession.close();

}

3.3 #和$的区别

3.3.1 # 占位符

语法: #{字符}

mybatis处理#{} 使用jdbc对象是 PrepareStatment对象

<select id="selectById"  parameterType="integer"
             resultType="com.bjpowernode.domain.Student">
    select id,name,email,age from student where id=#{studentId}
</select>

mybatis出创建PrepareStatement对象,执行sql语句
String sql=" select id,name,email,age from student where id=?";
PrepareStatement pst = conn.prepareStatement(sql);
pst.setInt(1,1001);  //传递参数
ResultSet rs  = pst.executeQuery(); //执行sql语句


#{}特点:

1)使用的PrepareStatement对象,执行sql语句,效率高。

2)使用的PrepareStatement对象,能避免sql语句, sql语句执行更安全。

3) #{} 常常作为 列值使用的, 位于等号的右侧, #{}位置的值和数据类型有关的。

3.3.2 $ 占位符

语法 : ${字符}

mybatis执行${}占位符的sql语句

<select id="selectById"  parameterType="integer"
             resultType="com.bjpowernode.domain.Student">
    select id,name,email,age from student where id=${studentId}
</select>	

${} 表示字符串连接, 把sql语句的其他内容和 ${}内容使用 字符串(+) 连接的方式连在一起
String sql="select id,name,email,age from student where id=" + "1001";

mybatis创建Statement对象, 执行sql语句。
Statement stmt  = conn.createStatement(sql);
ResultSet rs  = stmt.executeQuery();

${} 的特点

1)使用Statement对象,执行sql语句,效率低

2)${}占位符的值,使用的字符串连接方式, 有sql注入的风险。 有代码安全的问题

  1. ${} 数据是原样使用的, 不会区分数据类型。

4)${} 常用作 表名或者列名, 在能保证数据安全的情况下使用 ${}

总结

#{}使用的PrepareStatement对象,执行sql语句,效率高

#{}能避免sql注入,更安全

#{}使用占位符

${}使用字符串连接的方式

${}使用Statement对象执行sql,效率较低

${}有sql注入风险,缺乏安全性

3.4 封装MyBatis输出结果

封装输出结果: MyBatis执行sql语句,得到ResultSet, 转为java对象。

讲两个 resultType, resultMap

resultType和resultMap不能一起用

3.4.1 resultType

resultType属性: 在执行select时使用, 作为标签的属性出现的。

resultType:表示结果类型 , mysql执行sql语句,得到java对象的类型。 它的值有两种

​ 1) java类型的全限定名称 。 2)使用别名

全限定名称

1) resultType:表示java自定义对象

Student selectById(Integer id);

<select id="selectById"  parameterType="integer"
             resultType="com.bjpowernode.domain.Student">
    select id,name,email,age from student where id=#{studentId}
</select>

resultType:现在使用java类型的全限定名称。 表示的意思 mybatis执行sql,把ResultSet中的数据转为Student类型的对象。  mybatis会做以下操作:
1. 调用com.bjpowernode.domain.Student的无参数构造方法,创建对象。
    Student student = new Student(); //使用反射创建对象
2. 同名的列赋值给同名的属性。
    student.setId( rs.getInt("id"));
    student.setName(rs.getString("name"));
3. 得到java对象, 如果dao接口返回值是List集合, mybatis把student对象放入到List集合。


所以执行 Student mystudent = dao.selectById(1001); 得到 数据库中 id=1001这行数据, 
这行数据的列值, 付给了mystudent对象的属性。 你能得到mystudent对象。 就相当于是 id=1001这行数据。



2)resultType表示简单类型

dao方法

long countStudent();

mapper文件

<!--
  执行sql语句,得到是一个值(一行一列)
-->
<select id="countStudent" resultType="java.lang.Long">
    select count(*) from student
</select>

3) resultType:表示一个map结构

//查询结果返回是一个Map
Map<Object,Object> selectMap(@Param("stuid") Integer id);
<!--
   执行sql得到一个Map结构数据, mybatis执行sql,把ResultSet转为map
   sql执行结果, 列名做map的key , 列值作为value
   sql执行得到是一行记录,转为map结构是正确的。

   dao接口返回是一个map, sql语句最多能获取一行记录,多余一行是错误

-->
<select id="selectMap" resultType="java.util.HashMap">
    select id,name,email from student where id != #{stuid}
</select>
别名

在mybatis主配置文件中加入typeAliases标签

的name属性是包名,表示这个包中的所有类,以类名作为别名

<typeAliases>
    <!-- 设置别名后,bean.Student别名为Student -->
    <package name="bean"
</typeAliases>

3.4.2 resultMap

resultMap: 结果映射。 自定义列名和java对象属性的对应关系。 常用在列名和属性名不同的情况。

用法:

1.先定义 resultMap标签, 指定列名和属性名称对应关系

2.在select标签使用resultMap属性,指定上面定义的resultMap的id值

<!--使用resultMap定义列和属性的关系-->
<!--定义resultMap
    id:给resultMap的映射关系起个名称,唯一值
    type:java类型的全限定名称
-->
<resultMap id="customMap" type="com.bjpowernode.vo.CustomObject">

    <!--定义列名和属性名的对应-->
    <!--主键类型使用id标签-->
    <id column="id" property="cid" />
    <!--非主键类型使用result标签-->
    <result column="name" property="cname" />
    <!--列名和属性名相同不用定义-->
    <result column="email" property="email" />
    <result column="age" property="age" />
</resultMap>

<!--使用resultMap属性,指定映射关系的id
    resultMap和resultType 不能同时使用, 二选一。
-->
<select id="selectById2" resultMap="customMap">
  select id,name,email,age from student where id=#{stuid}
</select>

3.5 自定义别名

mybatis提供的对java类型定义简短,好记名称。

自定义别名的步骤:

1)在mybatis主配置文件,使用 typeAliases标签声明别名

2)在mapper文件中, resultType=“别名”

声明别名(mybatis主配置文件)

<typeAliases>
    <!--第一种语法格式
        type:java类型的全限定名称(自定义类型)
        alias:自定义别名
    -->
    <typeAlias type="com.bjpowernode.domain.Student" alias="stu" />

</typeAliases>

mapper文件中使用

resultType="别名"
<select id="selectById"  parameterType="integer" resultType="stu">
    select id,name,email,age from student where id=#{studentId}
</select>

3.6 列名和java对象属性名称不一样解决方式

1) 使用resultMap: 自定义列名和属性名称对应关系

2)使用resultType: 直接在sql语句中使用列别名(as),让别名和java对象属性名称一样

3.7 like

第一种方式: 在java程序中,把like的内容组装好。 把这个内容传入到sql语句

//like第一种方式
List<Student> selectLikeOne(@Param("name") String name);

mapper

<!--like第一种方式-->
<select id="selectLikeOne" resultType="com.bjpowernode.domain.Student">
    select * from student where name like #{name}
</select>

执行like

@Test
public void testLikeOne(){
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    StudentDao dao  = sqlSession.getMapper(StudentDao.class);

    String name="%李%";
    List<Student> students = dao.selectLikeOne(name);

    sqlSession.close();

    students.forEach( stu-> System.out.println(stu));
}

第二种方式: 在sql语句,组织like的内容。

sql语句like的格式: where name like “%“空格#{name}空格”%”

//like第二种方式
List<Student> selectLikeTwo(@Param("name") String name);
<!--like第二种方式-->
<select id="selectLikeTwo" resultType="com.bjpowernode.domain.Student">
    select * from student where name like "%" #{name} "%"
</select>
@Test
public void testLikeTwo(){
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    StudentDao dao  = sqlSession.getMapper(StudentDao.class);

    String name="李";
    List<Student> students = dao.selectLikeTwo(name);

    sqlSession.close();

    students.forEach( stu-> System.out.println(stu));
}

第四章 动态sql(核心)

什么是动态sql: 同一个dao的方法, 根据不同的条件可以表示不同的sql语句, 主要是where部分有变化

使用mybatis提供的标签,实现动态sql的能力, 主要讲 if ,where ,foreach, sql。

使用动态sql的时候, dao方法的形参使用java对象。

什么时候使用动态sql:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L60ffStm-1642234070740)(images/image-20201020114831474.png)]

4.1 if 标签

语法:

<if test="boolean判断结果">
   sql 代码
</if>


在mapper文件中
<select id="selectStudent" resultType="com.bjpwoernode.domain.Student">
      select *from student
      <if test="条件">
          sql语句
      </if>
      <if test="条件">
          sql语句
      </if>
</select>

例子:

List<Student> selectIf(Student student);
<!--if
    test: 使用对象的属性值作为条件
    &lt;代表小于号(<)
    &gt;代表大于符号(>)
    &le;表示小于或等于符号(<=)
    &ge;表示大于或等于符号(>=)
-->
<select id="selectIf" resultType="com.bjpowernode.domain.Student">
    select * from student
    <!-- 加入该条件,防止语法错误报异常 -->
    where id=-1
    <if test="name !=null and name!=''">
       or  name = #{name}
    </if>

    <if test="age >0">
        or age &lt; #{age}
    </if>
</select>

4.2 where 标签

使用if标签时,容易引起sql语句语法错误。 使用where标签解决if产生的语法问题。

使用时 where ,里面是一个或多个if 标签, 当有一个if标签 判断条件为true, where标签会转为 WHERE 关键字附加到sql语句的后面。 如果 if 没有一个条件为true , 忽略where和里面的if。

where标签删除 和他最近的or 或者 and。

语法:
<where>
    <if test="条件1">sql语句1</if>
    <if test="条件2">sql语句2</if>
</where>

例子:

//where
List<Student> selectWhere(Student student);
<!--where-->
<select id="selectWhere" resultType="com.bjpowernode.domain.Student">
    select * from student
    <where>
        <if test="name !=null and name!=''">
            or  name = #{name}
        </if>

        <if test="age >0">
            or age &lt; #{age}
        </if>
    </where>

</select>

4.3 foreach 循环

使用foreach可以循环数组,list集合, 一般使用在in语句中。

语法:

< foreach collection="集合类型" open="开始的字符" close="结束的字符"
          item="集合中的成员" separator="集合成员之间的分隔符">
              #{item 的值}
</ foreach>

标签属性:
collection: 表示,循环的对象是 数组, 还是list集合。  如果dao接口方法的形参是 数组, 
             collection="array" ,如果dao接口形参是List, collection="list"

open:循环开始时的字符。  sql.append("(");
close:循环结束时字符。  sql.append(")");
item:集合成员, 自定义的变量。   Integer item  = idlist.get(i);// item是集合成员
separator:集合成员之间的分隔符。  sql.append(","); //集合成员之间的分隔符
#{item 的值}:获取集合成员的值。

第一种方式:

//foreach-1
List<Student> selectForeachOne(List<Integer> idlist);


<!--foreach第一种方式, 循环简单类型的List-->
<select id="selectForeachOne" resultType="com.bjpowernode.domain.Student">
      select * from student
        <if test="list !=null and list.size>0">
            where id in
            <foreach collection="list" open="(" close=")" separator="," item="myid">
                  #{myid}
            </foreach>
        </if>
</select>

@Test
public void testSelectForeachOne(){
        //1.获取SqlSession
        SqlSession session = MyBatisUtil.getSqlSession();
        //2.获取dao的代理
        StudentDao dao = session.getMapper(StudentDao.class);


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


        List<Student> students  = dao.selectForeachOne(idlist);

        students.forEach( stu-> System.out.println("stu=="+stu));
        //3.关闭SqlSession对象
        session.close();
    }

第二种方式:

//foreach-2
List<Student> selectForeachTwo(List<Student> studentList);

<!--foreach第二种方式, 循环的List<Student>-->
<select id="selectForeachTwo" resultType="com.bjpowernode.domain.Student">
        select * from student
        <if test="list != null and list.size>0">
            where id in
            <foreach collection="list" open="(" close=")" separator="," item="stu">
                  #{stu.id}
            </foreach>
        </if>
</select>
            
 @Test
 public void testSelectForeachTwo(){
        //1.获取SqlSession
        SqlSession session = MyBatisUtil.getSqlSession();
        //2.获取dao的代理
        StudentDao dao = session.getMapper(StudentDao.class);


        List<Student> list  = new ArrayList<>();
        Student s1 = new Student();
        s1.setId(1001);

        Student s2 = new Student();
        s2.setId(1002);

        list.add(s1);
        list.add(s2);


        List<Student> students  = dao.selectForeachTwo(list);

        students.forEach( stu-> System.out.println("stu=="+stu));
        //3.关闭SqlSession对象
        session.close();
    }
            

4.4 sql标签

sql标签标示 一段sql代码, 可以是表名,几个字段, where条件都可以, 可以在其他地方复用sql标签的内容。

使用方式:

1) 在mapper文件中定义 sql代码片段 <sql id="唯一字符串">  部分sql语句  </sql>
2)在其他的位置,使用include标签引用某个代码片段

例如:

<!--定义代码片段-->
<sql id="selectStudent">
    select * from student
</sql>

<sql id="studentFieldList">
    id,name,email
</sql>

<select id="selectIf" resultType="com.bjpowernode.domain.Student">

        <include refid="selectStudent" />

        where id=-1
        <if test="name !=null and name!=''">
           or  name = #{name}
        </if>

        <if test="age >0">
            or age &lt; #{age}
        </if>
    </select>

    <!--where-->
    <select id="selectWhere" resultType="com.bjpowernode.domain.Student">
        select <include refid="studentFieldList"/> from student
        <where>
            <if test="name !=null and name!=''">
                or  name = #{name}
            </if>

            <if test="age >0">
                or age &lt; #{age}
            </if>
        </where>

    </select>

第五章 MyBatis配置文件

mybatis配置文件两大类: 1 mybatis主配置文件; 2 mybatis的mapper文件

  1. mybatis主配置文件,提供mybatis全局设置的。包含的内容 日志, 数据源,mapper文件位置
  2. mapper文件: 写sql语句的。 一个表一个mapper文件

5.1 settings部分

settings是mybatis的全局设置,影响整个mybatis的运行。 这个设置一般使用默认值就可以了。

<settings>
  <setting name="cacheEnabled" value="true"/>
  <setting name="lazyLoadingEnabled" value="true"/>
  <setting name="multipleResultSetsEnabled" value="true"/>
  <setting name="useColumnLabel" value="true"/>
  <setting name="useGeneratedKeys" value="false"/>
  <setting name="autoMappingBehavior" value="PARTIAL"/>
  <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
  <setting name="defaultExecutorType" value="SIMPLE"/>
  <setting name="defaultStatementTimeout" value="25"/>
  <setting name="defaultFetchSize" value="100"/>
  <setting name="safeRowBoundsEnabled" value="false"/>
  <setting name="mapUnderscoreToCamelCase" value="false"/>
  <setting name="localCacheScope" value="SESSION"/>
  <setting name="jdbcTypeForNull" value="OTHER"/>
  <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>

5.2 typeAliase 别名

设置别名

	<typeAliases>
        <!--第一种语法格式
            type:java类型的全限定名称(自定义类型)
            alias:自定义别名

            优点: 别名可以自定义
            缺点: 每个类型必须单独定义
        -->
        <typeAlias type="com.bjpowernode.domain.Student" alias="stu" />
        <typeAlias type="com.bjpowernode.vo.QueryParam" alias="qp" />

        <!--第二种方式
            name:包名, mybatis会把这个包中所有类名作为别名(不用区分大小写)
            优点:使用方便,一次给多个类定义别名
            缺点: 别名不能自定义,必须是类名。
        -->
        <package name="com.bjpowernode.domain" />
        <package name="com.bjpowernode.vo" />

    </typeAliases>

5.3 配置环境

environments: 环境标签, 在他里面可以配置多个environment
       属性: default ,必须是某个environment的id属性值。 表示mybatis默认连接的数据库
environment: 表示一个数据库的连接信息。
       属性: id 自定义的环境的标识。 唯一值。
transactionManager:事务管理器
       属性:  type 表示事务管理器的类型。
       属性值:1)JDBC: 使用Connection对象, 由mybatis自己完成事务的处理。
             2) MANAGED: 管理,表示把事务的处理交给容器实现(由其他软件完成事务的提交,回滚)
dataSource: 数据源,创建的Connection对象,连接数据库。
       属性:  type 数据源的类型
       属性值:1) POOLED, mybatis会在内存中创建PooledDataSource类,管理多个Connection连接对象,使                           用的连接池
             2) UNPOOLED ,不使用连接池, mybatis创建一个UnPooledDataSource这个类, 每次执行sql                           语句先创建Connection对象,再执行sql语句,最后关闭Connection
             3) JNDI : java的命名和目录服务。

<environments default="online">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <!--配置数据源: 创建Connection对象。-->
            <dataSource type="POOLED">
                <!--driver:驱动的内容-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <!--连接数据库的url-->
                <property name="url"
                          value="jdbc:mysql://localhost:3306/springdb"/>
                <!--用户名-->
                <property name="username" value="root"/>
                <!--密码-->
                <property name="password" value="123"/>
            </dataSource>
        </environment>
        <!-- 项目上线后使用的数据库 -->
        <environment id="online">
            <transactionManager type="JDBC"/>
            <!--配置数据源: 创建Connection对象。-->
            <dataSource type="POOLED">
                <!--driver:驱动的内容-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <!--连接数据库的url-->
                <property name="url"
                          value="jdbc:mysql://localhost:3306/springdb"/>
                <!--用户名-->
                <property name="username" value="admin"/>
                <!--密码-->
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

5.4 使用数据库属性配置文件(掌握)

需要把数据库的配置信息放到一个单独文件中, 独立管理。 这个文件扩展名是 properties. 在这个文件中,使用自定义的key=value的格式表示数据

使用步骤:

1.在resources目录中,创建xxxx.properties

2.在文件中,使用 key=value的格式定义数据。

例如 jdbc.url=jdbc:mysq://localhost:3306/springdb

3.在mybatis主配置文件, 使用properties标签引用外部的属性配置文件

4.在使用值的位置, 使用${key}获取key对应的value(等号右侧的值)

例子:

jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springdb?useUnicode=true&amp;characterEncoding=utf-8
jdbc.username=root
jdbc.password=123

mybatis主配置文件

<!--使用外部属性配置文件
    resource:指定类路径下的某个属性配置文件
-->
<properties resource="jdbc.properties" />

<environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <!--配置数据源: 创建Connection对象。-->
            <dataSource type="POOLED">
                <!--driver:驱动的内容-->
                <property name="driver" value="${jdbc.driver}"/>
                <!--连接数据库的url-->
                <property name="url" value="${jdbc.url}"/>
                <!--用户名-->
                <property name="username" value="${jdbc.username}"/>
                <!--密码-->
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
         </environment>
</environments>

5.5 mapper 标签(*)

使用mapper指定其他mapper文件的位置,

mapper标签使用的格式有两个常用的方式:

<mappers>
    <!--第一种方式, resources="mapper文件的路径"
        优点:文件清晰。 加载的文件是明确的。
              文件的位置比较灵活。
        缺点:文件比较多, 代码量会比较大, 管理难度大
    -->
    <mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
    <mapper resource="com/bjpowernode/dao/OrderDao.xml"/>
    <!--
       第二种方式,使用<package>
       name:包名, mapper文件所在的包名。
       特点: 把这个包中的所有mapper文件,一次加载。

       使用要求:
        1. mapper文件和dao接口在同一目录
        2. mapper文件和dao接口名称完全一样。
    -->
    <package name="com.bjpowernode.dao" />
    <package name="com.bjpowernode.dao1" />
</mappers>

第六章 PageHelper

PageHelper做数据分页。 在你的select语句后面加入 分页的 sql 内容, 如果你使用的mysql数据库, 它就是在select * from student 后面加入 limit 语句。

使用步骤:

1.加入依赖pagehelper依赖

<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>

2.在mybatis主配置文件, 加入plugin声明

<environments> 之前加入
<plugins>
   <plugin interceptor ="com.github.pagehelper.PageInterceptor" />
</plugins>    

3.在select语句之前,调用PageHelper.startPage(页码, 每页大小)

对比:

没有使用PageHelper

select * from student order by id

使用PageHelper

SELECT count(0) FROM student

select * from student order by id LIMIT ?

Mybatis-plus是MyBatis增强工具包,用于简化CRUD操作。该工具包为MyBatis提供了一些高效,有用,即用的功能,使用它可以有效地节省您的开发时间。 Mybatis-plus特征: 与MyBatis完全兼容 启动时自动配置 开箱即用的用于操作数据库的界面 强大而灵活的条件包装器 生成主键的多种策略 Lambda样式的API 全能和高度可定制的代码生成器 自动分页操作 SQL注入防御 支持活动记录 支持可插拔的自定义界面 内置许多有用的扩展 Mybatis-plus功能: 1、单表CURD(简单 + 批量)操作,自动完成(支持 like 比较等查询)。 2、分页插件,Count查询自动或自定义SQL查询。 3、Spring根据不同环境加载不同配置支持(支持typeAliasesPackage通配符扫描)。 【自动生成Entity  Mapper  Service文件】 Mybatis-plus更新日志: v3.4.3 增加瀚高数据库支持 增加注解 Order By 支持默认排序 Wrapper exists notExists orderBy groupBy 支持参数绑定 Wrapper 支持 setParamAlias 其它优化 优化 KeyGenerator 支持多实现多数据源注入 增强 ServiceImpl 泛型推断,解决多继承与代理问题 新增 PageDto 用于微服务对象传输序列化 新增 Page 提供静态 of 构造方式 增加代理 MethodHandleProxies 对 lambda 调试支持 调整 ActiveRecord 日志对象初始化 调整 ActiveRecord 模式 Model 类开发 pkVal 方法外部可用 删除标记过时代码 优化枚举值获取方式 分页 count 安全处理 Sequence 方法支持重写支持 升级 Mybatis 3.5.7 修复自动配置 lazy-initialization 无属性提示 修复 mysql on duplicate key update 字段名判断为表名问题 修复 lambda 条件 npe 异常 重构 lambda 信息提取方法 获取 lambda 信息不在序列化 合并 gitee pulls/ 141 fixed github issues/3208 3016 fixed github issues/3482 数据权限处理器支持 union all 调整事务未启用打印提示信息 单元测试优化相关依赖升级
### 关于 MyBatis 学习教程与笔记 #### 创建数据库表结构 为了更好地理解如何使用 MyBatis 进行操作,先定义一个简单的 `blog` 表来存储博客的相关信息。此表包含了博客 ID、标题、作者名、创建时间和浏览次数等字段。 ```sql CREATE TABLE `blog`( `id` VARCHAR(50) NOT NULL COMMENT '博客 id', `title` VARCHAR(100) NOT NULL COMMENT '博客标题', `author` VARCHAR(30) NOT NULL COMMENT '博客作者', `create_time` DATETIME NOT NULL COMMENT '创建时间', `views` INT(30) NOT NULL COMMENT '浏览量' ) ENGINE=INNODB DEFAULT CHARSET=utf8; ``` 上述 SQL 语句用于创建名为 `blog` 的数据表[^2]。 #### 编写实体类 当构建应用程序时,通常会有一个对应的 Java 类代表每一张数据库表格。对于上面提到的 `blog` 表格而言,应该存在相应的 Blog 实体类: ```java public class Blog { private String id; private String title; private String author; private Date createTime; private Integer views; // Getters and Setters... } ``` 这里需要注意的是,在设计实体类的时候应当遵循一些最佳实践原则,比如尽量采用包装类型而非基本数据类型,并确保实体类中的属性名称以及其数据类型需同数据库表内的列保持一致[^3]。 #### 定义 Mapper 接口 接着就是定义映射器接口(Mapper Interface)。这些接口用来描述对特定对象的操作行为而无需关心具体的实现细节。下面是一个非常基础的例子——查询所有用户的列表: ```java import java.util.List; public interface UserMapper { /** * 查询所有的用户. * * @return 用户集合 */ List<User> findAll(); } ``` 这段代码展示了怎样去声明一个可以返回多个用户记录的方法。 #### 配置 XML 文件 最后一步是在 resources 资源目录下建立 XML 映射文件 usermapper.xml 来指定具体执行哪些 SQL 命令。这使得开发者能够轻松地管理复杂的 CRUD 操作而不必硬编码到程序逻辑里边。 ```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="com.example.mapper.UserMapper"> <!-- Select all users --> <select id="findAll" resultType="com.example.model.User"> SELECT * FROM users </select> </mapper> ``` 以上内容概括了有关 MyBatis 使用的基础知识点,包括但不限于环境设置、SQL 动态处理机制等方面的信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值