关于mybatis的思考(1)——mybatis的使用实例

架构分析


    MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架。 MyBatis 消除了几乎所有的 JDBC 代码和参数的手工设置以及对结果集的检索。MyBatis 可以使用简单的XML 或注解用于配置和原始映射,将接口和 Java 的 POJO( Plain Old Java Objects,普通的Java 对象)映射成数据库中的记录。

该图引用于51CTO

    借助于该架构图我们可以发现,Mybatis的功能架构分为三层:

(1)API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。

(2)数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。

(3) 基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。

    作为持久层框架,mybatis可以将程序中的大量sql语句剥离出来,配置在配置文件中,实现sql的灵活配置。可以将sql语句和代码分离,无需修改代码,在配置文件中修改配置文件即可到达修改sql的目的。

    开发人员面对的是纯粹的java对象,和hibernate的orm思想一致。但对于具体的数据操作,hibernate会自动生成sql语句,而mybatis使用的时候,需要开发人员编写配置文件,将sql所需要的参数和返回的结果字段映射到具体的pojo。


maven依赖

    为了方便,构建的是maven项目,需要的依赖分别有:

  1. junit     (java单元测试依赖)
  2. mybatis(mybatis依赖)
  3. mysql   (mysql数据库依赖)
  4. log4j    (日志信息依赖)
<dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>3.8.1</version>
                <scope>test</scope>
            </dependency>

            <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.1</version>
            </dependency>

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

            <!-- https://mvnrepository.com/artifact/log4j/log4j -->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.17</version>
            </dependency>

        </dependencies>

建立数据库

    为了测试mybatis的功能,首先建立一个简单的数据库,比较简单,数据库字段含义不再赘述。

create database mybatis;

use mybatis;

