SSM Chapter 01 初识MyBatis

SSM Chapter 01 初识MyBatis 笔记

MyBatis体系结构图:

在这里插入图片描述

本章目标:

1. 框架技术

1.1 为什么要学习框架技术

(1) 不用考虑公共问题框架已经帮我们做好了

(2) 可以专心业务逻辑保证核心业务逻辑的开发质量

(3) 结构统一 便于学习和维护

(4) 框架集成了前人经验 可以帮助新手快速开发出稳定 性能优良 而且 结构优美的高质量程序

1.2 框架的概念

框架(Framework) 是一个提供了可重用的公共结构的半成品,它为我们构建新的应用程序提供了极大的便利 。

一方面提供了可以拿来就用的工具,更重要的是提供了可重用的设计。

框架这个词最早出现在建筑领域,指的是在建造房屋前期构建的骨架。

对应用程序来说,框架就是应用程序的骨架。

开发者可以在这个骨架上加上自己的东西 搭建符合自己需求的应用系统

1.3 主流框架介绍

  • Struts 2 框架:

    • 特点: MVC设计模式实现的web应用程序框架 逻辑中分离出横切关注点的拦截器 可变更和可重用的标签
  • Hibernate 框架:

    • 特点:简化DAO层 通过简单配置和编码代替JDBC烦琐的程序代码
  • Spring 框架:

    • 特点:简化Java EE的应用 依赖注入容器/AOP实现 声明式事务 集成各种市场上流行的框架
  • Spring MVC 框架:

    • 特点:结构最清晰MVC Model2的实现 高度可配置性 多种视图技术 可以进行定制化开发
  • MyBatis 框架:

    • 特点:半自动化ORM框架 支持定制化 SQL、存储过程以及高级映射

2. MyBatis 介绍及其环境搭建

2.1 数据持久化概念

持久化是程序数据在瞬时状态和持久状态间转换的过程

通俗的讲 就是将内存中的数据模型转换为存储模型 以及将存储模型转换为内存中的数据模型的统称 例如:文件的存储 数据的读取等都是数据持久化的操作 数据模型可以是任何数据结构或者对象模型 存储模型可以是关系模型 XML 二进制流等

从第一学期开始 我们就编写应用程序操作数据表 对数据表进行增删改查的操作 及数据持久化的操作

2.2 MyBatis 框架 以及 ORM

2.2.1 什么是ORM:
  • ORM(Object/Relational Mapping) 即对象/关系映射 是一种数据持久化技术 它在对象模型和关系型数据库之间建立起对应关系 并提供一种机制 通过JavaBean对象去操作数据库表中的数据
  • ORM解决方案包含以下四个部分:
    • 在持久化对象上执行基本的增、删、改、查操作
    • 对持久化对象提供一种查询语言或者API
    • 对象关系映射工具
    • 提供与事务对象交互、执行检查、延迟加载以及其他优化功能
2.2.2 MyBatis 简介:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EowG6fdx-1607157356350)(ssm-ch01.assets/03.png)]

MyBatis 前身是iBatis,本是Apache的一个开源的项目,是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

官方网站 :https://mybatis.org/mybatis-3/ 中文地址 :http://www.mybatis.org/mybatis-3/zh/index.html

GitHub地址 :https://github.com/mybatis

特点:基于SQL语法,简单易学 能了解底层封装过程

SQL语句封装在配置文件中,便于统一管理与维护,降低程序的耦合度 方便程序代码调试

返回顶部

2.3 MyBatis 环境搭建

2.3.1 安装

要使用 MyBatis, 只需将 mybatis-x.x.x.jar 文件置于 classpath 中即可

如果使用 Maven 来构建项目,则需将下面的dependency 代码置于 pom(ProjectObjectModel).xml 文件中

<!-- 加入mybatis依赖 -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.1</version>
</dependency>

<!-- 加入junit 依赖 -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>
<!-- 加入mysql 依赖 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.38</version>
</dependency>
<!-- 加入log4j 依赖 -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
2.3.2 创建核心配置文件

创建MyBatis的核心配置文件 configuration.xml (为了方便框架集成更好区分配置文件,建议改名为mybatis-config.xml) XML 配置文件中包含了对 MyBatis 系统的核心设置,包含获取数据库连接实例的数据源(DataSource)和决定事务作用域和控制方式的事务管理器(TransactionManager)。

XML 配置文件的详细内容后面再探讨,这里先给出一个简单的示例:

可参照官网https://mybatis.org/mybatis-3/zh/getting-started.html

<?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>
	<!-- 引入 database.properties 文件-->
	<properties resource="database.properties" />
	<!-- 配置mybatis的log实现为LOG4J -->
	<settings>
		<setting name="logImpl" value="LOG4J" />
	</settings>
    <environments default="development">
        <environment id="development">
          <!--配置事务管理,采用JDBC的事务管理  -->
          <transactionManager type="JDBC"/>
          <!-- POOLED:mybatis自带的数据源,JNDI:基于tomcat的数据源 -->
          <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://127.0.0.1:3306/smbms?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
          </dataSource>
        </environment>
   </environments>
   <mappers>
     <!-- 使用相对于类路径的资源引用 -->
     <mapper resource="cn/smbms/dao/UserMapper.xml"/>
   </mappers>
</configuration>

MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。

mybatis-config.xml文件几个常用元素作用如下:

  • (1) configuration:配置文件的根元素节点
  • (2) properties(属性):通过resource属性从外部指定properties属性文件(database.properties),该属性文件描述数据库连接的相关配置(数据库驱动,连接数据库的url,数据库用户名,数据库密码) 位置也是在resources目录下.
  • (3) settings(设置):这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。

  • (4) environments(环境配置):MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema 的多个生产数据库中 使用相同的 SQL 映射。有许多类似的使用场景。

    • 不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境
  • (5) environment:配置MyBatis的一套运行环境,需要制定运行环境的id,事务管理,数据源配置等相关信息

  • (6) mappers(映射器):作用是告诉MyBatis去哪里找到SQL映射文件(该文件的内容是开发者定义的映射SQL语句), 整个项目中可以有1个或多个SQL映射文件

  • (7)mapper:mappers的子元素节点.具体指定SQL映射文件的路径,其中resource属性的值表述了SQL映射文件的路径(类资源路径)

    • 必须注意的是:mybatis-config.xml文件的元素节点是有一定顺序的,节点位置若不按照顺序排位,XML文件就会报错

database.properties文件内容如下:

driver=com.mysql.jdbc.Driver
#在和mysql传递数据的过程中,使用unicode编码格式,并且字符集设置为utf-8
url=jdbc:mysql://127.0.0.1:3306/smbms?useUnicode=true&characterEncoding=utf-8
username=root
password=root

log4j.properties文件内容如下:

# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# MyBatis logging configuration...
log4j.logger.cn.smbms.dao=DEBUG
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
2.3.3 创建持久化类(POJO) 和SQL 映射文件

持久化类是指其实例状态需要被MyBatis持久化到数据库中的类。

