认识mybatis

mybatis和JDBC的作用一致,是用来对数据库执行操作的,但是优越在:

支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

要在项目中使用mybatis,需要mybatis和mysql-connector-java(相应数据库即可)两个jar包。

在配置上,需要给每张表一个映射文件mapper.xml,以及全局的mybatis-config.xml。

来看看如何使用mybatis。

一、利用maven或者手动导入jar包。

<dependency>
 <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
 <version>3.4.6</version>
</dependency>
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.11</version>
</dependency>

二、利用Mysql建库建表(或者其他数据库)。步骤如下(或者用可视化工具更快):

1、mysql -u root -p 然后输入密码登陆

2、create database testbase 或者 use testbase 选择一个数据库

3、任意建两张表,再插入部分数据:


三、建立如下结构:

其中,entity中的类可以理解是表中的记录项,mappers中的则用来提供增删查改接口,mapper配置文件和mybatis全局配置文件放在resources下。

具体来说,entity中的实体类的属性是和表的列相对应的,由mapper.xml完成二者之间的映射关系。而mapper文件夹下的mapper.java则是提供了操作数据库的接口,实际上它并不需要实现类(这里的impl文件下的实现类是用来方便使用而封装的)。

四、具体介绍

1、entity(以下均以Dragon为例,Warrior只需要改个名就行了)


//Dragon.java
package cn.ldy.entity;

public class Dragon {
    private int id;
    private String field;
    private String name;
    private int level;
    private String attribute;

    @Override
    public String toString() {
        return "Dragon{" +
                "id=" + id +
                ", field='" + field + '\'' +
                ", name='" + name + '\'' +
                ", level=" + level +
                ", attribute='" + attribute + '\'' +
                '}';
    }

    public int getId() {
        return id;
    }

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

    public String getField() {
        return field;
    }

    public void setField(String field) {
        this.field = field;
    }

    public String getName() {
        return name;
    }

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

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public String getAttribute() {
        return attribute;
    }

    public void setAttribute(String attribute) {
        this.attribute = attribute;
    }
}

2、mappers


//DragonMapper.java
package cn.ldy.mappers;

import cn.ldy.entity.Dragon;

import java.io.IOException;
import java.util.List;

public interface DragonMapper {
    public void insertDragon(Dragon Dragon) throws IOException;

    public void deleteDragonById(int id) throws IOException;

    public void deleteAll() throws IOException;

    public void updateDragon(Dragon Dragon);

    public List<Dragon> queryAll();

    public Dragon queryDragonById(int id);
}

3、mappers.impl


//DragonMapperImpl.java
package cn.ldy.mappers.impl;

import cn.ldy.entity.Dragon;
import cn.ldy.mappers.DragonMapper;
import cn.ldy.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;

import java.io.IOException;
import java.util.List;

