Mybatis学习总结第一课---Mybatis简介和快速入门

一MyBatis 简介

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

1.1、MyBatis的特点

简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。

灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多。

解除sql与程序代码的耦合

通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。

提供映射标签,支持对象与数据库的ORM字段关系映射

提供对象关系映射标签,支持对象关系组建维护

提供XML标签,支持编写动态sql。

1.2、MyBatis工作流程

(1)、加载配置并初始化

触发条件:加载配置文件

配置来源于两个地方,一处是配置文件,一处是Java代码的注解,将SQL的配置信息加载成为一个个MappedStatement对象(包括了传入参数映射配置、执行的SQL语句、结果映射配置),存储在内存中。

(2)、接收调用请求

触发条件:调用Mybatis提供的API

传入参数:为SQL的ID和传入参数对象

处理过程:将请求传递给下层的请求处理层进行处理。

(3)、处理操作请求 触发条件:API接口层传递请求过来 

传入参数:为SQL的ID和传入参数对象

处理过程:
  (A)根据SQL的ID查找对应的MappedStatement对象。

  (B)根据传入参数对象解析MappedStatement对象,得到最终要执行的SQL和执行传入参数。

  (C)获取数据库连接,根据得到的最终SQL语句和执行传入参数到数据库执行,并得到执行结果。

  (D)根据MappedStatement对象中的结果映射配置对得到的执行结果进行转换处理,并得到最终的处理结果。

  (E)释放连接资源。

(4)、返回处理结果将最终的处理结果返回。

无论是用过的hibernate,mybatis,你都可以法相他们有一个共同点:

在java对象和数据库之间有做mapping的配置文件,也通常是xml 文件

从配置文件(通常是XML配置文件中)得到 SessionFactory

由SessionFactory 产生 Session

在Session中完成对数据的增删改查和事务提交等

在用完之后关闭Session

1.3、MyBatis架构

Mybatis的功能架构分为三层:

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

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

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

 

1.4、MyBatis的主要成员如层次结构

主要成员:

Configuration:MyBatis所有的配置信息都保存在Configuration对象之中,配置文件中的大部分配置都会存储到该类中

SqlSession:作为MyBatis工作的主要顶层API,表示和数据库交互时的会话,完成必要数据库增删改查功能

Executor:MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护

StatementHandler:封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数等

ParameterHandler:负责对用户传递的参数转换成JDBC Statement 所对应的数据类型

ResultSetHandler:负责将JDBC返回的ResultSet结果集对象转换成List类型的集合

TypeHandler:负责java数据类型和jdbc数据类型(也可以说是数据表列类型)之间的映射和转换

MappedStatement:MappedStatement维护一条<select|update|delete|insert>节点的封装

SqlSource:负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回

BoundSql:表示动态生成的SQL语句以及相应的参数信息

层次结构:

 

 

1.5、学习资源

mybatis3中文帮助:http://www.mybatis.org/mybatis-3/zh/index.html

mybatis-spring:http://www.mybatis.org/spring/zh/index.html

MyBatis中国分站:http://www.mybatis.cn/

源代码:https://github.com/mybatis/mybatis-3/

二、MyBatis示例

2.1、在IDEA中创建项目

普通java项目或者是Maven项目都可以,如下图所示:

2.2、添加依赖


		<!-- mysql驱动 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.18</version>
		</dependency>


		<!-- mybatis相关依赖 -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.4.1</version>
		</dependency>

 

3、创建数据库和表,针对MySQL数据库

SQL脚本如下:

 

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '编号',
  `username` varchar(20) NOT NULL COMMENT '用户名',
  `password` varchar(10) NOT NULL COMMENT '密码',
  `name` varchar(20) NOT NULL COMMENT '姓名',
  `email` varchar(50) DEFAULT NULL COMMENT '邮箱',
  `state` varchar(50) DEFAULT NULL COMMENT '国家',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;

 

表中的数据如下:

