Hello-MyBatis


title: Hello-MyBatis
tag: JAVA


1.框架入门 2.What is MyBatis 3.Hello MyBatis 4.Dao 5.动态SQL 6.mybatis配置文件 7.PageHelper插件

1.框架入门

1. 三层架构:

  • 界面层:和用户打交道的,接收用户的请求参数,显示处理结果(jsp、html、servlet)
  • 业务逻辑层:接收界面层传递的数据,计算逻辑,调用数据库,获取数据
  • 数据访问层:访问数据库,对数据进行增删改查

2. 三层架构在项目中对应的包

  • 界面层:controller包(servlet)
  • 业务逻辑基层:service包(XxxService类)
  • 数据访问层:dao包(XxxDao类)

3. 三层中类之间的交互关系

  • 界面层–>业务逻辑层–>数据访问层–>数据库

4. 三层架构对应的开发框架

  • 界面层:servlet—SpringMVC框架
  • 业务逻辑层:service类—spring框架
  • 数据访问层:dao类—Mybatis框架

5. 框架是什么

框架是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法,另一种说法;框架是可被应用开发者定制的应用骨架、模板。简单的说,框架其实是半成品软件,就是一组组件,供你使用完成你自己的系统。框架是安全的,可复用的,不断升级的软件

2.What is MyBatis

1. MyBatis是什么

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。
MyBatis提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)

  • SQL Mapper:SQL映射,将数据库中的一行数据映射为一个Java对象
  • Data Access Objects:数据访问对象,它是对于数据库操作的一种设计方式,把Dao设计为一个通用接口,提供对数据库进行增、删、改、查的一系列操作数据库的抽象方法。

2. MyBatis提供了哪些功能

  1. 提供了创建Connection、Statement、ResultSet的功能,不用开发人员创建这些对象了
  2. 提供了执行SQL语句的功能,不用程序员去执行了
  3. 提供了循环SQL语句的功能,把SQL的执行结果转换为java对象,List集合
  4. 提供了关闭资源的功能,程序员不用关闭Connection、Statement、ResultSet了

开发人员要做的就是:提供SQL语句,把精力放在写好SQL语句上即可!

3.Hello MyBatis!

  1. 新建student表
  2. 加入maven的mybatis依赖和mysql驱动
  3. 创建实体类 Student- 用来保存表中的一行数据
  4. 创建持久层的dao接口 定义操作数据库的方法
  5. 创建mybatis配置文件,叫做sql映射文件,用来写sql语句的。一般一个表一个sql映射文件
  • 写在Dao接口所在的目录中
  • 文件名称与接口名保持一致
  1. 创建mybatis的主配置文件,主配置文件提供了数据库的连接信息和sq1映射文件的位置信息
  2. 创建使用mybatis的类,通过mybatis访问数据库

1. 新建student表

2. 加入maven的mybatis依赖和mysql驱动

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

    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.25</version>
    </dependency>

3. 创建实体类 Student

package xyz.guawaz.domain;

//类名推荐和表名一致,方便记忆
public class Student {
    private Integer id;
    private String name;
    private String email;
    private Integer age;

	...
}

4. 创建持久层的dao接口 定义操作数据库的方法

public interface StudentDao {
    //查询Student表的所有数据
    public List<Student> selectStudents();
}

5. 创建mybatis配置文件 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="xyz.guawaz.dao.StudentDao">

    <!--
    select:表示查询操作
    id:要执行的查询操作的唯一标识,mybatis会使用这个id来找到要执行的查询操作
        要求使用dao接口中的方法名

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

    -->
    <select id="selectStudents" resultType="xyz.guawaz.domain.Student">
        select id,name,email,age from student order by id
    </select>
</mapper>
<!--sq1映射文件:写sq1语句的 ,mybatis会 执行这些sql
1.指定约束文件:
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
2.约束文件的作用:限制、检查在当前文件中出现的标签和格式
3.<mapper:当前文件的根标签,必须的
 namespace:命名空间,唯一,要求使用dao接口的全限定名称

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

6. 创建mybatis的主配置文件

<?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"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/guawaz.xyz"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="xyz/guawaz/dao/StudentDao.xml"/>
    </mappers>
</configuration>

<!--mybatis的主配置文件,定义了数据库的配置信息和sql映射文件的位置-->

7. 通过mybatis访问数据库

package xyz.guawaz;

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 xyz.guawaz.domain.Student;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLOutput;
import java.util.List;