在应用的设计中,持久化类通常对应需求中的业务实体,MyBatis一般采用POJO编程模型来实现持久化类,与POJO类配合完成持久化操作是MyBatis最常见的工作模式

POJO(Plain Ordinary Java Object),从字面上来讲就是普通的Java对象。

POJO类可以简单的理解为符合JavaBean规范的实体类。

它不需要继承任何特殊的Java基类,根据需求可以实现Serializable接口。JavaBean对象的状态保存在属性中,访问属性必须通过对应的getter和setter方法。

package cn.smbms.pojo;
import java.io.Serializable;
import java.util.Date;
/**
 * 用户信息类
 */
public class User implements Serializable{
	private Integer id;			//id
	private String userCode;    //用户编码
	private String userName;	//用户名称
	private String userPassword;//用户密码
	private Integer gender;		//性别
	private Date  birthday;		//出生日期
	private String phone;		//电话
	private String address;		//地址
	private Integer userRole;   //用户角色
	private Integer createBy;   //创建者
	private Date creationDate;  //创建时间
	private Integer modifyBy;   //更新者
	private Date modifyDate;    //更新时间
	//省略 getter和setter方法 以及 toString方法
}

注意:

在MyBatis中,不需要POJO类名与数据表名一致,因为MyBatis是POJO与SQL语句之间的映射机制,一般情况下保证POJO对象的属性与数据库表的字段名一致即可

接下来 继续进行SQL映射文件的创建,完成与POJO(实体类)的映射,该文件也是一个xml文件,命名为UserMapper.xml,文件所在的包名为:cn.smbms.dao,文件内容可以从官方手册查看到

<?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="cn.smbms.dao.UserMapper">
  <select id="selectUser" resultType="cn.smbms.pojo.User">
    select * from smbms_user where id = #{id}
  </select>
</mapper>

经验:

SQL映射文件一般都对应于相应的POJO,所以一般都是采用POJO名称+Mapper的规则来进行命名。当然mapper文件属于DAO层的操作,应该放在dao包下,并根据业务功能进行分包放置。如:cn.smbms.dao.UserMapper.xml

UserMapper.xml文件中定义了SQL语句,其中各个元素如下:

mapper:映射文件的根元素节点,只有一个属性namespace

namespace:用于区分不同的mapper 全局唯一

select:表示查询语句,是mybatis中最常用的元素之一。常用的属性如下:

id属性:该命名空间下唯一标识符

resultType属性:表示SQL语句的返回值类型,此处通过SQL语句返回的User类型

2.3.4 创建测试类 :

编写测试类有两种方式,分别如下:

第一种:从XML中构建SqlSessionFactory

每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先定制的 Configuration 的实例构建出 SqlSessionFactory 的实例。

从 XML 文件中构建 SqlSessionFactory 的实例非常简单,建议使用类路径下的资源文件进行配置。 但是也可以使用任意的输入流(InputStream)实例,包括字符串形式的文件路径或者 file:// 的 URL 形式的文件路径来配置。MyBatis 包含一个名叫 Resources 的工具类,它包含一些实用方法,可使从 classpath 或其他位置加载资源文件更加容易。

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建SqlSessionFactory对象 mybatis使用构建者模式 而SqlSessionFactoryBuilder就是构建者
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  • 从 SqlSessionFactory 中获取 SqlSession
    • 既然有了 SqlSessionFactory,顾名思义,我们就可以从中获得 SqlSession 的实例了。SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。例如:
//创建SqlSession对象  此处mybatis 使用了工厂模式 不使用new的目的是为了降低类之间的依赖关系
SqlSession session = sqlSessionFactory.openSession();
try {
  User user = session.selectOne("cn.smbms.dao.UserMapper.selectUser", 1);
} finally {
  session.close();
}

Eclipse 运行测试代码,结果正确输出。但是,请注意 若是使用 Intellij IDEA 运行测试代码时,发现程序报错,web项目报错信息如下:

### Error querying database.  Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for cn.smbms.dao.UserMapper.selectUser
### Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for cn.smbms.dao.UserMapper.selectUser

这两句报错信息,很明显说的是 mapper.xml里的namespace报错 或者是方法名报错,但是仔细排查发现并未出现错误. 问题出在哪儿呢? 这是因为 Intellij IDEA 使用maven在编译的时候,如果配置文件不是放在resources文件夹下就不会被执行编译,所以导致运行时找不到对应的xml映射文件。

若是jar项目会报出UserMapper.xml映射文件不存在的错误.

解决方法:

(1) 在main/resources目录下创建 mapper目录,将对应的xml映射文件拖到mapper目录下,然后修改mybatis-config.xml文件中的 <mapper>元素,改为如下代码:

<mappers>
	<mapper resource="mapper/UserMapper.xml"/>
</mappers>

运行测试代码,控制台上正确输出结果。

但这种方式的弊端是:破坏了项目的包结构。如果项目包的结构已经确定,而且项目代码也已经很多了,同时有很多人都在用,而此时改变项目包结构就会变得很麻烦,可以采用第二种方式:

(2) 在项目pom.xml文件中找到<build></build>标签,在其中添加以下几行,用于扫描xml文件

<resources>
    <resource>
    	<directory>src/main/java</directory>
    	<includes>
    		<include>**/*.xml</include>
    	</includes>
    </resource>
</resources>
第二种:不使用 XML 构建 SqlSessionFactory

如果你更愿意直接从 Java 代码而不是 XML 文件中创建配置,或者想要创建你自己的配置建造器,MyBatis也提供了完整的配置类,提供了所有与 XML 文件等价的配置项。

创建封装数据连接池的类cn.smbms.util.UserDataSourceFactory,代码如下:

/**
 * 封装数据连接池的类 此类相当于mybatis-config.xml文件中的environment元素中的dataSource
 */
public class UserDataSourceFactory {
    public static DataSource getUserDataSource() {
        String driver = "com.mysql.jdbc.Driver";
        String user = "root";
        String password = "root";
        String url = "jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=utf-8&useSSL=false";
        DataSource dataSource = new PooledDataSource(driver,url,user,password);
        return dataSource;
    }
}

编写cn.smbms.dao.UserMapper接口,代码如下:

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

编写测试方法,代码如下:

@Test
public void testSelectUserById_2() throws IOException {
    DataSource dataSource = UserDataSourceFactory.getUserDataSource();
    TransactionFactory transactionFactory = new JdbcTransactionFactory();
    Environment environment = new Environment("development", transactionFactory, dataSource);
    Configuration configuration = new Configuration(environment);
    configuration.addMapper(UserMapper.class);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
    try (SqlSession session = sqlSessionFactory.openSession()) {
        User user = (User) session.selectOne("cn.smbms.dao.UserMapper.selectUser", 1);
        System.out.println(user);
    }
}

注意该例中:

configuration 添加了一个映射器类(mapper class)。

