动力节点—2020最新MyBatis教程笔记


本文为动力节点2020MyBatis笔记整理,视频地址为https://www.bilibili.com/video/BV185411s7Ry?from=search&seid=5830402177484068371。
王鹤老师的笔记可自行去动力节点官网下载。

1 介绍

Java WEB 通常分为三层,即表示层,业务逻辑层,数据访问层。

三层的职责

  1. 界面层(表示层,视图层):主要功能是接受用户的数据,显示请求的处理结果。使用 web 页面和用户交互,手机 app 也就是表示层的,用户在 app 中操作,业务逻辑在服务器端处理。

  2. 业务逻辑层:接收表示传递过来的数据,检查数据,计算业务逻辑,调用数据访问层获取数据。

  3. 数据访问层:与数据库打交道。主要实现对数据的增、删、改、查。将存储在数据库中的数据提交给业务层,同时将业务层处理的数据保存到数据库

具体过程为:用户---> 界面层(Spring MVC)--->业务逻辑层(Spring)--->数据访问层(MyBatis)--->DB 数据库。

MyBatis 框架:

MyBatis 是一个优秀的基于 java 的持久层框架,内部封装了 jdbc,开发者只需要关注 sql 语句本身,而不需要处理加载驱动、创建连接、创建 statement、关闭连接,资源等繁杂的过程。

MyBatis 通过 xml 或注解两种方式将要执行的各种 sql 语句配置起来,并通过 java 对象和 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。

2 快速入门

对于MyBatis项目来说,除了maven本身的pom.xml以外,还有主配置文件mybatis-config.xml,通常放在Resource目录下;以及各个Dao接口对应的在同级目录下且同名的xml映射文件。在主配置文件中,可以设置数据源,事务,别名,日志,分页以及映射器位置,在Dao对应的映射文件中,通常是写相应的SQL语句来实现Dao的各种功能。

2.1 操作步骤(P9)

2.1.1 首先创建maven

(1)创建maven:New Project/Module->选择Maven,打钩Create from archetype,选择 :maven-archetype-quickstart,next->输入Name/Location,点开Artifact Coordinates,输入相应Id。

(2)等待加载完成后,在src/main上右击,产生resources目录,resources下面的资源在编译后在target/classes下面。

2.1.2 接着会做一些配置

(1)在pom.xml中,修改properties中的1.7为1.8,删除maven原有的build,加入maven的依赖,包括mybatis和mysql驱动,以及一个扫描src/main/java目录下的各种资源放入编译后的target下的classes

<dependencies>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.1</version>
  </dependency>
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.9</version>
  </dependency>
</dependencies>


<build>
  <resources>
    <resource>
      <directory>src/main/java</directory><!--所在的目录-->
      <includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
        <include>**/*.properties</include>
        <include>**/*.xml</include>
      </includes>
      <filtering>false</filtering>
    </resource>
  </resources>
  <plugins>
    <plugin>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.1</version>
      <configuration>
        <source>1.8</source>
        <target>1.8</target>
      </configuration>
    </plugin>
  </plugins>
</build>

(2)创建Dao接口以及涉及到的Bean对象

(3)创建mapper文件,也叫sql映射文件,是一个xml:写sql语句的,和接口中方法对应的sql语句。