public class MyApp {
    public static void main(String[] args) throws IOException {
        //1.定义mybatis主配置文件的名称
        String config = "mybatis.xml";
        //2.读取这个config表示的文件
        InputStream in = Resources.getResourceAsStream(config);
        //3.创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //4.创建SqlSessionFactory对象
        SqlSessionFactory factory = builder.build(in);
        //5.【重要】获取SqlSession对象,从SqlSessionFactory中获取SqlSession
        SqlSession sqlSession = factory.openSession();
        //6.【重要】指定要执行的sql语句的标识。sql映射文件中的namespace + "." + 标签的id值
        String sqlId = "xyz.guawaz.dao.StudentDao" + "." + "selectStudents";
        //7.执行sql语句,通过sqlId找到语句
        List<Student> studentList = sqlSession.selectList(sqlId);
        //8.输出结果
        studentList.forEach(stu -> System.out.println(stu));
        //9.关闭sqlSession对象
        sqlSession.close();
    }
}

8. 执行结果

image-20210723011238277

前面我们利用MyBatis实现了对数据库的访问,接下来对这个过程进行优化,更优雅方便地进行数据库访问

4.DAO

1. MyBatis主要类和接口的介绍

image-20210724102322779

  • Resources:负责读取主配置文件
  • SqlSessionFactoryBuilder:负责创建SqlSessionFactory对象
  • SqlSessionFactory接口:默认实现类是DefaultSqlSessionFactory。它是一个重量级对象,程序创建一个对象耗时较长,使用资源较多,整个项目中只需创建一个,它的功能是负责创建SqlSession对象。使用openSession()方法来获取SqlSession对象
  • openSession()方法:无参数默认获取非自动提交事务的SqlSession对象。带参数的 openSession(true)获取自动提交事务的SqlSession,openSession(false)获取非自动提交事务的SqlSession
  • SqlSession接口:默认实现类是DefaultSqlSession。定义了操作数据库的方法,例如:selectOne(),selectList(),insert(),update(),commit(),roolback()…SqlSession对象不是线程安全的,需要在方法内部使用。在执行sql语句之前使用openSession()获取SqlSession在执行完sql语句后,需要执行SqlSession.close()关闭它,以保证线程安全。

2. 编写MyBatisUtils

package xyz.guawaz.utils;

import com.sun.tools.javac.util.JCDiagnostic;
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 {
    private static SqlSessionFactory factory = null;

    static {
        String config = "mybatis.xml";
        InputStream in = null;
        try {
            in = Resources.getResourceAsStream(config);
        } catch (IOException e) {
            e.printStackTrace();
        }

        factory = new SqlSessionFactoryBuilder().build(in);
    }

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

3. 创建Dao实现类

package xyz.guawaz.dao.impl;

import org.apache.ibatis.session.SqlSession;
import xyz.guawaz.dao.StudentDao;
import xyz.guawaz.domain.Student;
import xyz.guawaz.utils.MyBatisUtils;

import java.util.List;

public class StudentDaoImpl implements StudentDao {

    @Override
    public List<Student> selectStudents() {
        //使用工具类获取SqlSession对象
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        //使用SqlSession执行sql语句
        List<Student> students = sqlSession.selectList("xyz.guawaz.dao.StudentDao.selectStudents");
        //输出结果
        students.forEach( stu -> System.out.println(stu));
        //关闭SqlSession	
        sqlSession.close();
        return students;
    }

    @Override
    public int insertStudent(Student student) {
        //使用工具类获取SqlSession对象
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        //使用SqlSession执行sql语句
        int num = sqlSession.insert("xyz.guawaz.dao.StudentDao.insertStudent",student);
        //提交事务
        sqlSession.commit();
        //关闭SqlSession
        sqlSession.close();
        return num;
    }
}

这样再操作数据库就可以用Dao实现类对象操作了:

package xyz.guawaz;

import org.junit.Test;
import xyz.guawaz.dao.impl.StudentDaoImpl;
import xyz.guawaz.domain.Student;

import java.util.List;

public class MyTest {
    @Test
    public void test1(){
        StudentDaoImpl studentDao = new StudentDaoImpl();
        List<Student> students = studentDao.selectStudents();
    }

    @Test
    public void test2(){
        StudentDaoImpl studentDao = new StudentDaoImpl();
        Student student = new Student();
        student.setId(1008);
        student.setName("赵云");
        student.setEmail("zhaoyun@qq.com");
        student.setAge(25);
        int num = studentDao.insertStudent(student);
    }
}

4. 使用MyBatis的动态代理,自动创建Dao实现类

public class MyTest {
    @Test
    public void test(){
        /*使用mybatis的动态代理机制,使用SqlSession.getMapper(dao接口)
        * 获取dao接口对应的实现类对象
        * */
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);

        List<Student> students = dao.selectStudents();
        students.forEach(student -> System.out.println(student));

        sqlSession.close();

    }
}