映射器类是Java 类,它们包含 SQL 映射注解从而避免依赖 XML 文件。不过,由于 Java 注解的一些限制以及某些 MyBatis 映射的复杂性,要使用大多数高级映射(比如:嵌套联合映射),仍然需要使用 XML 配置。

有鉴于此,如果存在一个同名XML 配置文件,MyBatis 会自动查找并加载它(在这个例子中,基于类路径和 UserMapper.class 的类名,会加载UserMapper.xml)。具体细节稍后讨论。

2.4 MyBatis框架的优缺点 及其适用场合

2.4.1 MyBatis框架的优点
  • (1) 与 JDBC 相比,减少了50%的代码量
  • (2) MyBatis是最简单的持久化框架,小巧并且简单易学
  • (3) MyBatis 相当灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL写在XML文件里,从程序代码中彻底分离,降低耦合度,便于统一管理和优化,并可重用
  • (4) 提供XML标签,支持编写动态SQL语句。
  • (5) 提供映射标签,支持对象与数据库的ORM字段关系映射
2.4.2 MyBatis框架的缺点
  • (1) SQL语句的编写工作量较大,对开发人员编写SQL语句的功底有一定要求。
  • (2) SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。
2.4.3 MyBatis 框架的使用场合

MyBatis专注于SQL本身,是一个足够灵活的DAO层解决方案。对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis将是不错的选择。

返回顶部

3. MyBatis的基本要素 ---- 核心对象

基于以上内容,我们对MyBatis有了初步认识,下面正式介绍一下MyBatis的三个基本要素:

  • 核心接口和类
  • MyBatis 核心配置文件 (mybatis-config.xml)
  • SQL映射文件(mapper.xml)

3.1 SqlSessionFactoryBuilder

3.1.1 SqlSessionFactoryBuilder的作用:

SqlSessionFactoryBuilder负责构建SqlSessionFacoty,并提供了多个build()方法的重载,具体可参考手册

3.1.2 SqlSessionFactoryBuilder的生命周期 和 作用域

这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但是最好还是不要让其一直存在,以保证所有的 XML 解析资源可以被释放给更重要的事情.

3.2 SqlSessionFactory

3.2.1 SqlSessionFactory的作用

每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先定制的 Configuration 的实例构建出 SqlSessionFactory 的实例。

既然有了 SqlSessionFactory,顾名思义,我们就可以从中获得 SqlSession 的实例了。SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句

3.2.2 SqlSessionFactory的声明周期和作用域

SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏味道(bad smell)”。

因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。

对SqlSessionFactory的代码进行优化,最简单的方式就是放在静态代码块里,以保证SqlSessionFactory对象只被创建异常。

实现步骤如下:

  • (1) 创建工具类 MyBatisUtil.java 在静态代码块中创建SqlSessionFactory对象

    public class MyBatisUtil {
    	private static SqlSessionFactory factory;
    	private MyBatisUtil(){}
    	static{//在静态代码块下,factory只会被创建一次
    		System.out.println("static factory===============");
    		try {
    			InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
    			factory = new SqlSessionFactoryBuilder().build(is);
    		} catch (IOException e) {
    			e.printStackTrace();
    		} 
    	}
    }
    
  • (2) 创建SqlSession对象 和 关闭 SqlSession

    public static SqlSession createSqlSession(){
    	return factory.openSession();//true 为自动提交事务 默认值是false
    }
    
    public static void closeSqlSession(SqlSession sqlSession){
        if(null != sqlSession) 
        sqlSession.close();
    }
    

通过以上静态类的方式来保证SqlSessionFactory实例只被创建一次,当然最佳的解决方案是使用依赖注入容器:Spring框架 来管理SqlSessionFactory的单例生命周期,关于和Spring的集成,我们会在以后的章节中进行讲解

3.3 SqlSession

3.3.1 SqlSession的作用

SqlSession 是用于执行持久化操作的对象,类似于JDBC中的Connection。它提供了面向数据库执行SQL命令所需的所有方法,可以通过SqlSession实例直接运行已映射的SQL语句

常用的方法如下:
在这里插入图片描述

3.3.2 SqlSession的生命周期和作用域

每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。

绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。

也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你现在正在使用一种 Web 框架,要考虑 SqlSession 放在一个和 HTTP 请求对象相似的作用域中。 换句话说,每次收到的 HTTP 请求,就可以打开一个 SqlSession,返回一个响应,就关闭它。 这个关闭操作是很重要的,你应该把这个关闭操作放到 finally 块中以确保每次都能执行关闭。

下面的示例就是一个确保 SqlSession 关闭的标准模式:

SqlSession session = sqlSessionFactory.openSession();
try {
  // 你的应用逻辑代码
} finally {
  session.close();
}
3.3.3 SqlSession的三种使用方式

(1) 通过SqlSession实例 来直接执行已映射的SQL语句。例如 通过selectList方法执行用户表的查询操作。步骤:

  • UserMapper.xml文件中添加查询元素:

    <!--查询用户列表  -->	
      <select id="getUserList" resultType="cn.smbms.pojo.User">
        select * from smbms_user
      </select>
    
  • 修改测试类 UserMapperTest.java, 调用selectList()方法执行查询操作:

    //测试查询用户列表
    @Test
    public void testGetUserList() throws IOException {
        SqlSession session = MyBatisUtil.createSqlSession();
        try {
            List<User> list = session.selectList("cn.smbms.dao.UserMapper.getUserList");
            list.forEach(x->logger.debug(x));
        } finally {
        	MyBatisUtil.close(session);
        }
    }
    

(2) 基于mapper接口操作数据,修改上一个演示案例,步骤如下:

  • 创建绑定映射语句的接口UserMapper.java,并提供接口方法getUserList(),该接口称为映射器

    此接口命名 必须与对应mapper.xml的namespace属性一致,方法命名必须与mapper.xml文件中的select子元素中的id一致,方法的返回值必须与select元素中的resultType一致,若是泛型集合,则集合中的泛型类型应与resultType类型一致

    package cn.smbms.dao;
    import java.util.List;
    import cn.smbms.pojo.User;
    public interface UserMapper {
    	/**
    	 * 查询用户列表
    	 * @return
    	 */
    	List<User> getUserList();
    }
    
  • 修改测试类 UserMapperTest.java,调用sqlSession的getMapper(Mapper.class)获取一个Mapper,然后执行Mapper接口中的方法来实现对数据的查询操作。

    //测试查询用户列表
    @Test
    public void testGetUserList() throws IOException {
        SqlSession session = MyBatisUtil.createSqlSession();
        try {
        	UserMapper userMapper = session.getMapper(UserMapper.class);
            List<User> list = userMapper.getUserList();
            list.forEach(x->logger.debug(x));
        } finally {
        	MyBatisUtil.close(session);
        }
    }
    

    注意:

    第一种方式能够正常工作,并且对于使用旧版本 MyBatis 的用户来说也比较熟悉。不过现在有了一种更简洁的方式 ——使用正确描述每个语句的参数和返回值的接口(比如 UserMapper.class),你现在不仅可以执行更清晰和类型安全的代码,而且还不用担心易错的字符串字面值以及强制类型转换.这是MyBatis所推荐使用的

