mybatis 快速入门及配置文件详解

1、mybatis

前身iBatis,优秀的持久层框架,支持定制化SQL、存储过程以及高级映射。本质是半自动的ORM框架,除和POJO的映射外,还需要自己编写sql。

2、ORM

对象关系映射Object Relational Mapping,ORM模型就是数据库的表和简单的Java对象(POJO)的映射模型。

3、快速入门(maven 工程)

一、pom.xml 中加入mybatis依赖

二、新建mybatis 核心配置文件:mybatis-config.xml

三、新建mapper 接口和映射mapper.xml 文件。

3.1 代码

包结构

3.1.1 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>

    <groupId>mybatis-first</groupId>
    <artifactId>com.aeolusway.mybatis</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <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.18</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

3.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="mapUnderscoreToCamelCase" value="true" />

    </settings>
    
    <environments default="development">
        <environment id="development">
            <transactionManager type="jdbc"></transactionManager>
            <dataSource type="UNPOOLED">
                <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="sqlmapper/UserMapper.xml" />
    </mappers>

</configuration>

3.1.3 mapper 接口:UserMapper

package com.aeolusway.mapper;

import com.aeolusway.entity.User;


public interface UserMapper {
    User selectByPrimaryKey(Integer id);
}

映射xml文件: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="com.aeolusway.mapper.UserMapper">
    <select id="selectByPrimaryKey" resultType="com.aeolusway.entity.User"	parameterType="java.lang.Integer">
        select
        id,
        user_name ,
        real_name ,
        sex,
        mobile,
        email,
        note,
        position_id positionId
        from user
        where id = #{id,jdbcType=INTEGER}
    </select>
</mapper>

3.1.4 其他文件

db.properties:数据库连接信息,也可以配置在mybatis-config.xml 文件中

jdbc_driver=com.mysql.jdbc.Driver
jdbc_url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
jdbc_username=root
jdbc_password=root

对象实体:User

package com.aeolusway.entity;

public class User {
    private Integer id;

    private String userName;

    private String realName;

    private Byte sex;

    private String mobile;

    private String email;

    private String note;

    private Integer positionId;

    public Integer getId() {
        return id;
    }

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

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getRealName() {
        return realName;
    }

    public void setRealName(String realName) {
        this.realName = realName;
    }

    public Byte getSex() {
        return sex;
    }

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

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getEmail() {
        return email;
    }

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

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }

    public Integer getPositionId() {
        return positionId;
    }

    public void setPositionId(Integer positionId) {
        this.positionId = positionId;
    }

    @Override
    public String toString() {
        return "User{" + "id=" + id + ", userName='" + userName + '\'' + ", realName='" + realName + '\'' + ", sex=" + sex + ", mobile='" + mobile + '\'' + ", email='" + email + '\'' + ", note='" + note + '\'' + ", positionId=" + positionId + '}';
    }
}

测试类 MybatisFirst

package com.aeolusway.test;

import com.aeolusway.entity.User;
import com.aeolusway.mapper.UserMapper;
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;


public class MybatisFirst {
    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void init() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    @Test
    public void quickStart(){
        // 2.获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 3.获取对应mapper
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        // 4.执行查询语句并返回结果
        User user = mapper.selectByPrimaryKey(1);
        System.out.println(user.toString());
    }
}

4、入门核心类

mybatis官方中文文档:http://www.mybatis.org/mybatis-3/zh/configuration.html

mybatis的应用都是基于一个SqlSessionFactory 实例为核心的。

4.1 SqlSessionFactoryBuilder

读取xml 配置文件(或预先定制的configuration 实例),使用建造则模式构建出SqlSessionFactory实例,创建SqlSessionFactory实例后,就不需要这个类了,所以最佳作用域:方法级别。

4.2 SqlSessionFactory

用于创建SqlSession,而SqlSession代表的是一次数据库链接,所以SqlSessionFactory 需要在运行期间一直存在,不应重复多次创建(使用单例模式或者静态单例模式保证这一点),最佳作用域:程序整个生命周期。