5. 传参

传参指的是从Java代码中把实际的值传入mapper文件中

package xyz.guawaz.dao;

import org.apache.ibatis.annotations.Param;
import xyz.guawaz.domain.Student;

import java.util.List;

public interface StudentDao {
    /*
    * 一个简单类型的参数:
    *       简单类型:mybatis把java基本数据类型和String都叫简单数据类型
    *
    *       在mapper文件获取简单类型的一个参数的值,使用#{任意字符}
    *
    *多个参数;
    *         1.使用@Param命名参数:在形参定义的前面加上@Param("自定义参数名称")
    *           在mapper文件使用#{自定义参数名称}获取多个参数的值
    *         2.使用对象作为接口中方法的参数
    *           在mapper文件使用#{对象的属性名}获取多个参数的值
    *
    *
    * 在mapper文件使用#{}获取参数的值,#也可以换位$
    * #和$的区别:
    *
    * #:使用PreparedStatement执行sql,效率高
    * $:使用Statement执行sql,效率低,有sql注入问题
    *   在确定数据安全时可以使用$,$可以进行sql拼接,一般用来替换表名、列名等
    *
    * */
    //一个简单类型的参数
   Student selectStudentById(Integer id);
    //多个参数;
    // @Param参数命名
    List<Student> selectStudentsByMultiParam(@Param("myname") String name,@Param("myage") Integer age);
    //对象方式
    List<Student> selectStudentsByObject(Student student);
    // # $
    List<Student> selectStudentsInOrder(@Param("colName") String colName);
}

<?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="xyz.guawaz.dao.StudentDao">

    <!--一个简单类型的参数-->
    <select id="selectStudentById" resultType="xyz.guawaz.domain.Student">
        select * from student where id=#{sudentId}
    </select>
    <!--多个参数 @Param参数命名-->
    <select id="selectStudentsByMultiParam" resultType="xyz.guawaz.domain.Student">
        select id,name,email,age from student where name=#{myname} or age=#{myage}
    </select>
    <!--多个参数 对象方式-->
    <select id="selectStudentsByObject" resultType="xyz.guawaz.domain.Student">
        select id,name,email,age from student where name=#{name} or age=#{age}
    </select>
    <!--$-->
    <select id="selectStudentsInOrder" resultType="xyz.guawaz.domain.Student">
        select * from student order  by ${colName}
    </select>
</mapper>

6. 返回类型

<?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="xyz.guawaz.dao.StudentDao">
   <!--
   resultType:

       返回简单类型:
       resultType 与dao接口中对应方法的返回值是一致的,可以是int,当查询语句是select count(*)时

       返回对象:
       resultType 可以是任何一个类,只要查询的值和这个类的属性对应起来就行

       返回Map:
       resultType="java.lang.HashMap"
       1)列名是Map的key,列值是Map的value
       2)只能最多返回一行记录 多于一行会报错

   resultMap:
       解决列名和属性名不一致问题
       另一种解决列名和属性名不一致问题的方式:sql语句中为列取别名
   -->
    <!--返回简单类型-->
    <select id="countStudent" resultType="int">
        select count(*) from student
    </select>

    <!--返回对象-->
    <select id="selectViewStudent" resultType="xyz.guawaz.vo.ViewStudent">
        select id,name from student where name=#{name} or age=#{age}
    </select>

    <!--返回Map-->
    <select id="selectMapById" resultType="java.util.HashMap">
        select id,name from student where id=#{id}
    </select>

    <!--resultMap-->
    <resultMap id="myResultMap" type="xyz.guawaz.domain.MyStudent">
        <!--主键列-->
        <id column="id" property="myId"/>
        <!--非主键列-->
        <result column="name" property="myName"/>
        <result column="email" property="myEmail"/>
        <result column="age" property="myAge"/>
    </resultMap>
    <!--使用resultMap自定义列名和属性的对应关系-->
    <select id="selectMyStudent" resultMap="myResultMap">
        select * from student
    </select>
    <!--在sql语句中为列取别名-->
    <select id="selectMyStudent2" resultType="xyz.guawaz.domain.MyStudent">
        select id as myId,name as myName,email as myEmail,age as myAge from student
    </select>

    <!--第一种模糊查询 在java代码中指定Like的内容-->
    <select id="selectLikeOne" resultType="xyz.guawaz.domain.Student">
        select id ,name ,email ,age  from student where name like #{name}
    </select>
    <!--第二种模糊查询 在mapper文件中拼接Like内容-->
    <select id="selectLikeTwo" resultType="xyz.guawaz.domain.Student">
        select id ,name ,email ,age  from student where name like #{name} "%"
    </select>