2.3、定义操作Student表的sql映射文件

在resources目录下创建一个mapper目录,专门用于存放sql映射文件,在目录中创建一个studentMapper.xml文件,如下图所示:

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,namespace的值习惯上设置成包名+sql映射文件名,这样就能够保证namespace的值是唯一的
    例如namespace="com.dinghuoqin.dao.studentMapper"就是com.dinghuoqin.dao(包名)+studentMapper(studentMapper.xml文件去除后缀)
-->
<mapper namespace="com.dinghuoqin.dao.studentMapper">

    <!-- 在select标签中编写查询的SQL语句, 设置select标签的id属性为selectStudentById,id属性值必须是唯一的,不能够重复
         使用parameterType属性指明查询时使用的参数类型,resultType属性指明查询返回的结果集类型
         resultType="com.dinghuoqin.vo.message"就表示将查询结果封装成一个message类的对象返回
         message类就是message表所对应的实体类
     -->

    <!--查询-->
    <!--查询所有数据-->
    <select id="selectStudent"  resultType="com.dinghuoqin.vo.message">
        select id,username,password,name,email,state from  user
    </select>
    <!--根据id查询数据-->
    <select id="selectStudentById" resultType="com.dinghuoqin.vo.message">
        select id,username,password,name,email,state from  user where id = #{id}
    </select>
    <!--根据姓名模糊查询数据-->
    <select id="selectStudentByName" resultType="com.dinghuoqin.vo.message">
        select id,username,password,name,email,state from  user where name  like '%${value}%';
    </select>
    <!--分页查询-->
    <select id="selectStudentFY" resultType="com.dinghuoqin.vo.message" parameterType="java.lang.Integer">
        select id,username,password,name,email,state from  user limit #{page},#{number};
    </select>

    <!--根据id删除数据-->
    <delete id="deleteStudentById" parameterType="java.lang.Integer">
        delete  from user  where id=#{id}
    </delete>

    <!--
        添加数据
        parameterType:指定输入的参数类型是pojo(包括用户信息);
        #{}中指定pojo的属性名称,接收到pojo对象的属性值    ,mybatis通过OGNL(类似struts2的OGNL)获取对象的属性值
        useGeneratedKeys="true" keyProperty="id"
    -->
    <insert id="insertStudent" parameterType="com.dinghuoqin.vo.message" >
    <!--
        将insert插入的数据的主键返回到User对象中;
        select last_insert_id():得到刚insert进去记录的主键值,只适用于自增主键;
        keyProperty:将查询到的主键值,设置到parameterType指定的对象的那个属性
        order:select last_insert_id()执行顺序,相对于insert语句来说它的执行顺序。
        resultType:指定select last_insert_id()的结果类型;
     -->
    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer" >
        SELECT LAST_INSERT_ID() AS id;
    </selectKey>
        insert into user(username,password,name,email,state) values(#{username},#{password},#{name},#{email},#{state});
    </insert>
    
    <!--根据id修改数据修改-->
    <update id="updateStudent" parameterType="com.dinghuoqin.vo.message">
        update user set username=#{username},password=#{password},name=#{name},email=#{email},state=#{state} where id=#{id}
    </update>
</mapper>

 

解释

参考:https://www.cnblogs.com/hellokitty1/p/5216025.html

2.4、添加Mybatis配置文件

在resources目录下创建一个conf.xml文件,如下图所示:

 

conf.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>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>                     <!--加载驱动:com.mysql.jdbc.Driver-->
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis_01_user"/>  <!--数据库名称:mybatis_01_user-->
                <property name="username" value="root"/>                                    <!--用户名-->
                <property name="password" value=""/>                                        <!--密码-->

            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!-- 注册studentMapper.xml文件studentMapper.xml位于mapper这个目录下,所以resource写成mapper/studentMapper.xml-->
        <mapper resource="mapper/studentMapper.xml"/>
    </mappers>
</configuration>

 

解释

2.5、定义表所对应的实体类

message实体类的代码如下:

复制代码

package com.dinghuoqin.vo;

public class message {

    int id;
    String username;
    String password;
    String name;
    String email;
    String state;


    @Override
    public String toString() {
        return "message{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", state='" + state + '\'' +
                '}';
    }

    public int getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getName() {
        return name;
    }

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

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public message(int id, String username, String password, String name, String email, String state) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.name = name;
        this.email = email;
        this.state = state;
    }
    public message(String username, String password, String name, String email, String state) {
        this.username = username;
        this.password = password;
        this.name = name;
        this.email = email;
        this.state = state;
    }

    public message() {

    }
}

 