4.3 SqlSession

代表一次数据库连接,SqlSession 包含了SQL所需要的所有方法,(我们通过mapper接口操作数据库,实际上使用的是sqlSession的方法,其实iBatis就是这样做的。后面分析源码会具体讨论)。SqlSession 不是线程安全的,所以为了保证线程安全,每个线程都应该拥有自己的SqlSsession 实例,不能被共享,所以最佳作用域:方法级别。

4.4 SQL Mapping

由一个mapper 接口和映射文件xml组成,包含了要执行的sql语句和结果集映射规则,映射器接口的实例是从SqlSession 中获取的,所以最佳作用域:方法级别。

5、配置文件详解

5.1 核心配置文件mybatis-config.xml

mybatis官方中文文档:http://www.mybatis.org/mybatis-3/zh/configuration.html

5.1.1 properties

属性配置,可引入外部属性配置文件,也可通过properties的子元素property配置。

<properties resource="db.properties"></properties>
//引入的就是外部属性文件:db.properties,
// 然后通过${***} 获取属性 

5.1.2 settings

配置mybatis的一些全局属性,改变mybatis的运行时行为。

<settings>
    <!-- 在自动隐射时,数据库表字段的命名规则(“——”分隔)改为驼峰命名规则) -->
	<setting name="mapUnderscoreToCamelCase" value="true" />
    <!-- 取消所有的按需加载,一次性把数据全部加载出来 -->
	<setting name="aggressiveLazyLoading" value="false" />
</settings>