</mapper>

5.动态SQL

动态SQL是指,SQL语句的内容是变化的,可以根据条件获取到不同的SQL语句,主要是where部分发生变化。动态sql的实现,使用的是mybatis提供的标签if/where/foreach

<?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="xyz.guawaz.dao.StudentDao">


    <!--
    <if>用来判断条件,当条件为真,会把if标签之间的sql加入到主sql之后

    -->
    <select id="selectStudentIf" resultType="xyz.guawaz.domain.Student">
        select id,name,email,age from student
        where
        <if test="name!=null and name !=''">
            name = #{name}
        </if>
        <if test="age > 0">
            or age > #{age}
        </if>
    </select>
    <!--
    <where>用来包含多个<if>,当多个if有一个成立的,<where>会自动增加一个where关键字,并去掉if中多余的and or等
    -->
    <select id="selectStudentWhere" resultType="xyz.guawaz.domain.Student">
        select id,name,email,age from student
        <where>
        <if test="name!=null and name !=''">
            name = #{name}
        </if>
        <if test="age > 0">
            or age > #{age}
        </if>
        </where>
    </select>
    <!--
    <foreach>是用来循环遍历java中的数组、list集合的主要用在sql的in语句中
    -->
    <!--foreach用法一-->
    <select id="selectStudentForOne" resultType="xyz.guawaz.domain.Student">
        select * from student where id in
        <foreach collection="list" item="myid" open="(" close=")"  separator=",">
            #{myid}
        </foreach>
    </select>

    <!--foreach用法二-->
    <select id="selectStudentForTwo" resultType="xyz.guawaz.domain.Student">
        select * from student where id in
        <foreach collection="list" item="mystu" open="(" close=")"  separator=",">
            #{mystu.id}
        </foreach>
    </select>

    <!--sql代码片段,就是复用一些语句
    1.先使用sql标签定义代码片段
     <sql id=" "> sql语句</sql>
    2.再使用<include refid="id的值">引用sql代码片段
    -->
    <sql id="studentSql">
        select id,name,email,age from student
    </sql>

</mapper>

6.MyBatis配置文件

<?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>
	<!--文件开始位置指定使用数据库属性配置文件jdbc.properties
		在 classpath 路径下,创建 properties 文件
		使用 key 指定值,语法:${key}
	-->
    <properties resource="jdbc.properties" />
	 <!--设置打印日志-->
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <!--配置分页插件-->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>

    <environments default="development">
        <environment id="development">
        	<!--事务管理器,支持两种:JDBC和MANAGED,
        	JDBC:使用JDBC的事务管理机制。即,通过Connection的commit()方法提交,通过rollback()方法 回滚。
      		但默认情况下,MyBatis 将自动提交功能关闭了,改为了手动提交。即程序中需要显式的对 事务进行提交或回滚。
        	MANAGED:由容器来管理事务的整个生命周期(如 Spring 容器)。
        	-->
            <transactionManager type="JDBC"/>
            <!--Mybatis 中访问数据库,可以连接池技术,但它采用的是自己的连接池技术。在 Mybatis 的
      		 mybatis.xml配置文件中,通过<dataSource type=”pooled”>来实现 Mybatis 中连接池的配置。
			-->
            <dataSource type="POOLED">
                <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>
        </environment>
    </environments>
    <mappers>
   		<!-- <mapper resource=" " />: 使用相对于类路径的资源,从 classpath 路径查找文件
		-->
   		<!-- <package name=""/>: 指定包下的所有 Dao 接口,注意:此种方法要求 Dao 接口名称和 mapper 映射文件
   								名称相同,且在同一个目录中。
		-->
        <mapper resource="xyz/guawaz/dao/StudentDao.xml"/>
    </mappers>
</configuration>

        <!--mybatis的主配置文件,定义了数据库的配置信息和sql映射文件的位置-->

7.PageHelper插件

1. 加入maven依赖

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

2. 在mybatis.xml中加入插件

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

3. 使用PageHelper

查询语句之前调用PageHelper.startPage 静态方法,紧跟在这个 方法后的第一个 MyBatis 查询方法会被进行分页。

public void testSelectAll() {

    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);

    PageHelper.startPage(1,3);//获取第 1 页,3 条内容
    List<Student> students = dao.selectAll();
    students.forEach(stu -> System.out.println(stu));

    sqlSession.close();
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值