Mybatis之编程式开发

文章目录

  • 2.MyBatis 编程式开发
    • 2.1.开发步骤
      • 2.1.1.mybatis和MySQL jar包依赖
      • 2.1.2、全局配置文件mybatis-config.xml
      • 2.1.3.映射器 Mapper.xml
      • 2.1.4.Mapper接口
    • 2.2.MyBatis核心对象及其作用域
    • 2.3.MyBatis配置文件
      • 2.3.1.全局配置文件-mybatis-config.xml
        • 2.3.1.1.configuration节点
        • 2.3.1.2.属性(properties)
        • 2.3.1.3.设置(settings)
        • 2.3.1.4.类型别名(typeAliases)
        • 2.3.1.5.类型处理器(typeHandlers)
          • 2.3.1.5.1 自己配置一个typeHandler
        • 2.3.1.6.对象工厂(objectFactory)
      • 2.3.2.核心配置文件-Mapper.xml
        • 2.3.2.1.动态SQL
        • 2.3.2.2.批量操作[插入 删除 更新]

2.MyBatis 编程式开发

2.1.开发步骤

2.1.1.mybatis和MySQL jar包依赖

<dependency>
   <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.1</version>
</dependency>

2.1.2、全局配置文件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>

    <properties resource="db.properties"></properties>
    <settings>
        <!-- 打印查询语句 -->
        <setting name="logImpl" value="STDOUT_LOGGING" />

        <!-- 控制全局缓存(二级缓存)-->
        <setting name="cacheEnabled" value="true"/>

        <!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。默认 false  -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 当开启时,任何方法的调用都会加载该对象的所有属性。默认 false,可通过select标签的 fetchType来覆盖-->
        <setting name="aggressiveLazyLoading" value="false"/>
        <!--  Mybatis 创建具有延迟加载能力的对象所用到的代理工具,默认JAVASSIST -->
        <!--<setting name="proxyFactory" value="CGLIB" />-->
        <!-- STATEMENT级别的缓存,使一级缓存,只针对当前执行的这一statement有效 -->
        <!--
                <setting name="localCacheScope" value="STATEMENT"/>
        -->
        <setting name="localCacheScope" value="SESSION"/>
    </settings>

    <typeAliases>
        <typeAlias alias="blog" type="com.ggaoxinfu.domain.Blog" />
    </typeAliases>
    
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/><!-- 单独使用时配置成MANAGED没有事务 -->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="BlogMapper.xml"/>
        <mapper resource="BlogMapperExt.xml"/>
    </mappers>

</configuration>

2.1.3.映射器 Mapper.xml

SQL的xml文件

2.1.4.Mapper接口

主要是每一张表的Mapper接口

2.2.MyBatis核心对象及其作用域

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

SqlSession session = sqlSessionFactory.openSession();
try {
   Blog blog = (Blog) session.selectOne("com.gaoxinfu.mapper.BlogMapper.selectBlogById", 1);
   System.out.println(blog);
} finally {
   session.close();
}

Mybatis之编程式开发_第1张图片

Mapper(实际上是一个代理对象)是从 SqlSession 中获取的。
BlogMapper mapper = session.getMapper(BlogMapper.class)

2.3.MyBatis配置文件

参考官网
http://www.mybatis.org/mybatis-3/zh/getting-started.html

2.3.1.全局配置文件-mybatis-config.xml

2.3.1.1.configuration节点

源码代码:处理Xml文件中的一级标签如properties setttings等等标签

org.apache.ibatis.session.Configuration

配置文件
Mybatis之编程式开发_第2张图片

2.3.1.2.属性(properties)

http://www.mybatis.org/mybatis-3/zh/configuration.html#properties

2.3.1.3.设置(settings)

2.3.1.4.类型别名(typeAliases)

org.apache.ibatis.type.TypeAliasRegistry
<typeAliases>
  <typeAlias alias="blog" type="com.gapxinfu.domain.Blog" />
</typeAliases>

Mybatis之编程式开发_第3张图片

2.3.1.5.类型处理器(typeHandlers)

1.解决的问题主要是Java 类型和数据库的 JDBC 类型的对应
2.对应的默认类处理 org.apache.ibatis.type.TypeHandlerRegistry

Mybatis之编程式开发_第4张图片

如上MyBatis 已经内置了很多 TypeHandler(在 type 包下)[:StringTypeHandler,ClobTypeHandler等你等],
它们全部注册在 TypeHandlerRegistry中,他们都继承了抽象类 BaseTypeHandler,
泛型就是要处理的Java数据类型呢

StringTypeHandler源码举例

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

package org.apache.ibatis.type;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class StringTypeHandler extends BaseTypeHandler<String> {
    public StringTypeHandler() {
    }
	//setNonNullParameter: 设置非空参数
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, parameter);
    }
	//获取空结果集(根据列名), 一般都是调用这个
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return rs.getString(columnName);
    }
	//获取空结果集(根据下标值)
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return rs.getString(columnIndex);
    }
	//获取空结果集 存储过程用的
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return cs.getString(columnIndex);
    }
}
2.3.1.5.1 自己配置一个typeHandler

比如我们想要在获取或者设置 String 类型的时候做一些特殊处理,
我们可以写一个String 类型的 TypeHandler