public class DragonMapperImpl {
    private static SqlSession sqlSession;
    public static void insertDragon(Dragon dragon) {
        /*
        一种方式
        sqlSession = MybatisUtil.getSession();
        sqlSession.insert("insertDragon", dragon);
        sqlSession.commit();
        sqlSession.close();
        */

        //另一种方式
        sqlSession = MybatisUtil.getSession();
        DragonMapper dragonMapper = sqlSession.getMapper(DragonMapper.class);
        try{
            dragonMapper.insertDragon(dragon);
            System.out.println(dragon.toString() + "inserted!");
            sqlSession.commit();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void deleteDragonById(int id) {
        sqlSession = MybatisUtil.getSession();
        DragonMapper dragonMapper = sqlSession.getMapper(DragonMapper.class);
        try{
            dragonMapper.deleteDragonById(id);
            sqlSession.commit();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void deleteAll() {
        sqlSession = MybatisUtil.getSession();
        DragonMapper dragonMapper = sqlSession.getMapper(DragonMapper.class);
        try{
            dragonMapper.deleteAll();
            sqlSession.commit();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void updateDragon(Dragon dragon) {
        sqlSession = MybatisUtil.getSession();
        DragonMapper dragonMapper = sqlSession.getMapper(DragonMapper.class);
        dragonMapper.updateDragon(dragon);
        sqlSession.commit();
    }

    public static List<Dragon> queryAll() {
        sqlSession = MybatisUtil.getSession();
        DragonMapper dragonMapper = sqlSession.getMapper(DragonMapper.class);
        List<Dragon> list = dragonMapper.queryAll();
        sqlSession.commit();
        return list;
    }

    public static Dragon queryDragonById(int id) {
        sqlSession = MybatisUtil.getSession();
        DragonMapper dragonMapper = sqlSession.getMapper(DragonMapper.class);
        Dragon dragon = dragonMapper.queryDragonById(id);
        sqlSession.commit();
        return dragon;
    }
}

调用这些方法有两种方式,这里首先利用util工具类产生一个SqlSession对象。在工具类中,读取了相应的xml配置文件,利用会话getMapper方法就可以直接调用在xml文件中实现了的接口方法了。

4、util


//MybatisUtil.java
package cn.ldy.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.Reader;

public class MybatisUtil {
    private static String resource="mybatis-config.xml";
    static Reader reader;
    static{
        try {
            reader= Resources.getResourceAsReader(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private static SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
    public static SqlSession getSession() {
        return sqlSessionFactory.openSession();
    }
}

该工具类用来产生一个SqlSession对象。

5、resources


//mybatis-config.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">
<configuration>
    <settings>
        <setting name="lazyLoadingEnabled" value="false" />
    </settings>
   <typeAliases>
        <!--给实体类取别名,方便在mapper配置文件中使用 -->
        <typeAlias alias="Dragon" type="cn.ldy.entity.Dragon" />
        <typeAlias alias="Warrior" type="cn.ldy.entity.Warrior" />
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <!--连接数据库的属性,同JDBC -->
                <property name="driver" value="com.mysql.cj.jdbc.Driver" />
                <!-- ?serverTimezone=GMT%2B8   这部分可以不加,这是由于我这里Mysql报了时区错误-->
                <property name="url" value="jdbc:mysql://localhost:3306/testbase?serverTimezone=GMT%2B8" />
                <property name="username" value="root" />
                <property name="password" value="" />
            </dataSource>
        </environment>
   </environments>
    <!--这里要填入具体的配置文件的地址 -->
    <mappers>
        <mapper resource="mappers/DragonMapper.xml" />
        <mapper resource="mappers/WarriorMapper.xml" />
    </mappers>
</configuration>

在typeAliases中填写的别名,是为了在具体的xml配置文件中方便表示。
如果不设置,后面的parameterType等都要写全。

6、resources.mappers


//DragonMapper.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="cn.ldy.mappers.DragonMapper">

    <!--由于在mybatis-config.xml里配置了别名,所以不必写出完整的cn.ldy.entity.Dragon -->
    <insert id="insertDragon" parameterType="Dragon">
        insert into dragon(field,name,level,attribute)
        values(#{field}#,#{name},#{level},#{attribute})
    </insert>

    <!--虽然返回的是列表,但是resultType填写的应该是容器中的类型 -->
    <select id="queryAll" resultType="Dragon">
        select * from dragon
    </select>

    <select id="queryDragonById" parameterType="int" resultType="Dragon">
        select * from dragon
         where id = #{id}
    <select>
    
    <delete id="deleteAll">
        delete from dragon
    </delete>
    
    <delete id="deleteDragonById" parameterType="int">
        delete from dragon
        where id = #{id}
    </delete>

    <update id="updateDragon" parameterType="Dragon">
        update dragon
        <set>
            field = #{field},
            name = #{name},
            level = #{level},
            attribute = #{attribute}
        </set>
        where id = #{id}
    </update>
</mapper>

namespace中是个例外,即使设置了别名也要写全路径。
后面的四种类标签则对应增删查改四种方法,其中id名和接口中的方法名保持一致,参数类型parameterType和返回类型resultType也是。注意的是,如果类型是List这样的容器,填的仍然是容器中的类型。具体的实现中,用 #{}的格式作占位符,内部名字没有要求,但是最好和对应属性名一致。

五、测试


package cn.ldy.test;
import cn.ldy.entity.Dragon;
import cn.ldy.entity.Warrior;
import cn.ldy.mappers.impl.DragonMapperImpl;
import cn.ldy.mappers.impl.WarriorMapperImpl;
import java.util.List;
public class Test {
    public static void main(String[] args) {
        List<Dragon> dragonList= DragonMapperImpl.queryAll();
        System.out.println(dragonList.toString());
        List<Warrior> warriorList = WarriorMapperImpl.queryAll();
        System.out.println(warriorList.toString());
    }
}

输出结果:

7、流程

回顾一下,发现流程是这样的,工具类解析mybatis-config.xml,返回一个会话,返回一个代理类(貌似是)使接口可以“执行”对应xml里的语句实现,提交会话,执行操作。
可以发现,将接口和实现对应起来的,是id这个属性,如果selectDragonById和selectDragonByname两个接口以及对应的xml中的实现,那么我们在执行getMapper返回的那个代理类的selectDragonById的时候,由于它与xml文件里的id=“selectDragonById”一致,所以执行的就是它的实现。
那么在这个例子中,有DragonMapper.xml和WarriorMapper.xml两个配置文件,里面都有id = "queryAll",当我使用DragonMapperImpl.queryAll()的时候,怎么知道对应的是哪个配置文件里的queryAll呢? 答案就是命名空间namespace√。

posted @ 2018-07-24 17:16  木子李太宗  阅读(159)  评论(0编辑  收藏  举报