(1)MyBatis简介及其简单使用

MyBatis简介

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
MyBatis 的主要作用就是在java中操作数据库,其实就是在jdbc的基础上进行了封装,使用mybatis之后,开发者不用再像使用jdbc那样去处理诸如注册驱动、创建Connection、配置Statement、执行sql语句、获取结果集等繁琐过程。早期叫做iBatis,后来改名为myBatis,在官网上有中文版的介绍和文档,mybatis同时支持xml和注解。

使用mybatis操作数据库

1.创建一个maven项目,pom.xml文件如下。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.h3c</groupId>
    <artifactId>learnmybatis</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!---mybatis的依赖jar包->
        <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.15</version>
        </dependency>
        <!--用于在控制台打印出sql信息-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>

	<!--若*Mapper.xml不放在src/main/resources目录下,需要添加如下配置,否则maven是
	不会将该xml文件发布到编译后的classes目录下,这样就会导致mybatis到不到该文件。
	-->
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>
</project>

2.创建一个Student实体类并建立对应的数据库表:

package com.h3c.bean;

import org.apache.ibatis.type.Alias;

//@Alias("student")
public class Student {

    private int id;
    private String name;
    private int age;
    private double score;

    //省略constructor、getter、setter、toString方法
}
CREATE TABLE `learnmybatis`.`t_student` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(20) NULL,
  `age` INT NULL,
  `score` DOUBLE NULL,
  PRIMARY KEY (`id`));

3.定义一个dao的接口:

package com.h3c.dao;

import com.h3c.bean.Student;

import java.util.List;

public interface StudentDao {
    void insertStudent(Student student);

    void deleteStudentById(int id);

    void updateStudent(Student student);

    Student selectStudentById(int id);

    List<Student> selectAllStudents();

    List<Student> selectStudentByName(String name);
}

4.添加mapper映射文件

映射文件,一般称之为mapper,主要是在里面编写SQL语句。dtd约束可以直接拷贝下面的内容。mapper的文件名随意,一般会跟dao接口放在同一个包下,这里映射文件名称定为StudentMapper.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="mybatis">
    <!--parameterType可省略,MyBatis会自动识别-->
    <insert id="insertStudent" parameterType="com.h3c.bean.Student">
        INSERT INTO t_student(name,age,score) VALUES (#{name},#{age},#{score});
        <!--获取主键(主键使用自增的策略,当数据插入数据库后才会生成主键)-->
        <selectKey resultType="int" keyProperty="id" order="AFTER">
            SELECT @@identity
        </selectKey>
    </insert>
    <delete id="deleteStudentById">
        DELETE from t_student where id=#{id}
    </delete>
    <update id="updateStudent">
        UPDATE t_student set name=#{name},age=#{age},score=#{score} where id=#{id}
    </update>
    <!--resultType表示该SQL语句返回的单条数据对应的类型,这里写mybatis.xml文件中配置的别名,首字母大小写均可(若配置文件中未配置,需要写实体类的全限定名)-->
    <select id="selectAllStudents" resultType="student">
        select id,name,age,score from t_student
    </select>
    <select id="selectStudentById" resultType="Student">
        select id,name,age,score from t_student where id=#{id}
    </select>
    <!--模糊查询 注意:’%’ #{name} ‘%’之间是没有+号的,即这里的字符串拼接不需要+号,而是需要空格。-->
    <select id="selectStudentByName" resultType="student">
        SELECT id,name,age,score FROM t_student where name like '%' #{name} '%'
    </select>
</mapper>

模糊查询的另一种写法

<select id="selectStudentByName" resultType="student">
    SELECT id,name,age,score FROM t_student where name like '%${value}%'
</select>

因为我们传入的name是String字符串类型,所以这里需要注意的是${}中的内容只能写value,可以通过控制台打印的sql语句看出来,这种方式其实就是是字符串拼接,该方式可能会有SQL注入的问题。

#和$区别

  • #其实是占位符,通过控制台打印的sql语句可以看出,他是以?进行占位的,类似JDBC的PreparedStatement,可以防止SQL注入的问题,在上面的sql语句中我们写的是#{id},实际上#{}里面的内容可以写成其他字符串#{xxx},这里只是起着占位符的作用,mybatis会将sqlSession.selectList或sqlSession.selectOne等方法中的第二个参数赋值进去。因此如果sql语句需要获取用户的输入从而进行动态拼接的话,就需要使用#{}。
  • $是字符串拼接,参数会被直接拼接到SQL语句中,该方式会有SQL注入问题,如果SQL语句由我们程序员直接写好,不需要用户输入的话,可以使用${},不过一般还是建议使用#{}。

5.添加数据库相关配置文件(指定数据源)

在resources目录下创建db.properties配置文件,文件名随意:

#mysql数据库驱动8版本以上添加如下驱动类,5版本是com.mysql.jdbc.Driver
jdbc.driver=com.mysql.cj.jdbc.Driver
#注意:#mysql数据库驱动8版本以上需要指定时区
jdbc.url=jdbc:mysql://127.0.0.1:3306/learnmybatis?useSSL=false&amp;serverTimezone=Asia/Shanghai
jdbc.user=root
jdbc.password=12345

6.添加mybatis的主配置文件,引入上面配置的数据源

主配置文件的名称可以随意命名,这里将其命名为mybatis.xml,将其放到maven项目中的resources目录下。

<?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>
    <!--1、注册数据库配置文件-->
    <properties resource="db.properties"/>

    <!--注意:MyBatis配置文件中的标签是有顺序的-->
    <!--2、注册实体类的全限定名的别名-->
    <!--我们还可以在实体类上使用@Alias注解来手动给他取一个别名-->
    <!--另外mybatis已经为一些常见的类内建了别名-->
    <typeAliases>
        <!--方式一:不方便-->
        <!--<typeAlias type="com.h3c.bean.Student" alias="student"/>-->

        <!--方式二:MyBatis会在这个包下搜索需要的bean,生成全限定名的别名(默认是小写字母开头的实体类名)-->
        <package name="com.h3c.bean"/>
    </typeAliases>

	<!--配置MyBatis运行环境,即数据源与事务管理器-->
    <!--environments中可进行多环境配置,实际使用的环境由default属性决定-->
    <environments default="dev">
        <environment id="dev">
        	<!--指定MyBatis所使用的事务管理器-->
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.user}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--注册映射文件-->
        <mapper resource="com/h3c/dao/StudentMapper.xml"/>
    </mappers>
