Mybati和连接池

mybatis内置连接池创建时间

Mybatis连接池在SqlSessionFactory创建时创建,查看build方法源码

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    
    
        SqlSessionFactory var5;
        try {
    
    
        //解析xml文件
            XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
            var5 = this.build(parser.parse());
        } catch (Exception var14) {
    
    
            throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
        } finally {
    
    
            ErrorContext.instance().reset();

            try {
    
    
                inputStream.close();
            } catch (IOException var13) {
    
    
            }

        }

        return var5;
    }

var5 = this.build(parser.parse());查看parse函数源码

public Configuration parse() {
    
    
        if (this.parsed) {
    
    
            throw new BuilderException("Each XMLConfigBuilder can only be used once.");
        } else {
    
    
            this.parsed = true;
//解析configuration            
            this.parseConfiguration(this.parser.evalNode("/configuration"));
            return this.configuration;
        }
    }

this.parseConfiguration(this.parser.evalNode("/configuration"));查看parseConfiguration源码

//解析各个标签
private void parseConfiguration(XNode root) {
    
    
        try {
    
    
            this.propertiesElement(root.evalNode("properties"));
            Properties settings = this.settingsAsProperties(root.evalNode("settings"));
            this.loadCustomVfs(settings);
            this.typeAliasesElement(root.evalNode("typeAliases"));
            this.pluginElement(root.evalNode("plugins"));
            this.objectFactoryElement(root.evalNode("objectFactory"));
            this.objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
            this.reflectorFactoryElement(root.evalNode("reflectorFactory"));
            this.settingsElement(settings);
            this.environmentsElement(root.evalNode("environments"));
            this.databaseIdProviderElement(root.evalNode("databaseIdProvider"));
            this.typeHandlerElement(root.evalNode("typeHandlers"));
            this.mapperElement(root.evalNode("mappers"));
        } catch (Exception var3) {
    
    
            throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + var3, var3);
        }
    }

this.environmentsElement(root.evalNode(“environments”));查看environmentsElement源码

private void environmentsElement(XNode context) throws Exception {
    
    
        if (context != null) {
    
    
            if (this.environment == null) {
    
    
                this.environment = context.getStringAttribute("default");
            }

            Iterator var2 = context.getChildren().iterator();

            while(var2.hasNext()) {
    
    
                XNode child = (XNode)var2.next();
                String id = child.getStringAttribute("id");
                if (this.isSpecifiedEnvironment(id)) {
    
    
                    TransactionFactory txFactory = this.transactionManagerElement(child.evalNode("transactionManager"));
                    DataSourceFactory dsFactory = this.dataSourceElement(child.evalNode("dataSource"));
                    //连接池创建完毕了,datasource是连接池统一的接口标准
                    DataSource dataSource = dsFactory.getDataSource();
                    Builder environmentBuilder = (new Builder(id)).transactionFactory(txFactory).dataSource(dataSource);
                    this.configuration.setEnvironment(environmentBuilder.build());
                }
            }
        }

    }

这里查看DataSource源码已经跳转到javax.sql包下了

取出连接的时机

在getMapper的时候是不会从数据库连接池获取数据库连接的,在具体操作数据库调用mapper接口方法的时候才会从连接池拿连接。
断点调试
在这里插入图片描述
活动连接数为0
在这里插入图片描述
执行数据库查询语句后活动连接数为1
在这里插入图片描述
sqlSession关闭后归还连接,活动连接数再次为0
在这里插入图片描述

JNDI

  • 什么是JNDI

    JNDI:java naming directory interface(java命名目录接口,它是一种服务发布技术),数据源可以以服务的形式发布出去,那么哪个应用想用,就类似于客户端调用远程服务一样去调用即可(例如天气API)

  • 为什么必须是web应用

    往往只有tomcat/weblogic服务器中间件(客户端和服务器之间)才支持JNDI技术

事务控制

SqlSession.open函数控制事务,查看源码,参数为true则自动提交事务

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.apache.ibatis.session;

import java.sql.Connection;

public interface SqlSessionFactory {
    
    
    SqlSession openSession();

    SqlSession openSession(boolean var1);

    SqlSession openSession(Connection var1);

    SqlSession openSession(TransactionIsolationLevel var1);

    SqlSession openSession(ExecutorType var1);

    SqlSession openSession(ExecutorType var1, boolean var2);

    SqlSession openSession(ExecutorType var1, TransactionIsolationLevel var2);

    SqlSession openSession(ExecutorType var1, Connection var2);

    Configuration getConfiguration();
}

ctrl+H查看实现类

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.apache.ibatis.session.defaults;