(3) 使用 Java 注解来配置,步骤如下:

对命名空间的一点说明:

在之前版本的 MyBatis 中,命名空间(Namespaces)的作用并不大,是可选的。 但现在,随着命名空间越发重要,你必须指定命名空间。

命名空间的作用有两个

一个是利用更长的完全限定名来将不同的语句隔离开来,同时也实现了你上面见到的接口绑定。就算你觉得暂时用不到接口绑定,你也应该遵循这里的规定,以防哪天你改变了主意。 长远来看,只要将命名空间置于合适的 Java 包命名空间之中,你的代码会变得更加整洁,也有利于你更方便地使用 MyBatis。

另一个是命名解析,为了减少输入量,MyBatis 对所有的命名配置元素(包括语句,结果映射,缓存等)使用了如下的命名解析规则。

  • 完全限定名(比如 “com.mypackage.MyMapper.selectAllThings)将被直接用于查找及使用。
  • 短名称(比如 “selectAllThings”)如果全局唯一也可以作为一个单独的引用。 如果不唯一,有两个或两个以上的相同名称(比如 “com.foo.selectAllThings” 和 “com.bar.selectAllThings”),那么使用时就会产生“短名称不唯一”的错误,这种情况下就必须使用完全限定名。

对于像 UserMapper 这样的映射器类来说,还有另一种方法来处理映射。 它们映射的语句可以不用 XML 来配置,而可以使用 Java 注解来配置。比如,上面的 XML 示例可被替换如下:

package cn.smbms.dao;
import java.util.List;
import org.apache.ibatis.annotations.Select;
import cn.smbms.pojo.User;
public interface UserMapper {
	/**
	 * 使用注解 查询用户列表
	 * @param id
	 * @return
	 */
	@Select("select * from smbms_user")
	List<User> getUserList();
}
  • 修改mybatis-config.xml文件,将mapper的属性修改为class

    <mappers>
    	<mapper class="cn.smbms.dao.UserMapper" /> 
    </mappers>
    
  • 删除xml文件 , 保证mybatis 不会扫描到对应的xml文件,运行测试类,控制台显示结果

经验:

使用注解来映射简单语句会使代码显得更加简洁,然而对于稍微复杂一点的语句,Java 注解就力不从心了,并且会显得更加混乱。 因此,如果你需要完成很复杂的事情,那么最好使用 XML 来映射语句。

选择何种方式来配置映射,以及认为映射语句定义的一致性是否重要,这些完全取决于你和你的团队。 换句话说,永远不要拘泥于一种方式,你可以很轻松的在基于注解和 XML 的语句映射方式间自由移植和切换

返回顶部

4. MyBatis的基本要素 ---- 核心配置文件

mybatis-config.xml文件结构

MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。需要注意的是,该配置文件的元素节点是由先后顺序的, 配置文档的顶层结构如下:

  • configuration(配置)
    • [properties(属性)] 可以配置在Java属性配置文件中
    • [settings(设置)] 修改MyBatis在运行时的行为方式
    • [typeAliases(类型别名)] 为Java类型命名一个别名(简称)
    • [typeHandlers(类型处理器)] 类型处理器
    • [objectFactory(对象工厂)] 对象工厂
    • [plugins(插件)]
    • environments(环境配置)
      • environment(环境变量)
        • transactionManager(事务管理器)
        • dataSource(数据源)
    • [databaseIdProvider(数据库厂商标识)]
    • [mappers(映射器)]

从以上的结构中,可以看出configuration元素是整个XML配置文件的根节点,其角色就相当于MyBatis的总管,MyBatis所有的配置信息都会存放在它里面。

MyBatis还提供了设置这些配置信息的方法,Configuration可从配置文件中获取属性值,也可以通过程序直接设置,Configuration可配置的内容如下:

4.1 properties 元素

这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。

(1) 通过外部指定的方式,即可配置在典型的Java属性配置文件中(如database.properties),并使用这些属性对配置项实现动态配置,代码如下:

database.properties内容如下:

driver=com.mysql.jdbc.Driver
#在和mysql传递数据的过程中,使用unicode编码格式,并且字符集设置为utf-8
url=jdbc:mysql://127.0.0.1:3306/smbms?useUnicode=true&characterEncoding=utf-8
username=root
password=root

mybatis-config.xml部分内容如下:

<!-- 引入 database.properties文件 -->
<properties resource="database.properties">
	<property name="username" value="root"/>
</properties>
<environments default="development">
	<environment id="development">
        <transactionManager type="JDBC" />
        <dataSource type="POOLED">
            <property name="driver" value="${driver}" />
            <property name="url" value="${url}" />
            <property name="username" value="${username}" />
            <property name="password" value="${password}" />
        </dataSource>
    </environment>
</environments>

在上述代码中,driver url username,password属性将会用包含进来的database.properties文件中的值来替换

(2) 直接配置xml 并使用这些属性 实现动态配置 代码如下:

mybatis-config.xml 部分内容:

<!-- properties元素中直接配置property 属性-->
<properties>
    <property name="driver" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://127.0.0.1:3306/smbms"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
</properties> 
......
<dataSource type="POOLED">
    <property name="driver" value="${driver}"/>
    <property name="url" value="${url}"/>
    <property name="username" value="${user}"/>
    <property name="password" value="${password}"/>
</dataSource>

上述代码中,driver url username password 将会由properties元素中设置的值来替换

思考,若两种方式同时都用了,那么哪种方式优先?如下代码演示:

<!-- properties元素中直接配置property 属性-->
<properties resource="database.properties">
    <property name="username" value="root"/>
    <property name="password" value="123456"/>
</properties> 

分析:

这个例子中的property子节点设置的username 和 password的值会被先读取,但是由于database.properties中也设置了这两个属性,所以resource中同名属性将会覆盖property子节点的值。结合resource属性值的优先级高于 property子节点配置的值,具体说明可参照官方手册:

如果属性在不只一个地方进行了配置,那么 MyBatis 将按照下面的顺序来加载:

  • 在 properties 元素体内指定的属性首先被读取。
  • 然后根据 properties 元素中的 resource 属性读取类路径下属性文件或根据 url 属性指定的路径读取属性文件,并覆盖已读取的同名属性。
  • 最后读取作为方法参数传递的属性,并覆盖已读取的同名属性。

因此,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的是 properties 属性中指定的属性。

4.2 settings 元素

这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项的意图、默认值等。