</configuration>
  • transactionManager标签
    该标签用于指定MyBatis所使用的事务管理器。 MyBatis 支持两种事务管理器类型:

    • JDBC
      该事务器就是我们之前通过Connection的commit()方法提交,通过rollback()方法回滚,默认是需要手动提交的。

    • MANAGED
      由容器来管理事务的整个事务的生命周期,默认情况下会关闭连接,将来学习spring框架之后,就不用在配置事务管理器了,spring会使用自带的管理器。

  • dataSource标签
    该项主要用于配置数据源和数据库连接基本属性,有以下三种内建的数据源类型:

    • UNPOOLED
      该配置表示不使用连接池,每次请求都会创建一个数据库连接,使用完毕后再关闭。当项目对数据库性能要求不大的时候,可以使用该配置。
    • POOLED
      改配置表示使用mybatis自带的数据库连接池,可以在dataSource下的property属性中设置数据库连接池的基本信息,该部分可以在mybatis的官网中看到。
    • JNDI
      配置外部数据源
  • mapper映射器
    MyBatis 是基于 sql 映射配置的框架,sql 语句都写在 Mapper 配置文件中,当构建 SqlSession 类之后,就需要去读取 Mapper 配置文件中的 sql 配置。
    而映射器的作用就是在告诉mybatis.xml配置文件我们编写的mapper所在的路径,一共有四种写法:
    第一种:相对路径配置

    <mappers>
    <!--使用相对于类路径的资源引用-->
    <mapper resource="com/h3c/dao/StudentMapper.xml"/>
    </mappers>
    

    第二种:使用URL绝对路径方式引入(不用)

    <mappers>
        <!--通过url引入网络资源或者本地磁盘资源-->
        <mapper url="F:///h3c/StudentMapper.xml"/>
    </mappers>
    

    第三种:类注册引入
    该方式的使用,需要满足以下几个要求:
    (1)映射文件名要与 Dao 接口名称相同
    (2)映射文件要与接口在同一包中
    (3)映射文件中的 namespace 属性值为 Dao 接口的全类名

    <mappers>
    	<!--使用mapper标签的class属性指定mapper接口名称-->
    	<mapper class="com.monkey1024.dao.StudentDao"/>
    </mappers>
    

    第四种:接口所在包
    这种方式的使用需要满足以下几个条件:
    (1)映射文件名要与 Dao 接口名称相同
    (2)映射文件要与接口在同一包中
    (3)映射文件中的 namespace 属性值为 Dao 接口的全类名

    <mappers>
        <!--通过package标签的name属性指定mapper接口所在的包名-->
        <package name="com.monkey1024.dao"/>
    </mappers>
    

7.查看mybatis输出日志

mybatis支持下面的日志处理:

  • slf4j
  • Apache Commons Logging
  • Log4j
  • Log4j 2
  • JDK logging

在resources目录下创建log4j.properties文件,里面加上下面内容:

#log4j.rootLogger=debug,console
#只查看某个namespace(mybatis是在StudentMapper.xml中指定的)下的日志
log4j.logger.mybatis=debug,console

#控制台附加器
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern= [%-5p][%d{yyyy-MM-dd HH:mm:ss}]%m%n

8.创建获取SqlSession对象的工具类

其中用到的一些类:

  • SqlSessionFactoryBuilder
    作用就是创建SqlSessionFactory,在创建SqlSessionFactory之后就不再需要SqlSessionFactoryBuilder了。

  • SqlSessionFactory
    SqlSessionFactory是线程安全的,在应用中只创建一个SqlSessionFactory即可,即最好保证其是单例的,通过SqlSessionFactory我们可以创建出SqlSession。

  • SqlSession
    SqlSession是线程不安全的,在后面跟spring进行集成之后,可以创建出线程安全的SqlSession对象。如果单独使用的话,别忘了关闭SqlSession对象。