其他属性(部分常用属性)如下:(还有很多,可以去官网查看:http://www.mybatis.org/mybatis-3/zh/configuration.html

cacheEnabled全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存。true | falsetrue
lazyLoadingEnabled延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。true | falsefalse
aggressiveLazyLoading当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个属性会按需加载(参考 lazyLoadTriggerMethods)。true | falsefalse (在 3.4.1 及之前的版本默认值为 true)
autoMappingBehavior指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示取消自动映射;PARTIAL 只会自动映射没有定义嵌套结果集映射的结果集。 FULL 会自动映射任意复杂的结果集(无论是否嵌套)。NONE, PARTIAL, FULLPARTIAL
mapUnderscoreToCamelCase是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。true | falseFalse
logPrefix指定 MyBatis 增加到日志名称的前缀。任何字符串未设置

5.1.3 typeAliases

设置别名,方便映射时使用,除开系统定义的别名外,自己也可以定义别名

<typeAliases>
  <typeAlias alias="Author" type="domain.blog.Author"/>
</typeAliases>
// 当这样配置时,Author可以用在任何使用 domain.blog.Author的地方。

5.1.4 typeHandlers

类型处理器,用于jdbcType 和javaType之间的转换,mybatis定义了很多类型处理器。也可以自定义类型处理器来处理mybatis 不支持或非标准的类型转换,具体做法是,实现org.apache.ibatis.type.TypeHandler 接口或者继承org.apache.ibatis.type.BaseTypeHandler类,然后可以选择性的将其映射到一个jdbc类型,然后在核心配置文件中引入自定的类型处理器。

<typeHandlers>
    <!-- 引入自定义的ExampleTypeHandler 类型处理器   -->
  <typeHandler handler="org.mybatis.example.ExampleTypeHandler"/>
</typeHandlers>

5.1.5 ObjectFactory

对象工厂,mybatis 每次创建结果对象的新实例时,都会通过一个对象工厂的实例来完成。mybatis 默认使用DefaultObjectFactory ,DefaultObjectFactory做的仅仅是实例化目标类,如果想要覆盖工厂的默认行为,可以创建自己的对象工厂来实现,绝大部分情况下我们是不需要这样做的。

5.1.6 plugins

引入插件,mybatis允许在语句(已映射的)执行过程中的某一点进行拦截调用。插件开发后面章节会讲到。

5.1.7 environments

配置数据源,每个数据源的配置分为数据库源和事务管理器的配置,可以配置多个数据源,但每个 SqlSessionFactory 实例只能选择一种环境。

<environments default="development">
        <environment id="development">
            <transactionManager type="jdbc"></transactionManager>
            <dataSource type="UNPOOLED">
                <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>

environment 元素是配置一个数据源的开始,属性id是它的唯一标识 

transactionManager:元素配置数据库事务,其中type属性有三种配置方式

   jdbc,采用jdbc的方式管理事务;

   managed,采用容器的方式管理事务,在JNDI数据源中使用;

   自定义,自定义数据库事务管理办法; 

dataSource:元素配置数据源连接信息,type属性是连接数据库的方式配置,有四种配置方式

   UNPOOLED 非连接池方式连接

   POOLED   使用连接池连接

   JNDI  使用JNDI数据源

   自定义数据源 

5.1.8 databaseIdProvider

数据库厂商id 配置,MyBatis根据不同的数据库厂商执行不同的语句,用于一个系统内多厂商数据源支持。

5.1.9 mapper

引入映射器,三种当时配置

 <mappers>   
    <!--
    1、classPath下资源引用:
    直接映射到相应的mapper文件 -->   
    <mapper resource="sqlmapper/UserMapper.xml" />
    <!—-
    2、类注册方式引用:
    通过类扫描mapper文件 -->
    <mapper class="com.aeolusway.mapper.UserMapper" />
    <!—
    3、包名引入引射器名:
    扫描包下所有的mapper文件,
    这种映射mapper.xml 和mapper 接口名称要相同 --> 
    <package name="com.aeolusway.mapper"/> 
</mappers> 

5.2 mapper.xml映射文件

  1. cache:配置二级缓存
  2. cache-ref:引入其他命名空间的二级缓存
  3. resultMap:映射结果集规则,是最复杂最强大的元素。
  4. sql:sql语句块,供其他sql语句引入
  5. select:查
  6. insert:曾
  7. update:改
  8. delete:删

5.2.1 select元素

id它和Mapper的命名空间组合起来是唯一的,提供给MyBatis调用
parameterType将会传入这条语句的参数类的完全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler) 推断出具体传入语句的参数,默认值为未设置(unset)。
resultType从这条语句中返回的期望类型的类的完全限定名或别名。 注意如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身。可以使用 resultType 或 resultMap,但不能同时使用。
resultMap外部 resultMap 的命名引用。resultMap可以给予我们自定义映射规则的机会(通过id引用在映射文件中定义的resultMap)。
flushCache将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false。
useCache将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true。
timeout设置超时时间,超时之后抛出异常,秒 (依赖驱动)。
fetchSize

这是一个给驱动的提示,尝试让驱动程序每次批量返回的结果行数和这个设置值相等。 默认值为未设置(unset)(依赖驱动)。

<!-- resultType="User" User 是完全限定名的别名 -->
<select id="selectByKey" resultType="User"	parameterType="java.lang.Integer">
        <!-- sql 语句 -->
        where id = #{id,jdbcType=INTEGER}
</select>

select自动映射,使用resultType="类的完全限定名"

SQL的列名(sql字段可设置别名)和javaBean的属性名称一致,开启自动映射:autoMappingBehavior设置为PARTIAL或者FULL。

或者:autoMappingBehavior设置为PARTIAL或者FULL + mapUnderscoreToCamelCase设置为ture,可以把数据库的下划线命名规则自动改成驼峰规则进行映射。

实际开发过程中建议使用resultMap,自定义映射规则:解耦、易维护。

select 传参:

1、使用Map传递参数,不建议使用:因为不知道map中到底封入了哪些参数。

接口:
List<TUser> selectByEmailAndSex1(Map<String, Object> param);
对应的xml:
<select id="selectKey" resultType="User" parameterType="java.util.Map">
      sql 语句  
</select>

2、使用注解传递参数,直观明了,如果参数太多时不建议使用