import java.sql.Connection;
import java.sql.SQLException;
import org.apache.ibatis.exceptions.ExceptionFactory;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.TransactionIsolationLevel;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.managed.ManagedTransactionFactory;

public class DefaultSqlSessionFactory implements SqlSessionFactory {
    
    
    private final Configuration configuration;

    public DefaultSqlSessionFactory(Configuration configuration) {
    
    
        this.configuration = configuration;
    }

//无参构造方法默认false,手动提交事务
    public SqlSession openSession() {
    
    
        return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, false);
    }

//控制事务
    public SqlSession openSession(boolean autoCommit) {
    
    
        return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, autoCommit);
    }

    public SqlSession openSession(ExecutorType execType) {
    
    
        return this.openSessionFromDataSource(execType, (TransactionIsolationLevel)null, false);
    }

    public SqlSession openSession(TransactionIsolationLevel level) {
    
    
        return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), level, false);
    }

    public SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level) {
    
    
        return this.openSessionFromDataSource(execType, level, false);
    }

    public SqlSession openSession(ExecutorType execType, boolean autoCommit) {
    
    
        return this.openSessionFromDataSource(execType, (TransactionIsolationLevel)null, autoCommit);
    }

    public SqlSession openSession(Connection connection) {
    
    
        return this.openSessionFromConnection(this.configuration.getDefaultExecutorType(), connection);
    }

    public SqlSession openSession(ExecutorType execType, Connection connection) {
    
    
        return this.openSessionFromConnection(execType, connection);
    }

    public Configuration getConfiguration() {
    
    
        return this.configuration;
    }

    private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    
    
        Transaction tx = null;

        DefaultSqlSession var8;
        try {
    
    
            Environment environment = this.configuration.getEnvironment();
            TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
            tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
            Executor executor = this.configuration.newExecutor(tx, execType);
            var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);
        } catch (Exception var12) {
    
    
            this.closeTransaction(tx);
            throw ExceptionFactory.wrapException("Error opening session.  Cause: " + var12, var12);
        } finally {
    
    
            ErrorContext.instance().reset();
        }

        return var8;
    }

    private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
    
    
        DefaultSqlSession var8;
        try {
    
    
            boolean autoCommit;
            try {
    
    
                autoCommit = connection.getAutoCommit();
            } catch (SQLException var13) {
    
    
                autoCommit = true;
            }

            Environment environment = this.configuration.getEnvironment();
            TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
            Transaction tx = transactionFactory.newTransaction(connection);
            Executor executor = this.configuration.newExecutor(tx, execType);
            var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);
        } catch (Exception var14) {
    
    
            throw ExceptionFactory.wrapException("Error opening session.  Cause: " + var14, var14);
        } finally {
    
    
            ErrorContext.instance().reset();
        }

        return var8;
    }

    private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) {
    
    
        return (TransactionFactory)(environment != null && environment.getTransactionFactory() != null ? environment.getTransactionFactory() : new ManagedTransactionFactory());
    }

    private void closeTransaction(Transaction tx) {
    
    
        if (tx != null) {
    
    
            try {
    
    
                tx.close();
            } catch (SQLException var3) {
    
    
            }
        }

    }
}

Mybatis动态sql实现

java中自行实现

如果不适用Mybatis框架则是在dao层实现,为了满足多个查询条件一般的java动态sql语句如下

List paras = new ArrayList();
String sql = "select * from user where and";

if(username != null && username != ""){
    
    
sql += " where username = ?";
list.add(username);//查询的参数用list存储 
}

java中dao实现批量删除

String[] arr = {
    
    "1","3","5","7"};//实际上应该是从前端读取的数据
String sql = "delete from user where id in (";
for(int i = 0; i < arr.length; i++){
    
    
	if(i != arr.length - 1){
    
    
		sql += arr[i] + ",";
	} else {
    
    
		sql += arr[i] + ")";
	}
}

Mybatis中实现

Mybati配置文件中的动态标签(见UserMapper.xml)

  • where标签:处理SQL语句,自动添加where关键字,并去掉紧跟他后面的一个and或者or

  • if标签,test属性,判断表达式真假

  • foreach迭代标签,可以实现批量删除

多条件查询

SQL文件UserMapper.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和接口名相同-->
<mapper namespace="com.ahu.mapper.UserMapper">
        <select id="queryUser" resultType="user">
                select * from user
        </select>

        <!--
        多条件查询
        标签where拼接查询的条件(自动检查,不需要加1=1,Mys)
        根据pojo中的对象决定查询的条件(username和sex)

        标签if对pojo的属性进行判断
        属性test判断属性是否为空


        -->
        <!--
        直接用属性名就可以如username,如果使用user.username则user是内置的属性对象,空串用''表示
        SQL语句会自动加where,也会自动删除第一个and
        -->
        <select id="queryByWhere" resultType="user" parameterType="user">
                select * from user
                <where>
                        <if test="username != null and username != ''">
                        and username like #{username}
                        </if>

                        <if test="sex != null and sex != ''">
                        and sex = #{sex}
                        </if>
                </where>
        </select>
