mybatis入门

学习目标

  • 能够了解什么是框架
  • 能够了解jdbc开发存在的问题
  • 掌握mybatis框架开发快速入门
  • 理解自定义mybatis框架

框架概述

什么是框架

框架(Framework)是整个或者部分系统的可重用设计,是J2EE底层技术的封装。框架是可以被应用开发者(程序员)定制的应用骨架。简而言之,框架其实就是别人搭好了舞台,你来做表演。

mybatis入门_第1张图片

框架解决的问题

  • 框架解决了技术整合问题

在J2EE体系中,有着各种各样的技术。不同的软件企业,根据自身的业务需求选择不同的技术,容易造成应用依赖技术,增加了项目开发实现的复杂性和技术风险性。企业项目中应该将应用的设计与实现技术解耦。

  • 框架解决了提升开发效率的问题

企业项目中使用框架,程序员不再需要重复造轮子,**只需要专注实现业务需求。**使用框架的方便性,提升了开发效率。

  • 框架解决了稳定性的问题

一个成熟的框架,经过了在众多企业项目中的验证使用。稳定性有保障。

项目分层

在J2EE应用中,通常把项目整体进行分层设计。有表现层、业务层、持久层。

mybatis入门_第2张图片

分层开发下常见框架

  • 表现层框架

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q19Rwoga-1582168772560)(media/5227a6ccc8e9d2a3d91fb44a695df1de.png)]

  • 解决技术整合的框架

mybatis入门_第3张图片

  • 持久层框架

mybatis入门_第4张图片

关于持久层的框架,还有一个封装程度更高的框架(hibernate)。该框架相对比较重量级,以及其它各个方面的原因,目前流行程度下降了很多,企业项目中用的越来越少了。

mybatis框架快速入门

框架介绍

mybatis是Apache软件基金会下的一个开源项目,前身是Ibatis框架。2010年这个项目由apache软件基金会迁移到googlecode下,改名为mybatis。2013年11月又迁移到了github。

mybatis是一个持久层的框架,是对jdbc操作数据库的封装,使开发者只需要关注业务本身,不需要花费精力去处理加载驱动、创建数据库连接对象、创建statement语句对象、参数设置、结果集处理等一系列繁杂的过程代码。

mybatis框架通过xml或注解进行配置,将java对象与sql语句中的参数自动映射生成最终执行的sql语句,并将sql语句执行结果自动映射成java对象。

三句话概括介绍:

  1. mybatis框架早期版本叫做Ibatis,目前源代码托管在github

  2. mybatis框架是对jdbc操作数据库的封装,是一个持久层的框架

  3. mybatis框架通过xml或者注解进行配置,实现java对象与sql语句的自动对应关系(映射)

入门体验

需求

查询全部用户数据。

需求实现

开发流程

mybatis框架快速入门事项 需求:查询全部用户列表。
1 创建项目
2 配置pom.xml,加入mybatis框架依赖包
3 准备配置文件:sqlMapConfig.xml,log4j.properties
4 编写用户实体类(User)
5 编写用户dao接口(UserDao)
6 编写用户dao接口映射文件(UserDao.xml)
7 在sqlMapConfig.xml中,加载UserDao.xml
8 编写测试代码

创建项目

mybatis入门_第5张图片

配置pom.xml,加入依赖

  • mybatis框架包

  • mysql数据库驱动包


<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.0modelVersion>

    <groupId>mybatisgroupId>
    <artifactId>mybatis_quickstartartifactId>
    <version>1.0-SNAPSHOTversion>

    <dependencies>
        
        <dependency>
            <groupId>org.mybatisgroupId>
            <artifactId>mybatisartifactId>
            <version>3.4.6version>
        dependency>

        
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>5.1.47version>
        dependency>

        
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.12version>
        dependency>

    dependencies>

project>

准备配置文件

sqlMapConfig.xml

说明:它是mybatis框架的核心配置文件,是执行入口。



<configuration>

    
    <environments default="mysql">
        
        <environment id="mysql">
            
            <transactionManager type="JDBC"/>
            
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/zzw?characterEncoding=utf8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            dataSource>
        environment>
    environments>

    
    <mappers>
        
        <mapper resource="dao/maps/UserDaoMap.xml"/>
    mappers>

configuration>

编写用户实体类

package com.po;

public class User {