package com.h3c.util;

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;

/*
 * DCL单例模式,这里只是将单例模式应用在创建SqlSessionFactory对象上
 */
public class MyBatisUtil {

    private static volatile SqlSessionFactory sqlSessionFactory;

    public static SqlSession getSqlSession() {

        try {
            if(null == sqlSessionFactory) {
                //读取主配置文件
                InputStream input = Resources.getResourceAsStream("mybatis.xml");
                synchronized (MyBatisUtil.class) {
                    if(null == sqlSessionFactory) {
                    	//创建SqlSessionFactory对象
                        sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
		
		//创建SqlSession对象并返回
        return sqlSessionFactory.openSession();
    }
}

9.创建DAO接口的实现类

创建StudentDao接口的实现类StudentDaoImpl:

package com.h3c.dao.impl;

import com.h3c.bean.Student;
import com.h3c.dao.StudentDao;
import com.h3c.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;

import java.util.List;

public class StudentDaoImpl implements StudentDao {

    @Override
    public void insertStudent(Student student) {
        try (SqlSession sqlSession = MyBatisUtil.getSqlSession()){
            //新增数据操作
            sqlSession.insert("insertStudent", student);
            /*
             *当执行插入操作的时候,可以看到在提交事务之前,其实就已经获取到这个主键id了,
             * 就是说不管是提交还是回滚,这个主键都是先获取到的。当执行sql语句之后,数据
             * 库就会给该条数据分配一个主键,倘若回滚的话,这个主键就不能用了,下次再执行
             * 插入操作时,会在该id之后再分配一个id。
             * 由此可以得出一个结论:
             * 主键的生成跟事务没有关系,只要执行了sql语句,mysql就会为其分配一个主键。
             */
            System.out.println("提交数据库之前:" + student);
            //提交SqlSession
            sqlSession.commit();
        }
    }

    @Override
    public void deleteStudentById(int id) {
        try(SqlSession sqlSession = MyBatisUtil.getSqlSession()) {

            sqlSession.delete("deleteStudentById", id);

            sqlSession.commit();
        }
    }

    @Override
    public void updateStudent(Student student) {
        try(SqlSession sqlSession = MyBatisUtil.getSqlSession()) {

            sqlSession.update("updateStudent",student);

            sqlSession.commit();
        }
    }

    @Override
    public Student selectStudentById(int id) {
        Student student = null;

        try(SqlSession sqlSession = MyBatisUtil.getSqlSession()) {

            //根据id查询数据操作
            student = sqlSession.selectOne("selectStudentById", id);
        }

        return student;
    }

    @Override
    public List<Student> selectAllStudents() {
        List<Student> result = null;

        try(SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
            //查询数据操作
            result = sqlSession.selectList("selectAllStudents");
        }

        return result;
    }

    @Override
    public List<Student> selectStudentByName(String name) {
        List<Student> result = null;

        try(SqlSession sqlSession = MyBatisUtil.getSqlSession()) {

            //查询数据操作
            result = sqlSession.selectList("selectStudentByName",name);
        }

        return result;
    }
}

10.使用了junit测试:

在src/test/java目录下新建测试类:

import com.h3c.bean.Student;
import com.h3c.dao.StudentDao;
import com.h3c.dao.impl.StudentDaoImpl;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

public class StudentTest {

    private StudentDao studentDao;

    @Before
    public void initStudentDao(){
        studentDao = new StudentDaoImpl();
    }

    /**
     * 插入
     */
    @Test
    public void insertStudent(){
        Student student = new Student("Lucy", 18, 95.50);

        //此时主键未生成,id是默认值0
        System.out.println("before:" + student);
        studentDao.insertStudent(student);
        /*
         数据已写入数据库,mybatis会主动执行SELECT @@identity 语句帮我们将该数据的主键查询出来,
         此时可以获取到id的值,不用自己单独再去数据库查
         */
        System.out.println("after:" + student);
    }

    /**
     * 删除
     */
    @Test
    public void deleteStudent(){
        //删除id是7的数据
        studentDao.deleteStudentById(7);
    }

    /**
     * 更新
     */
    @Test
    public void updateStudent(){
        Student student = new Student("Lily", 16, 96.50);
        student.setId(7);
        studentDao.updateStudent(student);
    }

    /**
     * 查询所有Student
     */
    @Test
    public void selectAllStudents(){
        List<Student> students = studentDao.selectAllStudents();
        students.forEach((student)->{
            System.out.println(student);
        });
    }

    /**
     * 查询单个Student
     */
    @Test
    public void selectStudentById(){
        Student student = studentDao.selectStudentById(7);
        System.out.println(student);
    }

    /**
     * 根据name模糊查询
     */
    @Test
    public void selectStudentByName(){
        List<Student> students = studentDao.selectStudentByName("L");
        students.forEach((student)->{
            System.out.println(student);
        });
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值