会话工具类:

 

package utils;

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 MyBatisUtil {

    /**
     * 获得会话工厂
     * */
    public static SqlSessionFactory getFactory(){
        InputStream inputStream = null;
        SqlSessionFactory sqlSessionFactory=null;
        try{
            //加载conf.xml配置文件,转换成输入流
            inputStream = SqlSessionFactory.class.getClassLoader().getResourceAsStream("conf.xml");
            //根据配置文件的输入流构造一个SQL会话工厂
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        }
        finally {
            if(inputStream!=null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sqlSessionFactory;
    }

    /**
     * 获得sql会话,是否自动提交
     * */

    public static SqlSession openSession(boolean isAutoCommit){
        return getFactory().openSession(isAutoCommit);
    }

    /**
     * 关闭会话
     * */
    public static void closeSession(SqlSession session){
        if(session!=null){
            session.close();
        }
    }
}

 

2.6、编写数据访问类
StudentDao.java,执行定义的select语句

 

 

package com.dinghuoqin.Dao;

import com.dinghuoqin.Daoport.StudentDaoI;
import com.dinghuoqin.vo.message;
import org.apache.ibatis.session.SqlSession;
import utils.MyBatisUtil;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class StudentDao implements StudentDaoI {


    SqlSession session = MyBatisUtil.openSession(true);
    /**
     * 根据编号查询数据
     */
    public message sel(int id){
        message entity=session.selectOne("com.dinghuoqin.dao.studentMapper.selectStudentById",id);
            return entity;
        }
    /**
     *  根据姓名模糊查询数据
     */

    public List<message> sels(String name){
        List<message> list=session.selectList("com.dinghuoqin.dao.studentMapper.selectStudentByName",name);

        return list;
    }
    /**
     *  查询所有数据
     */
    public List<message> sel(){
        List<message> list=session.selectList("com.dinghuoqin.dao.studentMapper.selectStudent");

        return list;
    }

    /**
     *  分页查询
     */
    public List<message> selFy(int x,int y){
        int i=(x-1)*y;
        Map<String,Integer> map=new HashMap<String, Integer>();
        map.put("page",i);
        map.put("number",y);


        List<message> list=session.selectList("com.dinghuoqin.dao.studentMapper.selectStudentFY",map);
        return list;
    }

    /**
     *  根据id删除数据
     */
    public int delete(int id){
        int i=session.delete("com.dinghuoqin.dao.studentMapper.deleteStudentById",id);

        session.commit();
        return i;
    }

    /**
     *  添加数据
     */
    public int insert(message m){

        session.insert("com.dinghuoqin.dao.studentMapper.insertStudent",m);
        session.commit();
        return  m.getId();
    }

    /**
     *  根据id修改数据
     */
    public int update(message m){
        int i=session.update("com.dinghuoqin.dao.studentMapper.updateStudent",m);
           session.commit();//数据库操作同步
        return i;
    }
//
    public static void main(String[] args){
        Scanner S=new Scanner(System.in);
        System.out.print("请输入用户名:");
        int name=S.nextInt();
        StudentDao dao = new StudentDao();
        message m=dao.sel(name);
        System.out.println(m);
    }
}

 执行过程解释:

 

1、mybatis配置

SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。

mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。

2、通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂

3、由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。

4、mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。

5、Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。

6、Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。

7、Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。

参考:https://www.cnblogs.com/selene/p/4604605.html

单元测试:

 

 

package test;

import com.dinghuoqin.Dao.StudentDao;
import com.dinghuoqin.vo.message;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

public class StudentDaoTest { 

@Before
public void before() throws Exception { 
} 

@After
public void after() throws Exception { 
} 

/** 
* 
* Method: sel(int id) 
* 
*/
StudentDao dao =new StudentDao();
@Test
public void testSelId() throws Exception { 
//TODO: Test goes here...
    System.out.println(dao.sel(2));

} 

/** 
* 
* Method: sels(String name) 
* 
*/

@Test
public void testSels() throws Exception { 
//TODO: Test goes here...
    System.out.println(dao.sels("小"));

} 

/** 
* 
* Method: sel() 
* 
*/ 
@Test
public void testSel() throws Exception { 
//TODO: Test goes here...
    System.out.println(dao.sel());
} 

/** 
* 
* Method: delete(int id) 
* 
*/ 
@Test
public void testDelete() throws Exception { 
//TODO: Test goes here...
    System.out.println(dao.delete(2));
} 

/** 
* 
* Method: insert(message m) 
* 
*/ 
@Test
public void testInsert() throws Exception { 
//TODO: Test goes here...
    message m=new message("丁鑫","123456","丁钦","1234567@qq.com","中国");
    System.out.println(dao.insert(m));
    System.out.println("用户编号:"+m.getId());
}
/** 
* 
* Method: update(message m) 
* 
*/ 
@Test
public void testUpdate() throws Exception { 
//TODO: Test goes here...
    message m=new message(2,"阿萨德","123456","撒旦王","1234567@qq.com","日本");
    System.out.println(dao.insert(m));
}

@Test
public void testSelFy() throws  Exception{
    List<message> m=dao.selFy(2,3);
        for (message M:m) {
        System.out.println(M);
    }
}
}

 

 

测试结果:

 

 

 

 

第三方支付功能的技术人员;尤其适合从事电商、在线教育、SaaS类项目开发的工程师。; 使用场景及目标:① 实现微信与支付宝的Native、网页/APP等主流支付方式接入;② 掌握支付过程中关键的安全机制如签名验签、证书管理与敏感信息保护;③ 构建完整的支付闭环,包括下单、支付、异步通知、订单状态更新、退款与对账功能;④ 通过定时任务处理内容支付超时与概要状态不一致问题:本文详细讲解了Java,提升系统健壮性。; 阅读应用接入支付宝建议:建议结合官方文档与沙微信支付的全流程,涵盖支付产品介绍、开发环境搭建箱环境边学边练,重点关注、安全机制、配置管理、签名核心API调用及验签逻辑、异步通知的幂等处理实际代码实现。重点与异常边界情况;包括商户号与AppID获取、API注意生产环境中的密密钥与证书配置钥安全与接口调用频率控制、使用官方SDK进行支付。下单、异步通知处理、订单查询、退款、账单下载等功能,并深入解析签名与验签、加密解密、内网穿透等关键技术环节,帮助开发者构建安全可靠的支付系统。; 适合人群:具备一定Java开发基础,熟悉Spring框架HTTP协议,有1-3年工作经验的后端研发人员或希望快速掌握第三方支付集成的开发者。; 使用场景及目标:① 实现微信支付Native模式与支付宝PC网页支付的接入;② 掌握支付过程中核心的安全机制如签名验签、证书管理、敏感数据加密;③ 处理支付结果异步通知、订单状态核对、定时任务补偿、退款及对账等生产级功能; 阅读建议:建议结合文档中的代码示例与官方API文档同步实践,重点关注支付流程的状态一致性控制、幂等性处理异常边界情况,建议在沙箱环境中完成全流程测试后再上线。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值