设置名描述有效值默认值
cacheEnabled全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存。true | falsetrue
lazyLoadingEnabled延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。true | falsefalse
aggressiveLazyLoading当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个属性会按需加载(参考 lazyLoadTriggerMethods)。true | falsefalse (在 3.4.1 及之前的版本默认值为 true)
multipleResultSetsEnabled是否允许单一语句返回多结果集(需要驱动支持)。true | falsetrue
useColumnLabel使用列标签代替列名。不同的驱动在这方面会有不同的表现,具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果。true | falsetrue
useGeneratedKeys允许 JDBC 支持自动生成主键,需要驱动支持。 如果设置为 true 则这个设置强制使用自动生成主键,尽管一些驱动不能支持但仍可正常工作(比如 Derby)。true | falseFalse
autoMappingBehavior指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示取消自动映射;PARTIAL 只会自动映射没有定义嵌套结果集映射的结果集。 FULL 会自动映射任意复杂的结果集(无论是否嵌套)。NONE, PARTIAL, FULLPARTIAL
autoMappingUnknownColumnBehavior指定发现自动映射目标未知列(或者未知属性类型)的行为。NONE: 不做任何反应WARNING: 输出提醒日志 ('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior'的日志等级必须设置为 WARN)FAILING: 映射失败 (抛出 SqlSessionException)NONE, WARNING, FAILINGNONE
defaultExecutorType配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements); BATCH 执行器将重用语句并执行批量更新。SIMPLE REUSE BATCHSIMPLE
defaultStatementTimeout设置超时时间,它决定驱动等待数据库响应的秒数。任意正整数未设置 (null)
defaultFetchSize为驱动的结果集获取数量(fetchSize)设置一个提示值。此参数只可以在查询设置中被覆盖。任意正整数未设置 (null)
safeRowBoundsEnabled允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。true | falseFalse
safeResultHandlerEnabled允许在嵌套语句中使用分页(ResultHandler)。如果允许使用则设置为 false。true | falseTrue
mapUnderscoreToCamelCase是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。true | falseFalse
localCacheScopeMyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。SESSION | STATEMENTSESSION
jdbcTypeForNull当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。JdbcType 常量,常用值:NULL, VARCHAR 或 OTHER。OTHER
lazyLoadTriggerMethods指定哪个对象的方法触发一次延迟加载。用逗号分隔的方法列表。equals,clone,hashCode,toString
defaultScriptingLanguage指定动态 SQL 生成的默认语言。一个类型别名或完全限定类名。org.apache.ibatis.scripting.xmltags.XMLLanguageDriver
defaultEnumTypeHandler指定 Enum 使用的默认 TypeHandler 。(新增于 3.4.5)一个类型别名或完全限定类名。org.apache.ibatis.type.EnumTypeHandler
callSettersOnNulls指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这在依赖于 Map.keySet() 或 null 值初始化的时候比较有用。注意基本类型(int、boolean 等)是不能设置成 null 的。true | falsefalse
returnInstanceForEmptyRow当返回行的所有列都是空时,MyBatis默认返回 null。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集 (如集合或关联)。(新增于 3.4.2)true | falsefalse
logPrefix指定 MyBatis 增加到日志名称的前缀。任何字符串未设置
logImpl指定 MyBatis 所用日志的具体实现,未指定时将自动查找。SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING未设置
proxyFactory指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。CGLIB | JAVASSISTJAVASSIST (MyBatis 3.3 以上)
vfsImpl指定 VFS 的实现自定义 VFS 的实现的类全限定名,以逗号分隔。未设置
useActualParamName允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的项目必须采用 Java 8 编译,并且加上 -parameters 选项。(新增于 3.4.1)true | falsetrue
configurationFactory指定一个提供 Configuration 实例的类。 这个被返回的 Configuration 实例用来加载被反序列化对象的延迟加载属性值。 这个类必须包含一个签名为static Configuration getConfiguration() 的方法。(新增于 3.2.3)类型别名或者全类名.未设置

一个配置完整的 settings 元素的示例如下:

<settings>
  <setting name="cacheEnabled" value="true"/>
  <setting name="lazyLoadingEnabled" value="true"/>
  <setting name="multipleResultSetsEnabled" value="true"/>
  <!-- 使用列别名替换列名 默认:true -->
  <setting name="useColumnLabel" value="true"/>
  <!-- 使用jdbc的getGeneratedKeys 设置为true获取数据库自增主键值  -->
  <setting name="useGeneratedKeys" value="false"/>
  <setting name="autoMappingBehavior" value="PARTIAL"/>
  <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
  <setting name="defaultExecutorType" value="SIMPLE"/>
  <setting name="defaultStatementTimeout" value="25"/>
  <setting name="defaultFetchSize" value="100"/>
  <setting name="safeRowBoundsEnabled" value="false"/>
<!-- true为开启驼峰命名转换:Table{create_time} -> Entity{createTime} -->
  <setting name="mapUnderscoreToCamelCase" value="false"/>
  <setting name="localCacheScope" value="SESSION"/>
  <setting name="jdbcTypeForNull" value="OTHER"/>
  <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
4.3 typeAliases 元素

类型别名是为 Java 类型设置一个短的名字。 它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。例如:

<typeAliases>
  <!-- 这里给实体类去别名 方便在mapper配置文件中使用 -->
  <typeAlias alias="user" type="cn.smbms.pojo.User"/>
  <typeAlias alias="provider" type="cn.smbms.pojo.Provider"/>
  ......
</typeAliases>

当这样配置时,User 可以用在任何使用 cn.smbms.pojo.User 的地方。这种写法的弊端在于如果一个项目中有多个POJO的时候,需要一一配置,所以有更加简化的写法,可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:

<typeAliases>
  <package name="cn.smbms.pojo"/>
</typeAliases>

每一个在包cn.smbms.pojo 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 cn.smbms.pojo.User 的别名为 user;若有注解,则别名为其注解值。见下面的例子:

//此处可以使用注解简化别名
@Alias("u")
public class User {
    ...
}

UserMapper.xml中的配置如下:

<!-- 这里的resultType 可以写使用注解简化的别名 -->
<select id="getUserList" resultType="u">
    select * from smbms_user
 </select>

另外,MyBatis已经为常见的 Java 类型内建了相应的类型别名。它们都是不区分大小写的,注意对基本类型名称重复采取的特殊命名风格。

别名映射的类型
_bytebyte
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
byteByte
longLong
shortShort
intInteger
integerInteger
doubleDouble
floatFloat
booleanBoolean
dateDate
decimalBigDecimal
bigdecimalBigDecimal
objectObject
mapMap
hashmapHashMap
listList
arraylistArrayList
collectionCollection
iteratorIterator
4.4 类型处理器(typeHandlers)

typeHandlers又叫类型处理器,就像在JDBC中,我们在PreparedStatement中设置预编译sql所需的参数或执行sql后根据结果集ResultSet对象获取得到的数据时,需要将数据库中的类型和java中字段的类型进行转换一样,在MyBatis中使用typeHandler来实现。

所以说白了,typeHandlers就是用来完成javaType和jdbcType之间的转换。

举个比较简单的例子,比如超市订单管理系统中的用户表中的创建时间和修改时间加入用VARCHAR类型,但是在我的POJO对象中,创建时间和修改时间的类型是Date,这样我在向数据库插入数据时,需要将日期类型转化成VARCHAR,而从数据库中查询出的结果中,又需要将VARCHAR类型转换成Date.