接口
List<TUser> selectBySymbol(@Param("tableName")String tableName,
    		                @Param("inCol")String inCol);
xml:
<select id="selectByKey" resultType="User">  // 不需要指定parameterType 了
    sql 语句 
</select>

3、使用Java Bean 传递参数

接口:
int update(TUser record);

5.2.2 resultMap 

ResultMap 的设计思想:简单的语句不需要明确的结果映射,而复杂一点的语句只需要描述它们的关系就行了。 

属性:
id:当前命名空间中的一个唯一标识,用于标识一个result map. 
type:类的完全限定名, 或者一个类型别名。
autoMapping:如果设置这个属性,MyBatis将会为这个ResultMap开启或者关闭自动映射。这个属 性会覆盖全局的属性 autoMappingBehavior。默认值为:unset

子元素:

constructor - 用于在实例化类时,注入结果到构造方法中。(如果不加constructor,默认使用无参构造,若类没有无参构造,会报错)

             • idArg - ID 参数;标记出作为 ID 的结果可以帮助提高整体性能

             • arg - 将被注入到构造方法的一个普通结果 

<resultMap id="BaseResultMap" type="User">	
		<constructor>
			<idArg column="id" javaType="int"/>
			<arg column="user_name" javaType="String"/>
		</constructor>
		<id column="id" property="id" jdbcType="INTEGER" />
		<result column="user_name" property="userName" jdbcType="VARCHAR" />
		<result column="real_name" property="realName" jdbcType="VARCHAR" />
        ......
</resultMap>
1、一个pojo不存在没有参数的构造方法,就需要使用constructor;
2、为了通过名称来引用构造方法参数,可以添加 @Param 注解,指定参数名称的前提下,以任意顺序编写 arg 元素(否则要按照顺序)

id – 一个 ID 结果;标记出作为 ID 的结果可以帮助提高整体性能

result – 注入到字段或 JavaBean 属性的普通结果

id & result 属性:

property:POJO中映射到列结果的字段或者属性。

column:SQL中的列名,或者是列的别名。

javaType:配置的Java的类;

jdbcType:配置的数据库的类型;

typeHandler:类型处理器,使用这个属性,你可以覆盖默认的类型处理器。这个属性值是一个类型处理器实现类的完全限定名,或者是类型别名。 

id & result 
 id 和 result 都将一个列的值映射到一个简单数据类型(字符串,整型,双精度浮点数,日期等)的属性或字段

 两者之间的唯一不同是, id 表示的结果将是对象的标识属性,这会在比较对象实例时用到。 
这样可以 提高整体的性能,尤其是缓存和嵌套结果映射(也就是联合映射)的时候。

association –( 一对一关系 )  一个复杂类型的关联;许多结果将包装成这种类型

            • 嵌套结果映射 – 关联可以指定为一个 resultMap 元素,或者引用一个

collection –( 一对多关系 )  一个复杂类型的集合

            • 嵌套结果映射 – 集合可以指定为一个 resultMap 元素,或者引用一个

discriminator – 使用结果值来决定使用哪个 resultMap

            • case – 基于某些值的结果映射

                     ° 嵌套结果映射 – 一个 case 也是一个映射它本身的结果,因此可以包含很多相同的元素,或者它可以参照外部的

<resultMap id="report" extends="BaseResultMap" type="User">
	<discriminator column="sex"  javaType="int">
		<case value="1" resultMap="****"/>
		<case value="2" resultMap="****2"/>
	</discriminator>
</resultMap>

定义resultMap:

<resultMap id="BaseResultMap" type="User">	
        <!-- <constructor>
			    <idArg column="id" javaType="int"/>
			    <arg column="user_name" javaType="String"/>
		    </constructor>      -->
		<id column="id" property="id" jdbcType="INTEGER" />
		<result column="user_name" property="userName" jdbcType="VARCHAR" />
		<result column="real_name" property="realName" jdbcType="VARCHAR" />
		......
</resultMap>

使用resultMap