package com.gaoxinfu.type;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class MyTypeHandler extends BaseTypeHandler<String> {
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)
            throws SQLException {
        // 设置 String 类型的参数的时候调用,Java类型到JDBC类型
        // 注意只有在字段上添加typeHandler属性才会生效
        // insertBlog name字段
        System.out.println("---------------setNonNullParameter1:"+parameter);
        ps.setString(i, parameter);
    }

    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        // 根据列名获取 String 类型的参数的时候调用,JDBC类型到java类型
        // 注意只有在字段上添加typeHandler属性才会生效
        System.out.println("---------------getNullableResult1:"+columnName);
        return rs.getString(columnName);
    }

    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        // 根据下标获取 String 类型的参数的时候调用
        System.out.println("---------------getNullableResult2:"+columnIndex);
        return rs.getString(columnIndex);
    }

    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        System.out.println("---------------getNullableResult3:");
        return cs.getString(columnIndex);
    }
}

配置如下

<typeHandlers>
	<typeHandler handler="com.gupaoedu.type.MyTypeHandler"></typeHandler>
</typeHandlers>

查询应用:JDBC到JAVA类型
Mybatis之编程式开发_第5张图片

插入应用:JAVA类型到JDBC类型
Mybatis之编程式开发_第6张图片

2.3.1.6.对象工厂(objectFactory)

1.主要是对数据库查询结果每个对象的处理
1.默认的对象工厂:org.apache.ibatis.reflection.factory.DefaultObjectFactory

Mybatis之编程式开发_第7张图片
工厂类的接口:ObjectFactory

package org.apache.ibatis.reflection.factory;

import java.util.List;
import java.util.Properties;

/**
 * MyBatis uses an ObjectFactory to create all needed new Objects.
 *
 * @author Clinton Begin
 */
public interface ObjectFactory {

  /**
   * Sets configuration properties.
   * @param properties configuration properties
   */
   //设置参数时调用
  void setProperties(Properties properties);

  /**
   * Creates a new object with default constructor.
   * @param type Object type
   * @return
   */
   //创建对象(调用无参构造函数)
  <T> T create(Class<T> type);

  /**
   * Creates a new object with the specified constructor and params.
   * @param type Object type
   * @param constructorArgTypes Constructor argument types
   * @param constructorArgs Constructor argument values
   * @return
   */
   //创建对象(调用带参数构造函数)
  <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs);

  /**
   * Returns true if this object can have a set of other objects.
   * It's main purpose is to support non-java.util.Collection objects like Scala collections.
   *
   * @param type Object type
   * @return whether it is a collection or not
   * @since 3.1.0
   */
   //判断是否集合
  <T> boolean isCollection(Class<T> type);

}

应用举例

public class MyObjectFactory extends DefaultObjectFactory {
    @Override
    public Object create(Class type) {
        System.out.println("创建对象方法:" + type);
        if (type.equals(Blog.class)) {
            Blog blog = (Blog) super.create(type);
            blog.setName("object factory");
            blog.setBid(1111*100);
            blog.setAuthorId(2222);
            return blog;
        }
        Object result = super.create(type);
        return result;
    }
}

<!-- mybatis-config.xml -->
<objectFactory type="org.mybatis.gaoxinfu.MyObjectFactory ">
  <property name="someProperty" value="100"/>
</objectFactory>

2.3.2.核心配置文件-Mapper.xml

2.3.2.1.动态SQL

http://www.mybatis.org/mybatis-3/zh/dynamic-sql.html

<if>
<choose> (<when>,<otherwise>)
<trim> (<where>,<set>)
<foreach>

2.3.2.2.批量操作[插入 删除 更新]

mybatis操作数据库,默认最大4M数据包

1.把所有的循环的,弄成一次插入或者删除,可以减少数据库的交互次数;
2.但是数据量太大,不太好,因为数据库操作,数据包最大4M,ping接的太大,可能会报错;

样例

insert into tbl_emp (emp_id, emp_name, gender,email, d_id) values ( ?,?,?,?,? ) , ( ?,?,?,?,? ) , ( ?,?,?,?,? ) , ( ?,?,?,?,? ) ,
( ?,?,?,?,? ) , ( ?,?,?,?,? ) , ( ?,?,?,?,? ) , ( ?,?,?,?,? ) , ( ?,?,?,?,? ) , ( ?,?,?,?,? );

delete from tbl_emp where emp_id in (?,?,?,?);
    @Test
    public void testJdbcBatch() throws IOException {
        Connection conn = null;
        //支持预编译和缓存  PreparedStatement.addBatch()添加批次,批量执行  PreparedStatement.executeBatch();
        PreparedStatement ps = null;

        try {
            // 注册 JDBC 驱动
            Class.forName("com.mysql.jdbc.Driver");

            // 打开连接
            conn = DriverManager.getConnection(
                    "jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&rewriteBatchedStatements=true",
                    "root",
                    "root");
            ps = conn.prepareStatement(
                    "INSERT into blog values (?, ?, ?)");

            for (int i = 1000; i < 101000; i++) {
                Blog blog = new Blog();
                ps.setInt(1, i);
                ps.setString(2, String.valueOf(i));
                ps.setInt(3, 1001);
                ps.addBatch();
            }

            ps.executeBatch();
            // conn.commit();
            ps.close();
            conn.close();
        } catch (SQLException se) {
            se.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (ps != null) ps.close();
            } catch (SQLException se2) {
            }
            try {
                if (conn != null) conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
        }
    }
Batch Executor
底层和上面的PreparedStatement批量执行原理一样

在这里插入图片描述
SIMPLE 对应Statement
REUSE 对应PreparedStatement

你可能感兴趣的:(mybatis)