在MyBatis中,使用typeHandlers配置来实现这个转换过程。和别名一样,MyBatis中的类型处理器也存在系统定义的和自定义两种,MyBatis会根据javaType和jdbcType来决定采用哪个typeHandler来处理这些转换规则,而且系统定义的能满足大部分需求,可以说是非常好用

下表描述了一些默认的类型处理器。

提示 从 3.4.5 开始,MyBatis 默认支持 JSR-310(日期和时间 API) 。

类型处理器Java 类型JDBC 类型
BooleanTypeHandlerjava.lang.Boolean, boolean数据库兼容的 BOOLEAN
ByteTypeHandlerjava.lang.Byte, byte数据库兼容的 NUMERICBYTE
ShortTypeHandlerjava.lang.Short, short数据库兼容的 NUMERICSMALLINT
IntegerTypeHandlerjava.lang.Integer, int数据库兼容的 NUMERICINTEGER
LongTypeHandlerjava.lang.Long, long数据库兼容的 NUMERICBIGINT
FloatTypeHandlerjava.lang.Float, float数据库兼容的 NUMERICFLOAT
DoubleTypeHandlerjava.lang.Double, double数据库兼容的 NUMERICDOUBLE
BigDecimalTypeHandlerjava.math.BigDecimal数据库兼容的 NUMERICDECIMAL
StringTypeHandlerjava.lang.StringCHAR, VARCHAR
ClobReaderTypeHandlerjava.io.Reader-
ClobTypeHandlerjava.lang.StringCLOB, LONGVARCHAR
NStringTypeHandlerjava.lang.StringNVARCHAR, NCHAR
NClobTypeHandlerjava.lang.StringNCLOB
BlobInputStreamTypeHandlerjava.io.InputStream-
ByteArrayTypeHandlerbyte[]数据库兼容的字节流类型
BlobTypeHandlerbyte[]BLOB, LONGVARBINARY
DateTypeHandlerjava.util.DateTIMESTAMP
DateOnlyTypeHandlerjava.util.DateDATE
TimeOnlyTypeHandlerjava.util.DateTIME
SqlTimestampTypeHandlerjava.sql.TimestampTIMESTAMP
SqlDateTypeHandlerjava.sql.DateDATE
SqlTimeTypeHandlerjava.sql.TimeTIME
ObjectTypeHandlerAnyOTHER 或未指定类型
EnumTypeHandlerEnumeration TypeVARCHAR 或任何兼容的字符串类型,用以存储枚举的名称(而不是索引值)
EnumOrdinalTypeHandlerEnumeration Type任何兼容的 NUMERICDOUBLE 类型,存储枚举的序数值(而不是名称)。
SqlxmlTypeHandlerjava.lang.StringSQLXML
InstantTypeHandlerjava.time.InstantTIMESTAMP
LocalDateTimeTypeHandlerjava.time.LocalDateTimeTIMESTAMP
LocalDateTypeHandlerjava.time.LocalDateDATE
LocalTimeTypeHandlerjava.time.LocalTimeTIME
OffsetDateTimeTypeHandlerjava.time.OffsetDateTimeTIMESTAMP
OffsetTimeTypeHandlerjava.time.OffsetTimeTIME
ZonedDateTimeTypeHandlerjava.time.ZonedDateTimeTIMESTAMP
YearTypeHandlerjava.time.YearINTEGER
MonthTypeHandlerjava.time.MonthINTEGER
YearMonthTypeHandlerjava.time.YearMonthVARCHARLONGVARCHAR
JapaneseDateTypeHandlerjava.time.chrono.JapaneseDateDATE

你可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。具体做法请参考官网:https://mybatis.org/mybatis-3/zh/configuration.html#typeAliases

4.5 environments 元素

MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema 的多个生产数据库中 使用相同的 SQL 映射。有许多类似的使用场景。

不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。

所以,如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。而如果是三个数据库,就需要三个实例,依此类推,记起来很简单:

每个数据库对应一个 SqlSessionFactory 实例

为了指定创建哪种环境,只要将它作为可选的参数传递给 SqlSessionFactoryBuilder 即可。可以接受环境配置的两个方法签名是:

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);

如果忽略了环境参数,那么默认环境将会被加载,如下所示:

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, properties);

环境元素定义了如何配置环境。

<environments default="development"><!--默认运行环境的id-->
  <environment id="development"><!--运行环境的id-->
    <transactionManager type="JDBC"><!--事务管理器配置-->
      <property name="..." value="..."/>
    </transactionManager>
    <dataSource type="POOLED"><!--数据源配置-->
      <property name="driver" value="${driver}"/>
      <property name="url" value="${url}"/>
      <property name="username" value="${username}"/>
      <property name="password" value="${password}"/>
    </dataSource>
  </environment>
  <environment id="test"><!--运行环境的id 此为测试环境-->
  </environment>
</environments>

注意这里的关键点:

  • 默认使用的环境 ID(比如:default=“development”)。
  • 每个 environment 元素定义的环境 ID(比如:id=“development”)。
  • 事务管理器的配置(比如:type=“JDBC”)。
  • 数据源的配置(比如:type=“POOLED”)。

默认的环境和环境 ID 是自解释的,因此一目了然。 你可以对环境随意命名,但一定要保证默认的环境 ID 要匹配其中一个环境 ID。

transactionManager

在 MyBatis 中有两种类型的事务管理器(也就是 type=”[JDBC|MANAGED]”):

  • JDBC – 这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。

  • MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。例如:

    <transactionManager type="MANAGED">
      <property name="closeConnection" value="false"/>
    </transactionManager>
    

dataSource

dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。

  • 许多 MyBatis 的应用程序会按示例中的例子来配置数据源。虽然这是可选的,但为了使用延迟加载,数据源是必须配置的。

有三种内建的数据源类型(也就是 type=”[UNPOOLED|POOLED|JNDI]”):

UNPOOLED– 这个数据源的实现只是每次被请求时打开和关闭连接。虽然有点慢,但对于在数据库连接可用性方面没有太高要求的简单应用程序来说,是一个很好的选择。 不同的数据库在性能方面的表现也是不一样的,对于某些数据库来说,使用连接池并不重要,这个配置就很适合这种情形。UNPOOLED 类型的数据源仅仅需要配置以下 5 种属性:

  • driver – 这是 JDBC 驱动的 Java 类的完全限定名(并不是 JDBC 驱动中可能包含的数据源类)。
  • url – 这是数据库的 JDBC URL 地址。
  • username – 登录数据库的用户名。
  • password – 登录数据库的密码。
  • defaultTransactionIsolationLevel – 默认的连接事务隔离级别。

作为可选项,你也可以传递属性给数据库驱动。只需在属性名加上“driver.”前缀即可,例如:

  • driver.encoding=UTF8

这将通过 DriverManager.getConnection(url,driverProperties) 方法传递值为 UTF8encoding 属性给数据库驱动。

POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这是一种使得并发 Web 应用快速响应请求的流行处理方式。

除了上述提到 UNPOOLED 下的属性外,还有更多属性用来配置 POOLED 的数据源:

  • poolMaximumActiveConnections – 在任意时间可以存在的活动(也就是正在使用)连接数量,默认值:10
  • poolMaximumIdleConnections – 任意时间可能存在的空闲连接数。
  • poolMaximumCheckoutTime – 在被强制返回之前,池中连接被检出(checked out)时间,默认值:20000 毫秒(即 20 秒)
  • poolTimeToWait – 这是一个底层设置,如果获取连接花费了相当长的时间,连接池会打印状态日志并重新尝试获取一个连接(避免在误配置的情况下一直安静的失败),默认值:20000 毫秒(即 20 秒)。
  • poolMaximumLocalBadConnectionTolerance – 这是一个关于坏连接容忍度的底层设置, 作用于每一个尝试从缓存池获取连接的线程。 如果这个线程获取到的是一个坏的连接,那么这个数据源允许这个线程尝试重新获取一个新的连接,但是这个重新尝试的次数不应该超过 poolMaximumIdleConnectionspoolMaximumLocalBadConnectionTolerance 之和。 默认值:3 (新增于 3.4.5)
  • poolPingQuery – 发送到数据库的侦测查询,用来检验连接是否正常工作并准备接受请求。默认是“NO PING QUERY SET”,这会导致多数数据库驱动失败时带有一个恰当的错误消息。
  • poolPingEnabled – 是否启用侦测查询。若开启,需要设置 poolPingQuery 属性为一个可执行的 SQL 语句(最好是一个速度非常快的 SQL 语句),默认值:false。
  • poolPingConnectionsNotUsedFor – 配置 poolPingQuery 的频率。可以被设置为和数据库连接超时时间一样,来避免不必要的侦测,默认值:0(即所有连接每一时刻都被侦测 — 当然仅当 poolPingEnabled 为 true 时适用)。

JNDI – 这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。这种数据源配置只需要两个属性:

  • initial_context – 这个属性用来在 InitialContext 中寻找上下文(即,initialContext.lookup(initial_context))。这是个可选属性,如果忽略,那么将会直接从 InitialContext 中寻找 data_source 属性。
  • data_source – 这是引用数据源实例位置的上下文的路径。提供了 initial_context 配置时会在其返回的上下文中进行查找,没有提供时则直接在 InitialContext 中查找。

和其他数据源配置类似,可以通过添加前缀“env.”直接把属性传递给初始上下文。比如:

  • env.encoding=UTF8

这就会在初始上下文(InitialContext)实例化时往它的构造方法传递值为 UTF8encoding 属性。

你可以通过实现接口 org.apache.ibatis.datasource.DataSourceFactory 来使用第三方数据源:

public interface DataSourceFactory {
  void setProperties(Properties props);
  DataSource getDataSource();
}

org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory 可被用作父类来构建新的数据源适配器,比如下面这段插入 C3P0 数据源所必需的代码:

import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;
import com.mchange.v2.c3p0.ComboPooledDataSource;

public class C3P0DataSourceFactory extends UnpooledDataSourceFactory {

  public C3P0DataSourceFactory() {
    this.dataSource = new ComboPooledDataSource();
  }
}
4.6 mappers 元素

mappers:映射器,用来定义SQL映射语句,我们只需要告诉MyBatis去哪里找到这些SQL语句,即去哪里找响应的SQL映射文件。可以使用类路径或者URL等,具体代码如下:

(1) 使用相对于类路径的资源引用

<!-- 使用相对于类路径的资源引用 -->
<mappers>
  <mapper resource="cn/smbms/dao/provider/UserMapper.xml"/>
  <mapper resource="cn/smbms/dao/provider/ProviderMapper.xml"/>
</mappers>

(2) 使用URL获取资源

<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  <mapper url="file:///E:/mappers/UserMapper.xml"/>
</mappers>

(3) 使用映射器接口实现类的完全限定名

<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
  <mapper class="cn.smbms.pojo.UserMapper"/>
</mappers>

(4) 将包内的映射器接口实现全部注册为映射器

<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
  <package name="cn.smbms.dao"/>
</mappers>

返回顶部

5. Java世界的项目构建工具介绍:

5.1 构建工具:

我们要写一个Java程序,一般的步骤也就是编译,测试,打包。这个构建的过程,如果文件比较少,我们可以手动使用java, javac, jar命令去做这些事情。但当工程越来越大,文件越来越多,这个事情就不是那么地令人开心了。因为这些命令往往都是很机械的操作。我们可以把机械的东西交给机器去做。

5.2 Apache Ant:

当我们对代码进行打包的时候要做很多事,比如说配置文件中的用户名和密码,你本地开发和程序实际运行时的内容肯定不一致,所以需要有两个文件,开发的时候用一个,实际运行的时候用一个。这样每次打包的时候都要重复的做这些事,Ant可以让你用xml的形式把这些事情写成脚本,然后自动运行。

Apache Ant,是一个将软件编译、测试、部署等步骤联系在一起加以自动化的一个工具,大多用于 Java 环境中的软件开发。由Apache软件基金会所提供.Ant 也可以有效地用于构建非Java应用程序,例如 C 或 C++ 的应用程序。
在这里插入图片描述

Apache Ant的优点:

  • 跨平台性:Apache Ant使用java语言编写,因此具有很好的跨平台性。
  • 操作简单:Apache Ant的运行需要一个XML配置文件。这个XML配置文件定义了一系列的构建过程,每一个构建过程包含一个或多个操作。由于XML的特性,构建过程很容易维护和书写,而且结构很清晰。
  • 功能丰富、容易扩展:Apache Ant内置了多个任务,此外还包括许多可选的任务,这些任务囊括了构建过程中的大多数操作。在这些任务都不能满足构建需求时,还可以根据需要自定义任务。

Apache Ant的缺点:

  • Ant的编译以及所有的脚本完全是自定义的,没有一个统一的基础
  • Ant导入的所有的jar包,有的无法确定其版本号
  • Ant需要自己定义jar包的位置,发布的时候需要把所有的包一起发布

目前已经处于被淘汰的边缘

5.3 Apache Maven:

在这里插入图片描述

Maven 是一个项目管理工具,可以对 Java 项目进行构建、依赖管理。官网:https://maven.apache.org/。入门请参考第6小节

5.4 Apache Gradle:

在这里插入图片描述

Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了基于XML的各种繁琐配置。面向Java应用为主。当前其支持的语言限于Java、Groovy、Kotlin和Scala,计划未来将支持更多的语言。

Gradle提供了什么

  1. 一种可切换的,像maven一样的基于约定的构建框架,却又从不锁住你(约定优于配置)

  2. 强大的支持多工程的构建

  3. 强大的依赖管理(基于Apache Ivy),提供最大的便利去构建你的工程

  4. 全力支持已有的Maven或者Ivy仓库基础建设

  5. 支持传递性依赖管理,在不需要远程仓库和pom.xml和ivy配置文件的前提下

  6. 基于groovy脚本构建,其build脚本使用groovy语言编写

  7. 具有广泛的领域模型支持你的构建