CREATE TABLE `tb_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(18) DEFAULT NULL,
  `sex` char(2) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) 

建立pojo对象

    在这里建立了一个非常简单的pojo类,用于测试mybatis的功能。

/**
 * fayuan.com Inc.
 * Copyright (c) 2017-2018 All Rights Reserved.
 */
package com.fayuan.domain;

/**
 * 用户类
 *
 * @author fayuan.fzw
 * @version $Id: User.java, v 0.1 2018年02月18日 上午11:05 fayuan.fzw Exp $
 */
public class User {

    /** id */
    private int id;

    /** 姓名 */
    private String name;

    /** 性别 */
    private String sex;

    /** 年龄 */
    private int age;

    public User(String name, String sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

  这个类其实就是一个普通的javaBean,mybatis使用pojo类作为持久化类,这也是mybatis低侵入设计的关键。mybatis不需要持久化类继承任何父类,或者实现接口,可以保证代码的无侵入无污染。


pojo和数据库表字段映射

    为了实现pojo和数据表中字段的映射,需要通过配置文件来配置具体的映射。

<?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">
<!-- namespace指用户自定义的命名空间。 -->
<mapper namespace="com.fayuan.mapper.UserMapper">

    <!--
        id="save"是唯一的标示符
        parameterType属性指明插入时使用的参数类型
        useGeneratedKeys="true"表示使用数据库的自动增长策略
     -->
    <insert id="save" parameterType="com.fayuan.domain.User" useGeneratedKeys="true">
        insert into tb_user (name,sex,age) VALUES (#{name},#{sex},#{age})
    </insert>

    <!-- select操作
    parameterType="int"表示该查询语句需要一个int类型的参数
    resultType="user"表示返回的是一个user对象 -->
    <select id="select" parameterType="int" resultType="User">
        select * from tb_user where id=#{id}
    </select>

    <!-- update操作
    parameterType="user"表示该更新语句需要一个user对象作为参数-->
    <update id="update" parameterType="User">
        update tb_user set name= #{name},sex= #{sex},age=#{age} where id= #{id}
    </update>

    <!-- delete操作
    parameterType="int"表示该查询语句需要一个int类型的参数-->
    <delete id="delete" parameterType="int">
        delete from tb_user where id=#{id}
    </delete>

</mapper>

     在这里一次性添加了增、删、查、改的映射关系,为了实现每一部分的功能,对于每一部分单独写一个测试类。

插入

/**
 * Alipay.com Inc.
 * Copyright (c) 2004-2018 All Rights Reserved.
 */
package com.fayuan.test;

import java.io.InputStream;

import com.fayuan.domain.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

/**
 * 测试插入功能
 *
 * @author fayuan.fzw
 * @version $Id: InsertTest.java, v 0.1 2018年02月19日 下午4:02 fayuan.fzw Exp $
 */
public class InsertTest {
    public static void main(String[] args) throws Exception {

        //读取mybatis-config.xml文件
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");

        //初始化mybatis,创建SqlSessionFactory类的实例
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //创建Session实例
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //创建User对象
        User user = new User ("fayuan","男",24);

        //插入数据
        sqlSession.insert("com.fayuan.mapper.UserMapper.save", user);

        //提交事务
        sqlSession.commit();

        //关闭session
        sqlSession.close();
    }
}

     打印出来的日志:

DEBUG [main] - ==>  Preparing: insert into tb_user (name,sex,age) VALUES (?,?,?) 
DEBUG [main] - ==> Parameters: fayuan(String), 男(String), 24(Integer)
DEBUG [main] - <==    Updates: 1

查找

/**
 * fayuan.com Inc.
 * Copyright (c) 2017-2018 All Rights Reserved.
 */
package com.fayuan.test;

import com.fayuan.domain.User;
import com.fayuan.factory.SqlSessionFactoryClass;
import org.apache.ibatis.session.SqlSession;

/**
 * 测试查找功能
 *
 * @author fayuan.fzw
 * @version $Id: SelectTest.java, v 0.1 2018年02月24日 下午11:19 fayuan.fzw Exp $
 */
public class SelectTest {
    public static void main(String[] args) {

        //获取Session实例
        SqlSession sqlSession = SqlSessionFactoryClass.getSqlSession();

        // 创建User对象
        User user = sqlSession.selectOne("com.fayuan.mapper.UserMapper.select", 1);

        System.out.println("name = " + user.getName() + ", sex = " + user.getSex() +", age = " + user.getAge());

        //提交事务
        sqlSession.commit();

        //关闭Session
        sqlSession.close();
    }
}

    打印出来的日志: 

DEBUG [main] - ==>  Preparing: select * from tb_user where id=? 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1

修改

/**
 * fayuan.com Inc.
 * Copyright (c) 2017-2018 All Rights Reserved.
 */
package com.fayuan.test;

import com.fayuan.domain.User;
import com.fayuan.factory.SqlSessionFactoryClass;
import org.apache.ibatis.session.SqlSession;

/**
 * 测试修改功能
 * @author fayuan.fzw
 * @version $Id: UpdateTest.java, v 0.1 2018年02月24日 下午11:03 fayuan.fzw Exp $
 */
public class UpdateTest {
    public static void main(String[] args) {

        //获取Session实例
        SqlSession sqlSession = SqlSessionFactoryClass.getSqlSession();

        // 根据id查询User对象
        User user = sqlSession.selectOne("com.fayuan.mapper.UserMapper.select",1);
        // 修改User对象的属性值
        user.setName("tom");
        user.setAge(25);
        // 修改User对象
        sqlSession.update("update", user);
        // 提交事务
        sqlSession.commit();
        // 关闭Session
        sqlSession.close();
    }
}

    打印出来的日志:

DEBUG [main] - ==>  Preparing: select * from tb_user where id=? 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
DEBUG [main] - ==>  Preparing: update tb_user set name= ?,sex= ?,age=? where id= ? 
DEBUG [main] - ==> Parameters: tom(String), ?(String), 25(Integer), 1(Integer)
DEBUG [main] - <==    Updates: 1

删除

/**
 * fayuan.com Inc.
 * Copyright (c) 2017-2018 All Rights Reserved.
 */
package com.fayuan.test;

import com.fayuan.factory.SqlSessionFactoryClass;
import org.apache.ibatis.session.SqlSession;

/**
 * 测试删除功能
 *
 * @author fayuan.fzw
 * @version $Id: DeleteTest.java, v 0.1 2018年02月24日 下午11:55 fayuan.fzw Exp $
 */
public class DeleteTest {
    public static void main(String[] args) throws Exception {
        
        // 获得Session实例
        SqlSession session = SqlSessionFactoryClass.getSqlSession();
        // 删除id为1的User对象
        session.delete("com.fayuan.mapper.UserMapper.delete", 1);
        // 提交事务
        session.commit();
        // 关闭Session
        session.close();
    }

}

    打印出来的日志:

DEBUG [main] - ==>  Preparing: delete from tb_user where id=? 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==    Updates: 1 

问题总结:

  • 配置文件位置声明
  • pojo需要加上无参构造,否则在内部的反射机制是无法获得pojo对象的
  • 使用log4j观察执行状况
  • aliases的使用
  • 其他配置(pool、别名......)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java工程师日常干货

MyBatis+Spring MVC开发指南(一)前言没有MyBatis之前 MyBatis框架的架构Quick StartMapper代理开发关于自增主键返回关于动态SQL

MyBatis+Spring MVC这套组合,在实际互联网项目中非常流行,博主工作中也涉及过,打算由浅入深、系统的写出来!这个系列将会涵盖MyBatis开发详解...

552
来自专栏java学习

SSM框架原理,作用及使用方法

注:本公众号纯属个人公益公众号!不存在任何收费项目!免费分享所有学习资料!只求大家多多支持!多多关注!!

660
来自专栏Java帮帮-微信公众号-技术文章全总结

JavaWeb17-案例之ajax(Java真正的全栈开发)

案例 & ajax 一.案例 1. 生成订单操作分析 先看下订单页面: 分析下订单表需要那些字段 id 收货人(receiverName) 收货地址(recei...

35310
来自专栏Java3y

Mybatis面试题

Mybatis常见面试题 #{}和${}的区别是什么? {}和${}的区别是什么? 在Mybatis中,有两种占位符 #{}解析传递进来的参数数据 ${}对传递...

5264
来自专栏JadePeng的技术博客

使用Mongodb 做对象缓存

mongodb高效的访问速度,用来快速存取数据再合适不过了,缓存神马的,可以用这个的 另外,有的时候,如果仅仅存储几条数据,单独去建立一张表代价太大,这个时候,...

3255
来自专栏Java3y

用户登陆注册【JDBC版】

前言 在讲解Web开发模式的时候,曾经写过XML版的用户登陆注册案例!现在在原有的项目上,使用数据库版来完成用户的登陆注册!如果不了解的朋友,可以看看我Web开...

3119
来自专栏青枫的专栏

day30_Hibernate学习笔记_02

对象状态 瞬时态|临时态:Transient     1、没有与Hibernate产生关联(没有与Session有关联)。     2、与数据库中的记录没有产...

632
来自专栏程序你好

不同的.Net版本客户端软件调用Java Web Service区别

最近的系统中需要.Net开发的离线端软件通过Web Service技术和Java开发的在线系统进行数据交互。

693
来自专栏技术小讲堂

iBatis.Net(4):DataMapper API

在iBatis.Net中,可以通过SqlMapper实例访问DataMapper API,其实以前写的都是一些iBatis.Net的概念和一些配置的问题,从这一...

31410
来自专栏ImportSource

Junit 5新特性全集

本文略长,但都是大白话,如果你能一口气看完,你赢了。 如果你来不及看这么长,那么建议你滑到文末,直接看黑体部分就知道大概了。 在5中的一个测试类的基本生命周期是...

43211

扫码关注云+社区