<?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">
    <!--
       select:表示查询操作。
       id: 你要执行的sql语法的唯一标识, mybatis会使用这个id的值来找到要执行的sql语句
           可以自定义,但是要求你使用接口中的方法名称。

       resultType:表示结果类型的, 是sql语句执行后得到ResultSet,遍历这个ResultSet得到java对象的类型。
          值写的类型的全限定名称
    -->

    <select id="selectStudents" resultType="com.bjpowernode.domain.Student">
        select id,name,email,age from student order by id
    </select>


    <!--插入操作-->
    <insert id="insertStudent">
        insert into student values(#{id},#{name},#{email},#{age})
    </insert>
</mapper>
<!--
  sql映射文件(sql mapper): 写sql语句的, mybatis会执行这些sql
  1.指定约束文件
     <!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

    mybatis-3-mapper.dtd是约束文件的名称, 扩展名是dtd的。
  2.约束文件作用:  限制,检查在当前文件中出现的标签,属性必须符合mybatis的要求。

  3.mapper 是当前文件的根标签,必须的。
    namespace:叫做命名空间,唯一值的, 可以是自定义的字符串。
               要求你使用dao接口的全限定名称。

  4.在当前文件中,可以使用特定的标签,表示数据库的特定操作。
   <select>:表示执行查询,select语句
   <update>:表示更新数据库的操作, 就是在<update>标签中 写的是update sql语句
   <insert>:表示插入, 放的是insert语句
   <delete>:表示删除, 执行的delete语句
-->

(4)创建mybatis的一个主配置文件,也是xml,放在resources下,1)连接数据库;2)指定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>

    <!--settings:控制mybatis全局行为-->
    <settings>
        <!--设置mybatis输出日志-->
        <setting name="logImpl" value="STDOUT_LOGGING" />
    </settings>

    <!--环境配置: 数据库的连接信息
        default:必须和某个environment的id值一样。
        告诉mybatis使用哪个数据库的连接信息。也就是访问哪个数据库
    -->
    <environments default="mydev">
        <!-- environment : 一个数据库信息的配置, 环境
             id:一个唯一值,自定义,表示环境的名称。
        -->
        <environment id="mydev">
            <!--
               transactionManager :mybatis的事务类型
                   type: JDBC(表示使用jdbc中的Connection对象的commit,rollback做事务处理)
            -->
            <transactionManager type="JDBC"/>
            <!--
               dataSource:表示数据源,连接数据库的
                  type:表示数据源的类型, POOLED表示使用连接池
            -->
            <dataSource type="POOLED">
                <!--
                   driver, user, username, password 是固定的,不能自定义。
                -->
                <!--数据库的驱动类名-->
                <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="root"/>
            </dataSource>
        </environment>
    </environments>

    <!-- sql mapper(sql映射文件)的位置-->
    <mappers>
        <!--一个mapper标签指定一个文件的位置。
           从类路径开始的路径信息。  target/clasess(类路径)
        -->
        <mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
        <!--<mapper resource="com/bjpowernode/dao/SchoolDao.xml" />-->
    </mappers>
</configuration>
<!--
   mybatis的主配置文件: 主要定义了数据库的配置信息, sql映射文件的位置

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

    mybatis-3-config.dtd:约束文件的名称

  2. configuration 根标签。
-->

(5)使用mybatis的对象SqlSession,通过他的方法执行sql语句。

@Test
public void testSelect() throws Exception{
    //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()
    List<Student> studentList = session.selectList("com.bjpowernode.dao.StudentDao.selectStudents");
    //6.循环输出查询结果
    studentList.forEach( student -> System.out.println(student));
    //7.关闭 SqlSession,释放资源
    session.close();
}

2.2 在编译的target目录下面缺少xml的解决方式(P11)

事先做的配置

1.resource文件夹,前面需要有相应的标识,没有的话,右键-Mark Directory as

2.在pom.xml文件中的<build><resources>...</resources></build>放置resource,用于扫描并将src/main/java的相应资源导入。(见操作步骤)

解决方式

1.右边的maven,先clean,然后compile

2.上面的Build-ReBuild Project

3.上边的File-Invalidate Caches/Restart,再点一次。

4.将sql映射文件和主配置文件直接拷贝到target目录下面。

2.3 日志的输出

在mybatis.xml的<configuration>后面添加

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

2.4 注意事项

mybatis默认非自动提交事务,查询不需要提交,而insert/update/delete,需要提交,sqlSession.commit();

2.5对各个对象的分析

Resource类

Resources 类,顾名思义就是资源,用于读取资源文件。其有很多方法通过加载并解析资源文件,返回不同类型的 IO 流对象。

SqlSessionFactoryBuilder类

SqlSessionFactory 的 创 建 , 需 要 使 用 SqlSessionFactoryBuilder 对 象 的 build() 方 法 。 由于SqlSessionFactoryBuilder 对象在创建完工厂对象后,就完成了其历史使命,即可被销毁。所以,一般会将该 SqlSessionFactoryBuilder 对象创建为一个方法内的局部对象,方法结束,对象销毁。

SqlSessionFactory接口

SqlSessionFactory 接口对象是一个重量级对象(系统开销大的对象),是线程安全的,所以一个应用只需要一个该对象即可。创建 SqlSession 需要使用 SqlSessionFactory 接口的的 openSession()方法。

➢ openSession(true):创建一个有自动提交功能的 SqlSession

➢ openSession(false):创建一个非自动提交功能的 SqlSession,需手动提交

➢ openSession():同 openSession(false)

SqlSession接口

SqlSession 接口对象用于执行持久化操作。一个 SqlSession 对应着一次数据库会话,一次会话以SqlSession 对象的创建开始,以 SqlSession 对象的关闭结束。

SqlSession 接口对象是线程不安全的,所以每次数据库会话结束前,需要马上调用其 close()方法,将其关闭。再次需要会话,再次创建。 SqlSession 在方法内部创建,使用完毕后关闭。