    private int id;
    private String username;
    private String birthday;
    private String sex;
    private String address;

    public User() {
    }

    public User(int id, String username, String birthday, String sex, String address) {
        this.id = id;
        this.username = username;
        this.birthday = birthday;
        this.sex = sex;
        this.address = address;
    }

    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 getBirthday() {
        return birthday;
    }

    public void setBirthday(String birthday) {
        this.birthday = birthday;
    }

    public String getSex() {
        return sex;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", birthday='" + birthday + '\'' +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

编写用户dao接口

package com.dao;

import com.po.User;

import java.util.List;

public interface UserDao {

    List<User> findAll();
}

编写用户dao接口映射文件




<mapper namespace="com.dao.UserDao">

    
    <select id="findAll" resultType="com.po.User">
        select * FROM user
    select>

mapper>

编写测试代码

InputStream in = App.class.getResourceAsStream(“SqlMapConfig.xml”);建议是使用本类。不要乱用其他类的class文件。

import com.dao.UserDao;
import com.po.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.InputStream;
import java.util.List;

public class App {

    @Test
    public void test() throws Exception {
        //获取文件流
        InputStream in = App.class.getResourceAsStream("SqlMapConfig.xml");
        //创建工厂的构建器
        SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder();
        //创建SqlSession的工厂
        SqlSessionFactory factory = factoryBuilder.build(in);
        //创建SqlSession
        SqlSession sqlSession = factory.openSession();
        //创建接口的代理对象
        UserDao userDao = sqlSession.getMapper(UserDao.class);
        //调用方法
        List<User> users = userDao.findAll();
        for (User user : users) {
            System.out.println(user);
        }
        sqlSession.close();
        in.close();

    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KsArFbkd-1582168772562)(media/1540474390869.png)]

自定义mybatis框架【难点】

自定义框架架构分析

mybatis入门_第6张图片

序号 技术点 说明
1 xml配置文件解析 dom4j
2 jdbc连接数据库 mysql
3 数据库连接池 c3p0
4 单元测试框架 junit
5 工厂设计模式 工厂模式是我们最常用的实例化对象的模式,是用工厂方法代替new操作的一种模式。工厂模式在Java程序系统可以说是随处可见。因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的。
6 反射技术 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
7 代理 jdk提供的动态代理Proxy。
8 泛型 在编写代码时不确定类型,在使用时指定类型

准备基础环境

创建项目

mybatis入门_第7张图片

配置pom.xml,加入依赖


<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.0modelVersion>

    <groupId>TestgroupId>
    <artifactId>DemoartifactId>
    <version>1.0-SNAPSHOTversion>

    <properties>
        
        <dom4j.vesrion>1.6.1dom4j.vesrion>
        
        <jaxen.version>1.1.6jaxen.version>
        
        <mysql.version>5.1.30mysql.version>
        
        <c3p0.version>0.9.2.1c3p0.version>
        
        <junit.version>4.12junit.version>
    properties>

    <dependencies>
        
        <dependency>
            <groupId>dom4jgroupId>
            <artifactId>dom4jartifactId>
            <version>${dom4j.vesrion}version>
        dependency>
        <dependency>
            <groupId>jaxengroupId>
            <artifactId>jaxenartifactId>
            <version>${jaxen.version}version>
        dependency>
        
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>${mysql.version}version>
        dependency>
        
        <dependency>
            <groupId>com.mchangegroupId>
            <artifactId>c3p0artifactId>
            <version>${c3p0.version}version>
        dependency>
        
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>${junit.version}version>
        dependency>
    dependencies>

project>

拷贝文件

将入门程序中的User、UserDao、sqlMapConfig.xml、UserDao.xml拷贝到项目中

mybatis入门_第8张图片

自定义框架代码实现

解析配置文件

编写Mapper类

说明:Mapper类用于封装UserDao.xml文件内容。

分析UserDao.xml文件

mybatis入门_第9张图片

详细代码
package config;

/**
 * 封装接口配置文件内容
 */
public class Mapper {

    private String namespace;// 名称空间
    private String id;// select标签id属性
    private String resultType;// select标签resultType属性
    private String queryString;// sql语句

    public String getNamespace() {
        return namespace;
    }

    public void setNamespace(String namespace) {
        this.namespace = namespace;
    }

    public String getId() {
        return id;
    }

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

    public String getResultType() {
        return resultType;
    }

    public void setResultType(String resultType) {
        this.resultType = resultType;
    }

    public String getQueryString() {
        return queryString;
    }

    public void setQueryString(String queryString) {
        this.queryString = queryString;
    }
}

编写Configuration类

说明:Configuration类用于封装sqlMapConfig.xml配置内容。

分析sqlMapConfig.xml文件

mybatis入门_第10张图片

设计Configuration类

mybatis入门_第11张图片

详细代码
package config;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.beans.PropertyVetoException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 封装主配置文件sqlMapConfig.xml内容
 */
public class Configuration {

    // 连接数据库的四个基本要素
    private String driver;
    private String url;
    private String username;
    private String password;

    // 数据源对象
    private ComboPooledDataSource dataSource;

    // 接口映射文件的配置(Mapper)
    private Map<String, Mapper> mappers;

    /**
     * 思考:
     * 1.解析主配置文件内容
     * 2.创建数据源对象
     */
    public Configuration() {

        // 1.解析主配置文件
        loadSqlMapConfig();

        // 2.创建数据源对象
        createDataSource();

    }

    /**
     * 解析主配置文件内容
     */
    private void loadSqlMapConfig() {

        try {
            // 1.加载主配置文件
            InputStream inputStream = this.getClass().getClassLoader()
                    .getResourceAsStream("sqlMapConfig.xml");

            // 2.通过dom4j解析配置文件
            SAXReader reader = new SAXReader();
            Document document = reader.read(inputStream);
            Element rootElement = document.getRootElement();

            // 3.查找到property标签
            // 
            List<Element> list = rootElement.selectNodes("//property");
            for (Element e : list) {
                // 获取属性值
                String name = e.attributeValue("name");
                String value = e.attributeValue("value");

                if ("driver".equals(name)) {
                    driver = value;
                }
                if ("url".equals(name)) {
                    url = value;
                }
                if ("username".equals(name)) {
                    username = value;
                }
                if ("password".equals(name)) {
                    password = value;
                }

            }

            // 4.查找mapper标签
            //  
            List<Element> mapperList = rootElement.selectNodes("//mapper");
            for (Element e : mapperList) {
                String resource = e.attributeValue("resource");

                // 解析接口映射文件(UserDao.xml)
                loadMapper(resource);
            }


        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建数据源对象
     */
    private void createDataSource() {
        dataSource = new ComboPooledDataSource();
        // 设置连接数据库的四个基本要素
        try {
            dataSource.setDriverClass(driver);
            dataSource.setJdbcUrl(url);
            dataSource.setUser(username);
            dataSource.setPassword(password);
        } catch (PropertyVetoException e) {
            e.printStackTrace();
        }
    }

    /**
     * 解析接口配置文件
     */
    private void loadMapper(String filePath) {

        try {
            // 1加载接口映射文件
            InputStream inputStream = this.getClass().getClassLoader()
                    .getResourceAsStream(filePath);

            // 2.通过dom4j解析接口配置文件
            SAXReader reader = new SAXReader();
            Document document = reader.read(inputStream);
            Element rootElement = document.getRootElement();

            // 3.获取较名称空间
            String namespace = rootElement.attributeValue("namespace");

            // 4.获取根元素的所有子元素
            List<Element> elements = rootElement.elements();
            for (Element e : elements) {
                /**
                 *  
                 */

                String id = e.attributeValue("id");
                String resultType = e.attributeValue("resultType");

                String queryString = e.getText();

                // 封装Mapper对象
                putMappers(namespace, id, resultType, queryString);

            }


        } catch (DocumentException e) {
            e.printStackTrace();
        }

    }

    /**
     * 封装Mapper对象
     */
    private void putMappers(String namespace, String id, String resultType, String queryString) {

        // 如果mappers为空,就创建
        if (mappers == null) {
            mappers = new HashMap<String, Mapper>();
        }

        // 创建Mapper对象
        Mapper mapper = new Mapper();
        mapper.setId(id);
        mapper.setQueryString(queryString);
        mapper.setResultType(resultType);
        mapper.setNamespace(namespace);

        // hashmap 的Key
        String key = namespace + "." + id;

        mappers.put(key, mapper);

    }


    /**
     * =======================getter/setter==================
     */
    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    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 ComboPooledDataSource getDataSource() {
        return dataSource;
    }

    public void setDataSource(ComboPooledDataSource dataSource) {
        this.dataSource = dataSource;
    }

    public Map<String, Mapper> getMappers() {
        return mappers;
    }

    public void setMappers(Map<String, Mapper> mappers) {
        this.mappers = mappers;
    }
}

测试

package test;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import config.Configuration;
import config.Mapper;
import core.SqlSession;
import core.SqlSessionFactory;
import dao.UserDao;
import org.junit.Test;
import po.User;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 自定义框架测试类
 */
public class FrameWorkTest {

    /**
     * 1.测试解析配置文件
     */
    @Test
    public void configurationTest() {
        Configuration configuration = new Configuration();

        // 测试接口配置文件解析
        Map<String, Mapper> mappers = configuration.getMappers();
        Set<String> keys = mappers.keySet();
        Iterator<String> iter = keys.iterator();
        while (iter.hasNext()) {
            Mapper mapper = mappers.get(iter.next());
            System.out.println("mapper:" + mapper);
        }

        // 测试数据源对象
        ComboPooledDataSource dataSource = configuration.getDataSource();
        System.out.println("数据源:" + dataSource);
    }
 }

mybatis入门_第12张图片

编写框架核心组件

编写SqlSession类

说明:SqlSession类中,提供获取持久层接口代理对象方法。

package core;

import java.lang.reflect.Proxy;

/**
 * 核心组件之SqlSession,提供一个方法,这个方法返回dao接口的代理对象
 */
public class SqlSession {

    /**
     * 这里用到的技术:
     *      1.泛型技术
     *      2.动态代理技术
     *  涉及到的类:Proxy
     *  涉及到的方法:newProxyInstance()
     *  参数:
     *      Classlaoder:类加载器,不需要关心
     *      interfaces:接口列表
     *      InvocationHandler:如何增强功能
     */
    public <T> T getMapper(Class<T> type){

        // 创建接口的代理对象
        T proxy =(T) Proxy.newProxyInstance(
                this.getClass().getClassLoader(),
                new Class[]{type},
                new MapperProxyFactory()
        );

        return proxy;
    }
}

编写SqlSessionFactory类

package core;

/**
 * 工厂类,创建SqlSession对象
 */
public class SqlSessionFactory {

    /**
     *创建SqlSession
     */
    public static SqlSession openSqlSession(){
        return new SqlSession();
    }

}

编写MapperProxyFactory类

说明:在编写SqlSession类的getMapper方法中,需要返回持久层接口的代理对象,目前还是返回null。将在MapperProxyFactory类中,通过动态代理方式创建代理对象。

package core;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import config.Configuration;
import config.Mapper;
import util.Executor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

/**
 * 实现增强功能的类,它需要实现接口InvocationHandler
 */
public class MapperProxyFactory implements InvocationHandler{

    /**
     *反射调用的方法:invoke
     * 参数列表:
     *      proxy:代理对象的引用,不需要关心
     *      method:当前执行的方法对象
     *      args:当前执行的方法的参数
     *
     *  思考:该方法中需要做什么事情?
     *  1.解析配置文件内容,获取到相关性
     *  2.根据配置文件内容,得到执行的sql语句
     *  3.根据配置文件内容,得到数据源对象
     *  4.执行数据库操作,返回数据库执行结果
     *
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        // 1.获取到当前执行的方法名称
        // findAllUsers
        String methodName = method.getName();

        // 2.获取到接口的全路径
        // dao.UserDao
        String className = method.getDeclaringClass().getName();

        // 3.解析配置文件内容
        Configuration configuration = new Configuration();
        // 4.根据配置文件内容,得到执行的sql语句
        Map<String, Mapper> mappers = configuration.getMappers();
        Mapper mapper = mappers.get(className + "." + methodName);

        // 5.根据配置文件内容,得到数据源对象
        ComboPooledDataSource dataSource = configuration.getDataSource();

        System.out.println("执行的sql语句:"+mapper.getQueryString());
        System.out.println("数据源对象:"+dataSource);
        
        List<Object> userList = Executor.selectList(mapper, dataSource.getConnection());

        return userList;
    }
}


测试

package test;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import config.Configuration;
import config.Mapper;
import core.SqlSession;
import core.SqlSessionFactory;
import dao.UserDao;
import org.junit.Test;
import po.User;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 自定义框架测试类
 */
public class FrameWorkTest {

    /**
     * 1.测试解析配置文件
     */
    @Test
    public void configurationTest() {
        Configuration configuration = new Configuration();

        // 测试接口配置文件解析
        Map<String, Mapper> mappers = configuration.getMappers();
        Set<String> keys = mappers.keySet();
        Iterator<String> iter = keys.iterator();
        while (iter.hasNext()) {
            Mapper mapper = mappers.get(iter.next());
            System.out.println("mapper:" + mapper);
        }

        // 测试数据源对象
        ComboPooledDataSource dataSource = configuration.getDataSource();
        System.out.println("数据源:" + dataSource);
    }

    /**
     * 测试框架的核心组件
     */
    @Test
    public void coreFrameworkTest(){
        // 1.创建sqlSession
        SqlSession sqlSession = SqlSessionFactory.openSqlSession();

        // 2.获取接口的代理对象
        UserDao userDao = sqlSession.getMapper(UserDao.class);

        // 3.调用方法执行
        List<User> list = userDao.findAllUsers();
        for(User u:list){
            System.out.println(u);
        }
    }
}


mybatis入门_第13张图片

编写执行数据库操作工具类

分析

到此我们已经准备好了要执行的sql语句,数据库连接对象。只需要把静态的用户数据,替换成数据库中查询的用户数据即可。

mybatis入门_第14张图片

Executor执行器类代码

package util;

import config.Mapper;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;

/**
 * 执行数据库操作工具类
 */
public class Executor {

    /**
     * 执行数据库操作,返回执行结果
     * @param mapper:sql语句映射对象
     * @param connection:数据库连接对象
     */
    public static <T> List<T> selectList(Mapper mapper, Connection connection){

        //  1.定义statement语句对象和执行结果集ResultSet对象
        PreparedStatement psmt = null;
        ResultSet rs = null;

        // 2.返回结果集
        List<T> list = new ArrayList<T>();

        try{
            // 3.获取查询的sql语句
            String sql = mapper.getQueryString();

            // 4.获取返回值类型
            String resultType = mapper.getResultType();
            // 转换成字节码
            Class<?> clazz = Class.forName(resultType);

            // 5.创建statement语句对象
            psmt = connection.prepareStatement(sql);

            // 6.执行查询
            rs =  psmt.executeQuery();

            // 7.处理结果集
            handleResult(list,clazz,rs);

        }catch(Exception e){
            e.printStackTrace();
        }finally {
            // 8. 释放资源
            close(connection,psmt,rs);
        }

        return  list;
    }

    /**
     * 处理结果集
     * @param list
     * @param clazz
     * @param rs
     */
    private static void handleResult(List list,Class<?> clazz,ResultSet rs){

        try {
            // 1.获取元数据。元数据中包含有查询列的数量和列名称
            ResultSetMetaData metaData = rs.getMetaData();
            int columnCount = metaData.getColumnCount();// 列的数量

            // 列的名称数组(细节:列的名称,约定与对象中的属性名称一致)
            String[] columns = new String[columnCount];
            for(int i=1;i<=columnCount;i++){
                columns[i-1] = metaData.getColumnName(i);
            }
            //System.out.println(Arrays.asList(columns));

            // 2.循环处理结果集
            while(rs.next()){
                // 2.1.实例化对象
                Object obj = clazz.newInstance();

                // 2.2.取出字段值,赋值给obj对象属性
                for(int i=0;i<columns.length;i++){
                    Object cv = rs.getObject(columns[i]);

                    // 通过反射技术给对象属性赋值
                    PropertyDescriptor pd = new PropertyDescriptor(columns[i],clazz);

                    // 获取set方法
                    Method writeMethod = pd.getWriteMethod();

                    // 赋值
                    writeMethod.invoke(obj,cv);
                }

                list.add(obj);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 释放资源
     * @param con
     * @param psmt
     * @param rs
     */
    public static void close(Connection con, PreparedStatement psmt, ResultSet rs){
        try{
            if(rs != null) rs.close();
            if(psmt != null) psmt.close();
            if(con != null) con.close();
        }catch(Exception e){
            e.printStackTrace();
        }

    }
}

测试

mybatis入门_第15张图片

你可能感兴趣的:(Java数据库框架)