</mapper>

查询的代码

package com.ahu.test;

import com.ahu.mapper.UserMapper;
import com.ahu.pojo.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;
import org.junit.Before;
import org.junit.Test;

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

public class MainTest {
    
    
    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void before() throws IOException {
    
    
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        sqlSessionFactory = sqlSessionFactoryBuilder.build(is);//工厂构建的时候创建连接池
    }

    /**
     * 查询所有用户
     */
    @Test
    public void testQuery(){
    
    
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = userMapper.queryUser();
        for (User user : users) {
    
    
            System.out.println(user);
        }
        sqlSession.close();
    }

    /**
     * 模糊查询
     */
    @Test
    public void testQueryByWhere(){
    
    
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User factors = new User();
//        factors.setUsername("%孙%");
        factors.setSex("F");
        List<User> users = userMapper.queryByWhere(factors);
        if(users != null && users.size() > 0){
    
    
            for (User user : users) {
    
    
                System.out.println(user);
            }
        }
        sqlSession.close();
    }
}

批量删除
批量删除UserMapper.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和接口名相同-->
<mapper namespace="com.ahu.mapper.UserMapper">
        <select id="queryUser" resultType="user">
                select <include refid="userColumn"/> from user
        </select>

        <!--
        多条件查询
        标签where拼接查询的条件(自动检查,不需要加1=1,Mys)
        根据pojo中的对象决定查询的条件(username和sex)

        标签if对pojo的属性进行判断
        属性test判断属性是否为空


        -->
        <!--
        直接用属性名就可以如username,如果使用user.username则user是内置的属性对象,空串用''表示
        SQL语句会自动加where,也会自动删除第一个and
        -->
        <select id="queryByWhere" resultType="user" parameterType="user">
                select * from user
                <where>
                        <if test="username != null and username != ''">
                        and username like #{username}
                        </if>

                        <if test="sex != null and sex != ''">
                        and sex = #{sex}
                        </if>
                </where>
        </select>

        <!--
        批量删除
        参数是集合
        使用迭代标签foreach,标签属性parameterType,参数的数据类型,写的是集合的泛型
        迭代标签 foreach  遍历集合,固定的集合list

        属性: collection 遍历容器集合
        属性: open SQL开始的符号
        属性: close SQL结束符号
        属性: separator SQL语句参数分隔符
        属性  item 遍历的容器的元素
        -->
        <delete id="deleteUserByList" parameterType="list">
            delete from user where id in
            <foreach collection="list" open="(" close=")" separator="," item="id">
            #{id}
--             取出集合元素
            </foreach>
        </delete>

        <!--
        传入数组
        collection属性填array
        -->
        <delete id="deleteUserByArray" parameterType="int[]">
            delete from user where id in
            <foreach collection="array" open="(" close=")" separator="," item="id">
                #{id}
            </foreach>
        </delete>

        <!--
        批量删除,传递pojo对象
        -->
        <delete id="deleteUserByUserVO" parameterType="UserVO">
            delete from user where id in
            <foreach collection="idsList" open="(" close=")" separator="," item="id">
                #{id}
            </foreach>
        </delete>

        <sql id="userColumn">
        id,username,sex,birthday,address
        </sql>
</mapper>

UserMapper.java

package com.ahu.mapper;

import com.ahu.pojo.User;
import com.ahu.pojo.UserVO;

import java.util.List;

public interface UserMapper {
    
    
    /**
     * 查询所有用户的信息
     * @return
     */
    List<User> queryUser();

    /**
     * 模糊查询
     * @param userToSearch
     * @return
     */
    List<User> queryByWhere(User userToSearch);

    /**
     * 批量删除
     * @param idsList 传入集合
     * @return
     */
    int deleteUserByList(List<Integer> idsList);

    /**
     * 批量删除
     * @param ids 传入数组
     * @return
     */
    int deleteUserByArray(int[] ids);

    /**
     * 批量删除,传入pojo对象
     * @param userVO
     * @return
     */
    int deleteUserByUserVO(UserVO userVO);
}

sql标签

Mybatis提供了sql标签可以代替列名

<sql id="userColumn">
        id,username,sex,birthday,address
        </sql>

<select id="queryUser" resultType="user">
                select <include refid="userColumn"/> from user
        </select>

猜你喜欢

转载自blog.csdn.net/qq_41904699/article/details/109021274
今日推荐