5.5 总结三种工具:

  • Ant可以自动化打包逻辑。
  • Maven也可以自动化打包,相比于Ant,它多做的事是帮你下载jar包。
    但是Maven的打包逻辑太死板,定制起来太麻烦,不如Ant好用。
  • Gradle就是又能自动下jar包,又能自己写脚本,并且脚本写起来还比Ant好用的这么个东西

6. Maven 简单教程

6.1 Maven介绍:

Maven 翻译为"专家"、“内行”,是 Apache 下的一个纯 Java 开发的开源项目。基于项目对象模型(缩写:POM)概念,Maven利用一个中央信息片断能管理一个项目的构建、报告和文档等步骤。

Maven 是一个项目管理工具,可以对 Java 项目进行构建、依赖管理。

Maven 也可被用于构建和管理各种项目,例如 C#,Ruby,Scala 和其他语言编写的项目。Maven 曾是 Jakarta 项目的子项目,现为由 Apache 软件基金会主持的独立 Apache 项目。

简单的说Maven就是帮我们下载jar包、并且通过配置xml文件使jar包能被我们的Java代码引用的一个工具

6.2 Maven的功能:

Maven 能够帮助开发者完成以下工作:

  • 构建
  • 文档生成
  • 报告
  • 依赖
  • 发布
  • 分发
  • 邮件列表

6.3 约定配置

Maven 提倡使用一个共同的标准目录结构,Maven 使用约定优于配置的原则,大家尽可能的遵守这样的目录结构。如下所示:

目录目的
${basedir}存放pom.xml和所有的子目录
${basedir}/src/main/java项目的java源代码
${basedir}/src/main/resources项目的资源,比如说property文件,springmvc.xml
${basedir}/src/test/java项目的测试类,比如说Junit代码
${basedir}/src/test/resources测试用的资源
${basedir}/src/main/webapp/WEB-INFweb应用文件目录,web项目的信息,比如存放web.xml、本地图片、jsp视图页面
${basedir}/target打包输出目录
${basedir}/target/classes编译输出目录
${basedir}/target/test-classes测试编译输出目录
Test.javaMaven只会自动运行符合该命名规则的测试类
~/.m2/repositoryMaven默认的本地仓库目录位置

6.4 Maven 特点:

Maven 特点如下:

  • 项目设置遵循统一的规则。
  • 任意工程中共享。
  • 依赖管理包括自动更新。
  • 一个庞大且不断增长的库。
  • 可扩展,能够轻松编写 Java 或脚本语言的插件。
  • 只需很少或不需要额外配置即可即时访问新功能。
  • 基于模型的构建 − Maven能够将任意数量的项目构建到预定义的输出类型中,如 JAR,WAR 或基于项目元数据的分发,而不需要在大多数情况下执行任何脚本。
  • 项目信息的一致性站点 − 使用与构建过程相同的元数据,Maven 能够生成一个网站或PDF,包括您要添加的任何文档,并添加到关于项目开发状态的标准报告中。
  • 发布管理和发布单独的输出 − Maven 将不需要额外的配置,就可以与源代码管理系统(如 Subversion 或 Git)集成,并可以基于某个标签管理项目的发布。它也可以将其发布到分发位置供其他项目使用。Maven 能够发布单独的输出,如 JAR,包含其他依赖和文档的归档,或者作为源代码发布。
  • 向后兼容性 − 您可以很轻松的从旧版本 Maven 的多个模块移植到 Maven 3 中。
  • 子项目使用父项目依赖时,正常情况子项目应该继承父项目依赖,无需使用版本号,
  • 并行构建 − 编译的速度能普遍提高20 - 50 %。
  • 更好的错误报告 − Maven 改进了错误报告,它为您提供了 Maven wiki 页面的链接,您可以点击链接查看错误的完整描述。

Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。

当你使用Maven的时候,你用一个明确定义的项目对象模型来描述你的项目,然后Maven可以应用横切的逻辑,这些逻辑来自一组共享的(或者自定义的)插件。

Maven 有一个生命周期,当你运行 mvn install 的时候被调用。这条命令告诉 Maven 执行一系列的有序的步骤,直到到达你指定的生命周期。遍历生命周期旅途中的一个影响就是,Maven 运行了许多默认的插件目标,这些目标完成了像编译和创建一个 JAR 文件这样的工作。

此外,Maven能够很方便的帮你管理项目报告,生成站点,管理JAR文件,等等。

6.5 Maven常用命令

mvn archetype:generate 创建Maven项目

mvn compile 编译源代码

mvn deploy 发布项目

mvn test-compile 编译测试源代码

mvn test 运行应用程序中的单元测试

mvn site 生成项目相关信息的网站

mvn clean 清除项目目录中的生成结果

mvn package 根据项目生成的jar

mvn install 在本地Repository中安装jar

mvn eclipse:eclipse 生成eclipse项目文件

mvn jetty:run 启动jetty服务

mvn tomcat:run 启动tomcat服务

mvn clean package -Dmaven.test.skip=true:清除以前的包后重新打包,跳过测试类

6.6 Maven生命周期

maven 对项目构建过程分为三套相互独立的生命周期,请注意这里说的是“三套”,而且“相互独立”, 这三套生命周期分别是*

  • Clean Lifecycle 在进行真正的构建之前进行一些清理工作。
  • Default Lifecycle 构建的核心部分,编译,测试,打包,部署等等。
  • Site Lifecycle 生成项目报告,站点,发布站点。

6.7 pom基本配置

pom.xml 是 Maven 项目的核心配置文件,位于每个工程的根目录,基本配置如下:

<project>:文件的根节点 。

<modelversion>: pom.xml 使用的对象模型版本

<groupId>:项目名称,一般写项目的域名

<artifactId>:模块名称,子项目名或模块名称

<version>:产品的版本号 .

<packageing>:打包类型,一般有 jar、war、pom 等

<name>:项目的显示名,常用于 Maven 生成的文档。

<description>:项目描述,常用于 Maven 生成的文档

<dependencies>:项目依赖构件配置,配置项目依赖构件的坐标

<build>:项目构建配置,配置编译、运行插件等。

7. 扩展maven插件:

关于定义编译java代码的插件可以在pom.xml文件中的<build></build>中加入以下内容:

<build>
    <plugins>
        <!--定义maven处理资源文件的插件-->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <version>3.1.0</version>
            <configuration>
                <encoding>utf-8</encoding>
            </configuration>
        </plugin>
        <!--定义maven编译java代码的插件-->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <compilerVersion>1.8</compilerVersion>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>utf-8</encoding>
            </configuration>
        </plugin>    
    </plugins>
</build>

更多插件请参照maven 官方网址 : http://maven.apache.org/pom.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值