<select id="select" resultMap="BaseResultMap"
		parameterType="map">
		<!-- sql 语句 -->
</select>

5.2.2 insert, update 和 delet

id:命名空间中的唯一标识符,可被用来代表这条语句。

parameterType:将要传入语句的参数的完全限定类名或别名。

flushCache:将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:true(对应插入、 更新和删除语句)。

timeout:超时时间。

statementType:STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。

useGeneratedKeys:(仅对 insert 和 update 有用)使用 JDBC 的 getGeneratedKeys 方法取出由数据库内部生成的主键,默认值:false。

keyProperty:(仅对 insert 和 update 有用)对应数据库主键的POJO属性。MyBatis 会通过 getGeneratedKeys 的返回值或者通过 insert 语句的 selectKey 子元素设置它的键值,默认:unset。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。

keyColumn:(仅对 insert 和 update 有用)数据库主键。通过生成的键值设置表中的列名,这个设置仅在某些数据库(像 PostgreSQL)是必 须的,当主键列不是表中的第一列的时候需要设置。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。

databaseId:如果配置了 databaseIdProvider,MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带 或者不带的语句都有,则不带的会被忽略。 

5.2.3 selectKey元素

查找并且返回数据库生成的主键。

keyProperty:对应数据库主键的POJO 字段。selectKey 语句结果应该被设置的目标属性。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。

keyColumn:数据库主键字段。匹配属性的返回结果集中的列名称。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。

resultType:返回的主键结果类型。MyBatis 通常可以推算出来,但是为了更加确定写上也不会有什么问题。MyBatis 允许任何简单类型用 作主键的类型,包括字符串。如果希望作用于多个生成的列,则可以使用一个包含期望属性的 Object 或一个 Map。

order:这可以被设置为 BEFORE 或 AFTER。如果设置为 BEFORE,那么它会首先选择主键,设置 keyProperty 然后执行插 入语句。如果设置为 AFTER,那么先执行插入语句,然后是 selectKey 元素 - 这和像 Oracle 的数据库相似,在插入 语句内部可能有嵌入索引调用。

statementType:与前面相同,MyBatis 支持 STATEMENT,PREPARED 和 CALLABLE 语句的映射类型,分别代表 PreparedStatement 和 CallableStatement 类型。 

<insert id="insert2" parameterType="TUser">
		<selectKey keyProperty="id" order="AFTER" resultType="int">
			select
			LAST_INSERT_ID()
		</selectKey>
		<!-- insert sql 语句 -->
	</insert>

5.2.4 sql元素和参数

sql元素:用来定义可重用的 SQL 代码段,可以包含在其他语句中; 

参数:向sql语句中传递的可变参数

 预编译 #{}:将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号,能够很大程度防止 sql注入;

 传值    ${}:传入的数据直接显示生成在sql中,无法防止sql注入;

 表名、选取的列是动态的,order by和in操作, 可以考虑使用$

定义代码段:

<sql id="Base_Column_List">
		id, user_name, real_name, sex, mobile, email, note,
		position_id
</sql>

使用代码段:

<select id="selectByPrimaryKey" resultMap="BaseResultMap"
		parameterType="java.lang.Integer">
		select
		<include refid="Base_Column_List" />
		from user
		where id = #{id,jdbcType=INTEGER}
	</select>

5.3 注解方式配置

注解方式就是将SQL语句直接写在接口上,对于需求比较简单的系统,效率较高。缺点在于,每次修改sql语句 都要编译代码,对于复杂的sql语句可编辑性和可读性都差,一般不建议使用这种配置方式; 
 @Select;@Results;@Insert; @Update; @Delete 

5.4 动态sql元素

if:判断语句,单条件分支判断

choose、when、otherwise:相当于java的case when,多条件分支判断

Trim、where、set:辅助元素,用于处理sql拼装问题

foreach:循环语句,在in语句等列举条件常用,常用于实现批量操作 

除开使用动态sql的foreach 做批量操作外,还可以使用BATCH类型的excutor。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值