由于build()方法中的参数environment和properties都可以为null,所以SqlSessionFactoryBuilder构建SqlSessionFactory对象的build()方法按照配置信息的传入方式,可以分为三种形式。
形式一:SqlSessionFactoryBuilder构建build()方法
build(InputStream inputStream,String environment,Properties properties)
上述build()方法中,参数inputStream是字节流,它封装了XML文件形式的配置信息;参数environment和参数properties为可选参数。其中,参数environment决定将要加载的环境,包括数据源和事务管理器;参数properties决定将要加载的properties文件。
形式二:SqlSessionFactoryBuilder构建build()方法
build(Reader reader,String environment,Properties properties)
由上述build()方法可知,第二种形式的build()方法参数作用与第一种形式大体一致,唯一不同的是,第一种形式的build()方法使用InputStream字节流封装了XML文件形式的配置信息,而第二种形式的build()方法使用Reader字符流封装了xml文件形式的配置信息。
形式三:SqlSessionFactoryBuilder构建build()方法
build(Configuration config)
通过以上代码可知,配置信息可以通过InputStream(字节流)、Reader(字符流)、Configuration(类)三种形式提供给SqlSessionFactoryBuilder的build()方法。
通过过读取XML配置文件的方式构造SqlSessionFactory对象的关键代码如下所示。
// 读取配置文件 InputStream inputStream = Resources.getResourceAsStream(“配置文件位置”);
// 根据配置文件构建 SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSessionFactory对象是线程安全的,它一旦被创建,在整个应用程序执行期间都会存在。如果我们多次创建同一个数据库的SqlSessionFactory对象,那么该数据库的资源将很容易被耗尽。通常每一个数据库都只创建一个SqlSessionFactory对象,所以在构建SqlSessionFactory对象时,建议使用单例模式。
SqlSessionFactory的openSession()方法
openSession(ExecutorType execType)参数值
参数execType有三个可选值:
ExecutorType.SIMPLE:表示为每条语句创建一条新的预处理语句。
ExecutorType.REUSE:表示会复用预处理语句。
ExecutorType.BATCH:表示会批量执行所有更新语句。
openSession(ExecutorType execType,Boolean autoCommit)参数值
参数execType有三个可选值,同openSession(ExecutorType execType)的参数。
参数autoCommit可设置是否开启事务。
openSession(ExecutorType execType,Connection connection)参数值
参数execType有三个可选值,同openSession(ExecutorType execType)的参数。
参数connection可提供自定义连接。
SqlSession是MyBatis框架中另一个重要的对象,它是应用程序与持久层之间执行交互操作的一个单线程对象,主要作用是执行持久化操作,类似于JDBC中的Connection。SqlSession对象包含了执行SQL操作的方法,由于其底层封装了JDBC连接,所以可以直接使用SqlSession对象来执行已映射的SQL语句。
每一个线程都应该有一个自己的SqlSession对象,并且该对象不能共享。SqlSession对象是线程不安全的,因此其使用范围最好在一次请求或一个方法中,绝不能将其放在类的静态字段、对象字段或任何类型的管理范围(如Servlet的HttpSession)中使用。SqlSession对象使用完之后,要及时的关闭,SqlSession对象通常放在finally块中关闭,代码如下所示。
元素是整个XML配置文件的根元素,相当于MyBatis各元素的管理员。有很多子元素,MyBatis的核心配置就是通过这些子元素完成的。需要注意的是,在核心配置文件中,的子元素必须按照上图由上到下的顺序进行配置,否则MyBatis在解析XML配置文件的时候会报错。
是一个配置属性的元素,该元素的作用是读取外部文件的配置信息。 假设现在有一个配置文件db.properties,该文件配置了数据库的连接信息,具体如下:
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root
如果想获取数据库的连接信息,可以在 MyBatis 的核心配置文件 mybatis-config.xml 中使用元素先引入 db.properties 文件,具体代码:
<properties resource="db.properties" />
引入 db.properties 文件后,如果希望动态获取 db.properties
文件中的数据库连接信息,可以使用元素配置,示例代码如下:
<dataSource type="POOLED">
<!-- 数据库驱动 -->
<property name="driver" value="${jdbc.driver}" />
<!-- 连接数据库的url -->
<property name="url" value="${jdbc.url}" />
<!-- 连接数据库的用户名 -->
<property name="username" value="${jdbc.username}" />
<!-- 连接数据库的密码 -->
<property name="password" value="${jdbc.password}" />
</dataSource>
db.properties文件实现动态参数配置
完成上述配置后,元素中连接数据库的 4个属性(driver、url、username 和 password)值将会由db.properties 文件中对应的值来动态替换。这样一来,元素就可以通过 db.properties 文件实现动态参数配置。
元素中的常见配置参数
元素中常见配置参数的使用方式
<settings>
<!-- 是否开启缓存 -->
<setting name="cacheEnabled" value="true" />
<!-- 是否开启延迟加载,如果开启,所有关联对象都会延迟加载 -->
<setting name="lazyLoadingEnabled" value="true" />
<!-- 是否开启关联对象属性的延迟加载,如果开启,对任意延迟属性的调用都
会使用带有延迟加载属性的对象向完整加载,否则每种属性都按需加载 -->
<setting name="aggressiveLazyLoading" value="true" />
...
</settings>
核心配置文件若要引用一个POJO实体类,需要输入POJO实体类的全限定类名,而全限定类名比较冗长,如果直接输入,很容易拼写错误。例如,POJO实体类User的全限定类名是com.itheima.pojo.User,未设置别名之前,映射文件的select语句块若要引用POJO类User,必须使用其全限定类名,引用代码如下。
<select id="findById" parameterType="int" resultType="com.itheima.pojo.User">
select * from users where uid = #{id}
</select>
多个全限定类设置别名的方式
方式一:在
<typeAliases>
<typeAlias alias=“Usertype="com.itheima.pojo.User"/>
<typeAlias alias="Student" type="com.itheima.pojo.Student"/>
<typeAlias alias="Employee" type="com.itheima.pojo.Employee"/>
<typeAlias alias="Animal" type="com.itheima.pojo.Animal"/>
</typeAliases>
方式二:通过自动扫描包的形式自定义别名。
<typeAliases>
<package name="com.itheima.pojo"/>
</typeAliases>
常见Java类型的默认别名问题
除了可以使用元素为实体类自定义别名外,MyBatis框架还为许多常见的Java类型(如数值、字符串、日期和集合等)提供了相应的默认别名。例如别名_byte映射类型byte、_long映射类型long等,别名可以在MyBatis中直接使用,但由于别名不区分大小写,所以在使用时要注意重复定义的覆盖问题。
元素配置运行环境
MyBatis可以配置多套运行环境,如开发环境、测试环境、生产环境等,我们可以灵活选择不同的配置,从而将SQL映射到不同运行环境的数据库中。不同的运行环境可以通过元素来配置,但不管增加几套运行环境,都必须要明确选择出当前要用的唯一的一个运行环境。
各元素配置运行环境
MyBatis的运行环境信息包括事务管理器和数据源。在MyBatis的核心配置文件中,MyBatis通过元素定义一个运行环境。元素有两个子元素, 元素和 元素>。 元素用于配置运行环境的事务管理器; 元素用于配置运行环境的数据源信息。
使用
元素进行配置的示例代码
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" /><!—设置使用JDBC事务管理 -->
<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>
元素配置事务管理器
在MyBatis中,元素可以配置两种类型的事务管理器,分别是JDBC和MANAGED。
JDBC:此配置直接使用JDBC的提交和回滚设置,它依赖于从数据源得到的连接来管理事务的作用域。
MANAGED:此配置不提交或回滚一个连接,而是让容器来管理事务的整个生命周期。默认情况下,它会关闭连接,但可以将元素的closeConnection属性设置为false来阻止它默认的关闭行为。
1.UNPOOLED
UNPOOLED表示数据源为无连接池类型。配置此数据源类型后,程序在每次被请求时会打开和关闭数据库连接。UNPOOLED适用于对性能要求不高的简单应用程。UNPOOLED类型的数据源需要配置5种属性。
UNPOOLED数据源需要配置的属性
2.POOLED
POOLED表示数据源为连接池类型。POOLED数据源利用“池”的概念将JDBC连接对象组织起来,节省了在创建新的连接对象时需要初始化和认证的时间。POOLED数据源使得并发Web应用可以快速的响应请求,是当前比较流行的数据源配置类型。
POOLED数据源可额外配置的属性
3.JNDI数据源
JNDI 表示数据源可以在 EJB 或应用服务器等容器中使用。JNDI数据源需要配置的属性如下所示。
元素作用
在MyBatis的核心配置文件中,元素用于引入MyBatis映射文件。映射文件包含了POJO对象和数据表之间的映射信息,MyBatis通过核心配置文件中的元素找到映射文件并解析其中的映射信息。通过元素引入映射文件的方法有4种。
a.使用类路径引入
使用类路径引入映射文件的示例代码如下所示。
<mappers>
<mapper resource="com/itheima/mapper/UserMapper.xml"/>
</mappers>
b.使用本地文件路径引入
使用本地文件路径引入映射文件的示例代码如下所示。
<mappers>
<mapper url="file:///D:/com/itheima/mapper/UserMapper.xml"/>
</mappers>
c.使用接口类引入
使用接口类引入映射文件的示例代码如下所示。
<mappers>
<mapper class="com.itheima.mapper.UserMapper"/>
</mappers>
d.使用包名引入
使用包名引入映射文件的示例代码如下所示。
<mappers>
<package name="com.itheima.mapper"/
</mappers>
元素中namespace属性作用
<!—查询操作 -->
<select id="findUserById" parameterType="Integer"
resultType="com.itheima.pojo.User">
select * from users where id = #{id}
</select>
元素用于映射插入语句,在执行完元素中定义的SQL语句后,会返回插入记录的数量。使用
元素执行插入操作非常简单,示例代码如下:
<!—插入操作 --><insert id="addUser" parameterType="com.itheima.pojo.User">
insert into users(uid,uname,uage)values(#{uid},#{uname},#{uage})
</insert>
数据库获取主键值的方式
元素用于映射更新语句,它可以更新数据库中的数据。在执行完元素中定义的SQL语句后,会返回更新的记录数量。使用元素执行更新操作非常简单,示例代码如下:
<!—更新操作 -->
<update id="updateUser" parameterType="com.itheima.pojo.User">
update users set uname= #{uname},uage = #{uage} where uid = #{uid} </update>
元素用于映射删除语句,在执行完元素中的SQL语句之后,会返回删除的记录数量。使用元素执行删除操作非常简单,示例代码如下所示:
<!-- 删除操作 -->
<delete id="deleteUser" parameterType="Integer">
delete from users where uid=#{uid}
</delete>
元素中,除了上述示例代码中的几个属性外,还有其他一些可以配置的属性,如flushCache、timeout等。
在一个映射文件中,通常需要定义多条SQL语句,这些SQL语句的组成可能有一部分是相同的(如多条select语句中都查询相同的id、username字段),如果每一个SQL语句都重写一遍相同的部分,势必会增加代码量。针对此问题,可以在映射文件中使用MyBatis所提供的、
元素,将这些SQL语句中相同的组成部分抽取出来,然后在需要的地方引用。\ 元素的作用是定义可重用的SQL代码片段,它可以被包含在其他语句中。 元素可以被静态地(在加载参数时)参数化, 元素不同的属性值通过包含的对象发生变化。
实现一个根据客户id查询客户信息的SQL片段
<!--定义要查询的表 -->
<sql id=“someinclude">from { include_target}" /></sql>
<!--定义查询列 --><sql id=“userColumns"> uid,uname,uage </sql>
<!--根据客户id查询客户信息 -->
<select id="findUserById" parameterType="Integer"
resultType="com.itheima.pojo.User"> select
<include refid="userColumns"/>
<include refid="someinclude">
<property name="include_target" value="users" /></include>
where uid = #{uid}
</select>
元素表示结果映射集,是MyBatis中最重要也是功能最强大的元素。元素主要作用是定义映射规则、更新级联以及定义类型转化器等。数据表中的列和需要返回的对象的属性可能不会完全一致,这种情况下MyBatis不会自动赋值,这时就需要使用元素进行结果集映射。
员工表详情
案例要求
创建建一个名称为mybatisdemo的项目,并在项目中引入 MySQL 驱动包、 JUnit 测试包、MyBatis
的核心包等相关依赖、创建数据库连接信息配置文件、创建 MyBatis 的核心配置文件。核心配置文件的内容如下。
<configuration><properties resource="db.properties"/>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${mysql.driver}" />
<property name="url" value="${mysql.url}" />
<property name="username" value="${mysql.username}" />
<property name="password" value="${mysql.password}" />
</dataSource>
</environment></environments>
</configuration>
在mybatis数据库中创建employee表,并在employee表中插入几条数据。
use mybatis;
create table employee(
id int primary key auto_increment,
name varchar(20) not null,
age int not null,
position varchar(20) );
insert into employee(id,name,age,position) values(null,'张三',20,'员工‘),
(null,'李四',18, '员工'),(null,'王五',35,'经理');
创建持久化类Employee,并在类中声明id(编号)、name(姓名)、age(年龄)和position(职位)属性,以及属性对应的getter/setter方法。
public class Employee {
private Integer id; private String name;
private Integer age;
private String position;
// 省略getter/setter方法
@Override
public String toString() {
return "Employee{" + "id=" + id + ", name=" + name +
", age=" + age + ", position=" + position +'}’;
}}
创建映射文件EmployeeMapper.xml,该文件主要用于实现SQL语句和Java对象之间的映射,部分文件内容如下。
<mapper namespace="com.itheima.mapper.EmployeeMapper">
<select id="findById"parameterType="Integer”
resultType="com.itheima.pojo.Employee"> select * from employee where id = #{id}
</select>
<insert id="addEmployee" parameterType="com.itheima.pojo.Employee">
insert into employee(id,name,age,position)values
(#{id},#{name},#{age},#{position})
</insert> </mapper>
在mybatis-config.xml映射文件的元素下添加EmployeeMapper.xml映射文件路径的配置,用于将EmployeeMapper.xml映射文件加载到程序中。
<mapper
resource="com/itheima/mapper/EmployeeMapper.xml">
</mapper>
创建MyBatisUtils工具类,该类用于封装读取配置文件信息的代码。
public class MyBatisUtils {
private static SqlSessionFactory sqlSessionFactory = null;
static { try {
// 使用MyBatis提供的Resources类加载MyBatis的配置文件
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
// 构建SqlSessionFactory工厂
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (Exception e) { e.printStackTrace();}}
public static SqlSession getSession() {//获取SqlSession对象的静态方法
return sqlSessionFactory.openSession();}
}
(1)在项目src/test/java目录下创建Test包,在Test包下创建MyBatisTest测试类,用于程序测试。在MyBatisTest测试类中添加findByIdTest()方法,用于根据id查询员工信息。
(2)在MyBatisTest测试类中添加insertEmployeeTest()方法,用于插入员工信息。
(3)在MyBatisTest测试类中添加updateEmployeeTest()方法,用于更新员工信息。
(4)在MyBatisTest测试类中添加deleteEmployeeTest()方法,用于删除员工信息。