2.6 工具类

通过该工具类的静态方法可以方便获取SqlSession。

public class MyBatisUtils {

    private  static  SqlSessionFactory factory = null;
    static {
        String config="mybatis.xml"; // 需要和你的项目中的文件名一样
        try {
            InputStream in = Resources.getResourceAsStream(config);
            //创建SqlSessionFactory对象,使用SqlSessionFactoryBuild
            factory = new SqlSessionFactoryBuilder().build(in);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //获取SqlSession的方法
    public static SqlSession getSqlSession() {
        SqlSession sqlSession  = null;
        if( factory != null){
            sqlSession = factory.openSession();// 非自动提交事务
        }
        return sqlSession;
    }
}

3 MyBatis DAO代理

3.1两种sql的执行方式

第一类是前面的方法,SqlSession直接执行selectList/update/delete/insert之类操作;

第二类是先通过SqlSession的getMapper()获取接口Dao的实现类,然后调用接口的方法。原理是动态代理。

以select为例解释,第一种是通过SqlSession直接执行selectList来获取数据,第二种是SqlSession首先获取一个StudentDao的一个实现类,该实现类可以直接调用selectStudents获取数据。

SqlSession session = MyBatisUtil.getSqlSession();
List<Student> studentList = session.selectList("com.bjpowernode.dao.StudentDao.selectStudents");
 
StudentDao studentDao = MyBatisUtil.getSqlSession().getMapper(StudentDao.class);
List<Student> studentList = studentDao.selectStudents();

3.2 参数的理解

3.2.1 parameterType

parameterType表示传入的参数类型,可以省略。

3.2.2 传入的参数在SQL语句中的使用

(1)如果传入的是一个简单类型(java 基本类型和 String),在SQL中,可以用#{任意字符}

<select id="selectById" resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student where id=#{studentId}
</select>
#{studentId} , studentId 是自定义的变量名称,和方法参数名无关。

(2)传入多个参数,使用@Param

接口方法:
List<Student> selectMultiParam(@Param("personName") String name,@Param("personAge") int age);

mapper 文件:
<select id="selectMultiParam" resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student where name=#{personName} or age 
=#{personAge}</select>

(3)传入一个对象,#{ property,javaType=java 中数据类型名,jdbcType=数据类型名称 },简写为 #{ property }

创建保存参数值的对象 QueryParam
package com.bjpowernode.vo;
public class QueryParam {
 private String queryName;
 private int queryAge;
 //set ,get 方法}
 
接口方法:
List<Student> selectMultiObject(QueryParam queryParam);

mapper 文件:
<select id="selectMultiObject" resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student where name=#{queryName} or age 
=#{queryAge}
</select>

(4)多个参数还可以按位置或者使用map

3.2.3 #和$的区别

  1. #使用 ?在sql语句中做占位的, 使用PreparedStatement执行sql,效率高
  2. #能够避免sql注入,更安全。
  3. $不使用占位符,是字符串连接方式,使用Statement对象执行sql,效率低
  4. $有sql注入的风险,缺乏安全性。
  5. $:可以替换表名或者列名

3.2.4 resultType和resultMap

两者选一,resultMap主要用于表的列和对象属性不匹配。

<resultMap id="student2Map" type="com.bjpowernode.domain.Student2">
    <!-- 主键字段使用 id -->
    <id column="id" property="id2" />
    <!--非主键字段使用 result-->
    <result column="name" property="name2"/>
    <result column="email" property="email2" />
    <result column="age" property="age2" />
</resultMap>

<select id="selectStudents2" resultMap="student2Map">
    select id,name,email,age from student order by id
</select>

3.2.5 模糊like

例 1: java 代码中提供要查询的 “%力%”

接口方法:
List<Student> selectLikeFirst(String name);
mapper 文件:
<select id="selectLikeFirst" resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student
 where name like #{studentName}
</select>
测试方法:
@Test
public void testSelectLikeOne(){
 String name="%力%";
 List<Student> stuList = studentDao.selectLikeFirst(name);
 stuList.forEach( stu -> System.out.println(stu));
}

例 2:mapper 文件中使用 like name "%" #{xxx} "%"

接口方法:
List<Student> selectLikeSecond(String name);
mapper 文件:
<select id="selectLikeSecond" resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student
 where name like "%" #{studentName} "%"
</select>
测试方法:
@Test
public void testSelectLikeSecond(){
 String name="力";
 List<Student> stuList = studentDao.selectLikeSecond(name);
 stuList.forEach( stu -> System.out.println(stu));
}

4 动态SQL

对于 sql 中的"<",一定要换成"&lt;"。

动态 SQL 相当于会变化的 SQL,主要包括<if>,<where>,<foreach>和代码片段。

if 可以在满足条件时执行相应功能,where主要用于包装if,去掉多余的and/or,foreach是对于一个可以遍历的集合进行输出,代码片段表示代码的重用功能。

示例:

4.1 if 和 where

<select id="selectStudentWhere" resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student
 <where>
 <if test="name != null and name !='' ">
 and name = #{name}
 </if>
 <if test="age > 0 ">
 and age &gt; #{age}
 </if>
 </where>
</select>

4.2 foreach

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


<!--示例-->
<select id="selectStudentForList" 
resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student
 <if test="list !=null and list.size > 0 ">
 where id in
 <foreach collection="list" open="(" close=")" 
item="stuid" separator=",">
 #{stuid}
 </foreach>
 </if>
</select>

4.3 代码片段,重用

<sql/>标签用于定义 SQL 片断,以便其它 SQL 标签复用。而其它标签使用该 SQL 片断,需要使用<include/>子标签。

<sql id="studentSql">
 select id,name,email,age from student
</sql> <select id="selectStudentSqlFragment" 
resultType="com.bjpowernode.domain.Student">
 <!-- 引用 sql 片段 -->
 <include refid="studentSql"/>
 <if test="list !=null and list.size > 0 ">
 where id in
 <foreach collection="list" open="(" close=")" 
item="stuobject" separator=",">
 #{stuobject.id}
 </foreach>
 </if>
</select>

5 配置文件

5.1 主配置文件

之前项目中使用的 mybatis.xml 是主配置文件。

主配置文件特点:

1.xml 文件,需要在头部使用约束文件

<?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">

2.根元素,<configuration>

3.主要包含内容:

​ 定义别名

​ 数据源

​ mapper 文件

5.2 dataSource

在主配置文件中配置,包括下面三种

  • UNPOOLED 不使用连接池的数据源,MyBatis 会创建 UnpooledDataSource 实例

  • POOLED 使用连接池的数据源,MyBatis 会创建 PooledDataSource 实例

  • JNDI 使用 JNDI 实现的数据源,MyBatis 会从 JNDI 服务上查找 DataSource 实例

<dataSource type="POOLED">
 <!--连接数据库的四个要素-->
 <property name="driver" value="com.mysql.jdbc.Driver"/>
 <property name="url" 
value="jdbc:mysql://localhost:3306/ssm?charset=utf-8"/>
 <property name="username" value="root"/>
 <property name="password" value="123456"/>
</dataSource>

5.3 事务

使用位置,<transactionManager type="JDBC"/>

  • JDBC,使用 JDBC 的事务管理机制。默认不自动提交,需要手动提交。

  • MANAGED,由容器来管理事务的整个生命周期(如 Spring 容器)。

5.4 使用数据库属性配置文件

将写在dataSource中数据库四个要素抽取到一个文件中,主文件中换成${文件名.具体name}。

<dataSource type="POOLED">
 <!--使用 properties 文件: 语法 ${key}-->
 <property name="driver" value="${jdbc.driver}"/>
 <property name="url" value="${jdbc.url}"/>
 <property name="username" value="${jdbc.username}"/>
 <property name="password" value="${jdbc.password}"/>
</dataSource>

5.5 mapper(映射器)

1.<mapper resource=" " />

使用相对于类路径的资源,从 classpath 路径查找文件,

例如:<mapper resource="com/bjpowernode/dao/StudentDao.xml" />

​2. <package name=""/>

指定包下的所有 Dao 接口

如:<package name="com.bjpowernode.dao"/>

注意:此种方法要求 Dao 接口名称和 mapper 映射文件名称相同,且在同一个目录中。

6 分页

使用插件 PageHelper,对应配置如下:

  • 在pom.xml中
<dependency>
  <groupId>com.github.pagehelper</groupId>
  <artifactId>pagehelper</artifactId>
  <version>5.1.10</version>
</dependency>
  • 在mybatis主配置文件中,<environments>之前加入
<plugins>
 <plugin interceptor="com.github.pagehelper.PageInterceptor" />
</plugins>

用法

@Test
public void testSelect() throws IOException {
//获取第 1 页,3 条内容
 PageHelper.startPage(1,3);
 List<Student> studentList = studentDao.selectStudents();
 studentList.forEach( stu -> System.out.println(stu));
}
posted @ 2021-08-15 20:57  Java与大数据进阶  阅读(381)  评论(0编辑  收藏  举报