Mybatis_day01

时间:2022-05-04
本文章向大家介绍Mybatis_day01,主要内容包括前言、Jdbc演变到mybatis、一. Mybatis简介、二.mybatis入门、三.Mybatis的Dao开发、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

Mybatis_day01

前言

Jdbc演变到mybatis

jdbc

jdbc编程

publicstaticvoid main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//通过驱动管理类获取数据库链接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "mysql");
//定义sql语句 ?表示占位符
String sql = "select * from user where username = ?";
//获取预处理statement
preparedStatement = connection.prepareStatement(sql);
//设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
preparedStatement.setString(1, "王五");
//向数据库发出sql执行查询,查询出结果集
resultSet = preparedStatement.executeQuery();
//遍历查询结果集
while(resultSet.next()){
System.out.println(resultSet.getString("id")+" "+resultSet.getString("username"));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//释放资源
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(preparedStatement!=null){
try {
preparedStatement.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

上述jdbc查询未经封装,原生态的查询方式

jdbc编程步骤

1.加载数据库驱动

2.创建并获取数据源连接

3.创建jdbc的statement对象

4.设置sql语句

5.设置statement中的sql参数(statement的参数注入)

6.statement执行sql语句

7.对sql执行结果进行解析处理

8.释放资源(statement,connection,resultSet)

jdbc演变到mybatis

上面我们看到了实现JDBC有七个步骤,哪些步骤是可以进一步封装的,减少我们开发的代码量

第一步优化:连接获取和释放

问题描述:

数据库连接频繁的开启和关闭本身就造成了资源的浪费,影响系统的性能。

解决问题:

数据库连接的获取和关闭我们可以使用数据库连接池来解决资源浪费的问题。通过连接池就可以反复利用已经建立的连接去访问数据库了。减少连接的开启和关闭的时间。

问题描述:

但是现在连接池多种多样,可能存在变化,有可能采用DBCP的连接池,也有可能采用容器本身的JNDI数据库连接池。

解决问题:

我们可以通过DataSource进行隔离解耦,我们统一从DataSource里面获取数据库连接,DataSource具体由DBCP实现还是由容器的JNDI实现都可以,所以我们将DataSource的具体实现通过让用户配置来应对变化。

第二步优化:SQL统一存取

问题描述:

我们使用JDBC进行操作数据库时,SQL语句基本都散落在各个JAVA类中,这样有三个不足之处:

第一,可读性很差,不利于维护以及做性能调优。

第二,改动Java代码需要重新编译、打包部署。

第三,不利于取出SQL在数据库客户端执行(取出后还得删掉中间的Java代码,编写好的SQL语句写好后还得通过+号在Java进行拼凑)。

解决问题:

我们可以考虑不把SQL语句写到Java代码中,那么把SQL语句放到哪里呢?首先需要有一个统一存放的地方,我们可以将这些SQL语句统一集中放到配置文件或者数据库里面(以key-value的格式存放)。然后通过SQL语句的key值去获取对应的SQL语句。

既然我们将SQL语句都统一放在配置文件或者数据库中,那么这里就涉及一个SQL语句的加载问题。

第三步优化:传入参数映射和动态SQL

问题描述:

很多情况下,我们都可以通过在SQL语句中设置占位符来达到使用传入参数的目的,这种方式本身就有一定局限性,它是按照一定顺序传入参数的,要与占位符一一匹配。但是,如果我们传入的参数是不确定的(比如列表查询,根据用户填写的查询条件不同,传入查询的参数也是不同的,有时是一个参数、有时可能是三个参数),那么我们就得在后台代码中自己根据请求的传入参数去拼凑相应的SQL语句,这样的话还是避免不了在Java代码里面写SQL语句的命运。既然我们已经把SQL语句统一存放在配置文件或者数据库中了,怎么做到能够根据前台传入参数的不同,动态生成对应的SQL语句呢?

第四步优化:结果映射和结果缓存

问题描述:

执行SQL语句、获取执行结果、对执行结果进行转换处理、释放相关资源是一整套下来的。假如是执行查询语句,那么执行SQL语句后,返回的是一个ResultSet结果集,这个时候我们就需要将ResultSet对象的数据取出来,不然等到释放资源时就取不到这些结果信息了。我们从前面的优化来看,以及将获取连接、设置传入参数、执行SQL语句、释放资源这些都封装起来了,只剩下结果处理这块还没有进行封装,如果能封装起来,每个数据库操作都不用自己写那么一大堆Java代码,直接调用一个封装的方法就可以搞定了。

解决问题:

我们分析一下,一般对执行结果的有哪些处理,有可能将结果不做任何处理就直接返回,也有可能将结果转换成一个JavaBean对象返回、一个Map返回、一个List返回等等,结果处理可能是多种多样的。从这里看,我们必须告诉SQL处理器两点:第一,需要返回什么类型的对象;第二,需要返回的对象的数据结构怎么跟执行的结果映射,这样才能将具体的值copy到对应的数据结构上。

接下来,我们可以进而考虑对SQL执行结果的缓存来提升性能。缓存数据都是key-value的格式,那么这个key怎么来呢?怎么保证唯一呢?即使同一条SQL语句几次访问的过程中由于传入参数的不同,得到的执行SQL语句也是不同的。那么缓存起来的时候是多对。但是SQL语句和传入参数两部分合起来可以作为数据缓存的key值。

第五步优化:解决重复SQL语句问题

问题描述:

由于我们将所有SQL语句都放到配置文件中,这个时候会遇到一个SQL重复的问题,几个功能的SQL语句其实都差不多,有些可能是SELECT后面那段不同、有些可能是WHERE语句不同。有时候表结构改了,那么我们就需要改多个地方,不利于维护。

解决问题:

当我们的代码程序出现重复代码时怎么办?将重复的代码抽离出来成为独立的一个类,然后在各个需要使用的地方进行引用。对于SQL重复的问题,我们也可以采用这种方式,通过将SQL片段模块化,将重复的SQL片段独立成一个SQL块,然后在各个SQL语句引用重复的SQL块,这样需要修改时只需要修改一处即可。

优化总结:

我们总结一下上面对JDBC的优化和封装:

(1) 使用数据库连接池对连接进行管理

(2) SQL语句统一存放到配置文件

(3) SQL语句变量和传入参数的映射以及动态SQL

(4) 动态SQL语句的处理

(5) 对数据库操作结果的映射和结果缓存

(6) SQL语句的重复

一. Mybatis简介

1.什么是mybatis

myBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,实质上Mybatis对ibatis进行一些改进。

MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。

Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

Mybatis就是一个持久层的框架,是对jdbc的封装

2.mybatis架构设计

2.1.架构设计图

2.2.开发设计图

l mybatis配置

SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。

mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。

l 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂

l 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。

l mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。

l Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。

l Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。

l Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。

二.mybatis入门

1.需求

根据用户ID(主键)进行查询用户信息

根据用户名称模糊查询用户信息

添加用户

删除用户

更新用户

2.环境

Java环境:jdk1.7.0_72

Eclipse:kepler

Mysql:5.5

mybaits的代码由github.com管理,地址:https://github.com/mybatis/mybatis-3/releases

mybatis-3.2.7.jar----mybatis的核心包

lib----mybatis的依赖包

mybatis-3.2.7.pdf----mybatis使用手册

3.创建mysql数据库

先导入sql_table.sql,再导入 sql_data.sql脚本:

如下:

4.mybatis入门程序

4.1.环境准备

4.1.1.创建一个Java工程

4.1.2.导入jar文件

4.1.3.log4j日志

4.1.4.创建sqlMapConfig.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>
<!-- 初始化环境,和spring整合以后,这个将会被废除 -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc管理事务,事务控制是由mybatis来执行 -->
<transactionManager type="JDBC"/>
<!-- 数据源 也是由mybatis来进行管理-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="admin"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 引入映射文件 -->
<!-- <mapper resource="org/mybatis/example/BlogMapper.xml"/> -->
</mappers>
</configuration>

sqlMapConfig是mybatis的核心配置文件,包含数据源,事务管理等等

4.1.5.创建PO类

4.2.根据ID查询用户

4.2.1.准备Mapper映射文件

在classpath下sqlMap里面创建映射文件User.xml(此名称可以任意定义)

但是:在mybatis代理开发时,必须命名XXXMapper.xml这样的样式

测试开发:使用普通模式进行开发、定义user.xml

User.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">
<!-- namespace是命名空间,用来隔离sql语句,可以随意定义,
注意:在使用代理时具有特殊的约定含义,不能随意定义 -->
<mapper namespace="test">
</mapper>

Namespace:命名空间 用来隔离sql语句,在mybatis代理模式具有特殊的含义

详细的mapper文件如下:

<?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">
<!-- namespace是命名空间,用来隔离sql语句,可以随意定义,
注意:在使用代理时具有特殊的约定含义,不能随意定义 -->
<mapper namespace="test">
<!-- 首先明确:mybatis的所有sql语句都存放在xml的映射文件中,也就是说有多个sql -->
<!-- id:id就是我们唯一标识一个sql语句的地址
mybatis会将sql语句封装到mappedStatement对象中,id就是statement的id
注意:我们需要根据ID进行查询,需要接受参数使用parameterType进行接受参数
#,$都用来接受参数,就是占位符接受参数,注意:如果传递的是基本类型的参数,#{??}里面可以任意
parameterType:传递参数
resultType:结果集映射 -->
<select id="selectUserByID" parameterType="int" resultType="cn.itcast.bean.User">
select * from user where id=#{id}
</select>
</mapper>

4.2.2.ID查询测试类

测试代码:

publicclass MybatisTest {
private SqlSessionFactory sessionFactory;
@Before
publicvoid createSessionFactory() throws Exception{
String res="sqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(res);
sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
publicvoid test02(){
//获取Session
SqlSession session = sessionFactory.openSession();
User user = session.selectOne("test.selectUserByID", 1);
System.out.println(user);
session.close();
}
@Test
publicvoid test01() throws Exception{
String resources="sqlMapConfig.xml";
//读取文件资源流
InputStream inputStream = Resources.getResourceAsStream(resources);
//创建一个SessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//获取Session
SqlSession session = sessionFactory.openSession();
User user = session.selectOne("test.selectUserByID", 1);
System.out.println(user);
session.close();
}
}

4.3.根据姓名username模糊查询

4.3.1.映射文件

<!--需求:根据用户姓名进行模糊查询,可能返回多条记录
resultType:指定返回单条记录,映射成Java单个对象
${}拼接sql语句,对参数不加任何修饰的拼接在sql语句中
${value}:如果传入的参数类型是基本类型,那么${}内只能是value -->
<select id="selectUserByUsername" parameterType="string" resultType="cn.itcast.bean.User">
select * from user where username like '%${value}%'
</select>

4.3.2.测试代码模糊查询

@Test
publicvoid selectUserByUsername(){
SqlSession session = sessionFactory.openSession();
//第一个参数:statement的id,根据id找到需要执行的sql
//第二个参数:指定匹配parameterType的参数类型
List<User> list = session.selectList("test.selectUserByUsername", "张");
System.out.println(list);
}

4.4.#,$

#{}表示一个占位符,通过#{}可以实现preparedStatement向占位符中设置值,自动进行Java

类型和jdbc类型转换,#{}可以有效防止sql注入。#{}可以接受简单类型值或pojo属性值。

如果parameterType传输单个类型的值,#{}括号中可以是value或者其他任意值。

${}表示拼接sql串,通过${}可以通过patameterType传入的内容拼接在sql中且不进行jdbc类型转换。${}可以接受简单类型值或pojo属性值,如果parameterType传输单个类型值,${}括号中只能是value.

4.5.parameterType和resultType

patameterType:指定传递参数类型,mybatis通过ognl获取参数拼接在sql语句中

resultType:指定返回结果类型,mybatis可以把查询结果封装成Java对象,这里就是把结果集映射成resultType指定的对象。

4.6.selectOne和selectList

selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常:

org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)

selectList可以查询一条或多条记录。

5.添加

5.1.映射文件(user.xml)

<!-- parameterType:指定输入参数类型pojo,就是javabean对象
#{}口号中是Javabean的属性名,mybatis通过ognl来获取javabean的属性值 -->
<insert id="insertUser" parameterType="cn.itcast.bean.User">
<!--使用sql函数生成主键ID 注意:mysql主键是在执行完成insert语句后才增加主键,所以使用after -->
<selectKey keyProperty="id" order="AFTER" resultType="int">
SELECT LAST_INSERT_ID()
</selectKey>
insert into user(id,username,birthday,sex,address)
values(#{id},#{username},#{birthday},#{sex},#{address})
</insert>

Mysql自增主键返回:

selectKey实现自增主键返回:

keyProperty:返回值对应pojo里面的那个属性。

Order:表示id生成的顺序,由于mysql主键生成是在sql语句执行之后在进行设置,所以我们设置成after。

ResultType:主键返回类型

LAST_INSERT_ID()是mysql函数,返回auto_increament自增id值

也可以使用useGeneratedKeys来返回主键

5.2.添加测试代码

@Test
publicvoid test01() throws Exception{
SqlSession sqlSession = sessionFactory.openSession();
User user = new User();
user.setUsername("张三");
user.setSex("男");
user.setBirthday(new Date());
user.setAddress("陕西");
sqlSession.insert("test.insertUser", user);
System.out.print(user.getId);//使用last_insert_Id返回ID
sqlSession.commit();
sqlSession.close();
}

5.3.mysql使用uuid实现主键自增

注意:mysql的uuid生成必须在执行insert之前进行,因为后面需要获取uuid的属性值进行表的插入。

5.4.oracle的自增序列

Oracle序列的自定义方法:

注意:oracle自增主键是序列化自增类型。需要before

6.删除

6.1.映射文件

6.2.删除测试

@Test
publicvoid deleteUserByID(){
SqlSession session = sessionFactory.openSession();
//删除单表,没有外键关联才能被删除
session.delete("test.deleteUserByID", 32);
session.commit();
session.close();
}

7.修改

7.1.映射文件

7.2.修改测试

7.3.测试结果

8.总结

8.1.parameterType

指定传递参数类型,前台传入参数和后台获取参数类型必须匹配

8.2.resultType

指定返回值类型,执行sql结果映射Java对象

8.3.#和$

#{}表示一个占位符,#{}接受传入参数,类型可以是基本类型,pojo,map

如果接受的是基本类型的值,那么#{}括号中可以任意或者value

如果#{}获取是的pojo,mybatis通过ognl获取参数值。Ognl就是对象导航语言 属性.属性.属性的方式获取值。

如果传递是map值,#{}中需要的是map的key

${}表示拼接sql,会引入sql注入,不建议使用

${}接受输入参数可以是pojo,基本类型,map

${}如果接受的是基本类型,只能是value

${}接受pojo类型的参数,通过ognl对象导航进行获取

8.4.selectOne和selectList

selectOne是查询单个对象记录,selectList查询多条记录

不能使用selectOne查询selectList的记录

8.5.mybatis和hibernate区别

Hibernate:hibernate是一个标准的ORM框架,不需要写sql语句,维护关系比叫复杂,sql语句自动生成,对sql语句优化,修改比较困难。

Hibernate的优缺点:

优点:面向对象开发,不需要自己写sql语句。如果进行数据库迁移不需要修改sql语句,只需要修改一下方言。

缺点:hibernate维护数据表关系比较复杂。完全是有hibernate来管理数据表的关系,对于我们来说完全是透明的,不易维护。

Hibernate自动生成sql语句,生成sql语句比较复杂,比较难挑错。

Hibernate由于是面向对象开发,不能开发比较复杂的业务。

应用场景:

适合需求变化较少的项目,比如ERP,CRM等等

Mybatis框架对jdbc框架进行封装,屏蔽了jdbc的缺点,开发简单。

Mybatis只需要程序员关注sql本身,不需要过多的关注业务。对sql的优化,修改比较容易

适应场景:

适合需求变化多端的项目,比如:互联网项目

三.Mybatis的Dao开发

使用dao开发有两种开发方式,一种是使用普通的接口和接口实现类来进行开发

另一种开发方式是使用mapper代理的开发的方式(直接使用接口)

1.sqlSession的使用范围

1.1.sessionFactoryBuidler

SessionFactoryBuidler创建会话工厂sqlSessionFactory

把sessionFactoryBuidler当成一个工具类即可,不需要进行单列模式设计。也

没有进行和spring的整合开发,所以说现在我们还不需要进行单列的设置。直接开发一个工具类,创建sqlSessionFactory的时候直接进行new一个对象即可。

1.2.sqlSessionFactory

sqlSessionFactory生产sqlSession回话,使用单列模式进行创建sqlSessionFactory(工厂一旦创建,只创建一个实例),将mybatis和spring进行整合后使用单列模式进行管理

1.3.sqlSession

sqlSession是面向用户的一个回话接口

sqlSession提供很多操作数据库的方法:selectOne(查询单个对象),selectList(返回单个或者多个对象)

sqlSession是线程不安全的,在sqlSession实现类中除了有查询数据库中的方法外还有数据域属性。

sqlSession最好是在方法内部使用。

2.传统的dao的开发方式

2.1.思路

程序员需要编写dao接口和dao接口实现类

在dao实现类里面进行注入sqlSessionFactory,然后通过sqlSessionFactory创建sqlSession

2.2.dao接口

2.3.dao的实现类

publicclass UserDaoImpl implements UserDao {
//给dao层注入SessionFactory对象
//使用构造方法进行注入
public SqlSessionFactory sessionFactory;
public UserDaoImpl(SqlSessionFactory sessionFactory){
this.sessionFactory=sessionFactory;
}
public User findUserbyId(int id) {
//获取sqlSession
SqlSession sqlSession = sessionFactory.openSession();
//根据ID进行查询
User user = sqlSession.selectOne("test.selectUserByID", 30);
return user;
}
public List<User> findUserByUsername(String username) {
//获取Session
SqlSession sqlSession = sessionFactory.openSession();
//使用用户名进行模拟查询
List<User> list = sqlSession.selectList("test.selectUserByUsername", username);
return list;
}
publicvoid insertUser(User user) {
SqlSession sqlSession = sessionFactory.openSession();
sqlSession.insert("test.insertUser", user);
}
publicvoid deleteUserById(int id) {
SqlSession sqlSession = sessionFactory.openSession();
sqlSession.delete("test.deleteUserByID", id);
}
}

2.4.测试代码

2.5.原始dao总结

1.dao接口中存在着大量的模版方法,能不能提取出来,大量减轻程序员的压力

2.实现类进行操作数据库时对statement的ID进行硬编码了。

3.sqlSession直接进行设置参数,由于sqlsession使用的泛型,设置参数类型不会报错,这样不利于开发。

3.代理Mapper开发模式

程序员只需要编写dao接口代码,不需要编写实现类代码。大大减轻了程序员的压力

3.1.思路

程序员还需要开发mapper.xml文件。

程序员编写mapper接口需要遵循一些开发规范。Mybatis会自动生成mapper接口实现类代理类。

3.2.开发规范

3.2.1.namespace的地址和mapper.xml的地址相同

Namespace在这里具有特殊的含义:必须是接口Mapper的接口全路径

3.2.2.dao接口中的方法必须和statement的Id必须一致

3.2.3.参数类型匹配

Mapper接口中的方法输入参数必须和对应的Mapper.xml中的parameterType中的参数匹配

3.2.4.返回值类型匹配

Mapper接口返回值类型必须和对应的mapper.xml中resultType输出类型匹配。

3.2.5.总结

采用代理模式进行开发:更方便,更快捷。

底层会自动调用:selectOne() selectList()

3.3.测试开发

3.3.1.映射文件

3.3.2.测试代码

3.4.总结

3.4.1.底层调用原理

Mapper动态代理方式底层根据返回值类型进行判断调用那个方法:

如果是返回单个对象就调用selectOne

如果是返回集合就调用selectList

3.4.2.mapper接口中参数只能是一个

Mapper接口中的参数只能是一个是否影响系统开发系统维护:

注意:dao层代码是被业务层公用的,即使是dao层代码参数只能是一个

业务层包装成不同类型pojo都可以满足不同业务需求。

持久层方法参数可以是map,基本类型,自定义对象,包装类型.

4.sqlMapConfig.xml

4.1.配置内容

SqlMapConfig.xml中配置的内容和顺序如下:

properties(属性)

settings(全局配置参数)

typeAliases(类型别名)

typeHandlers(类型处理器)

objectFactory(对象工厂)

plugins(插件)

environments(环境集合属性对象)

environment(环境子属性对象)

transactionManager(事务管理)

dataSource(数据源)

mappers(映射器)

4.2.properties属性文件

sqlMapConfig.xml文件可以引用外部资源文件:

注意:mybatis按照如下的顺序来加载属性:

l 在properties中定义的属性首先被读取

l 然后会读取properties中的resource和url资源

4.3.settings配置

mybatis框架在运行时可以调整一些运行参数。

比如:开启二级缓存、开启延迟加载

全局参数将会影响mybatis的运行行为。

详细参见“学习资料/mybatis-settings.xlsx”文件

4.4.typeAliases(别名)

在sql的xml文件中有很多的statement,statement需要指定parameterType输入参数类型和resultType输出结果类型

如果在开发时每次都写如全路径,不方便开发,此时就可以给parameterType和resultType定义别名

4.4.1.mybatis默认支持别名

别名

映射的类型

_byte

byte

_long

long

_short

short

_int

int

_integer

int

_double

double

_float

float

_boolean

boolean

string

String

byte

Byte

long

Long

short

Short

int

Integer

integer

Integer

double

Double

float

Float

boolean

Boolean

date

Date

decimal

BigDecimal

bigdecimal

BigDecimal

4.4.2.自定义别名

4.4.2.1.单个别名定义

引用别名

测试

4.4.2.2.批量定义别名

4.5.类型处理器(typeHandlers)

通常mybatis的typeHandlers完成jdbc类型和Java类型的转换

通常情况下,mybatis提供的类型处理器满足日常的需求,不需要自定义

mybatis支持类型处理器:

类型处理器

Java类型

JDBC类型

BooleanTypeHandler

Boolean,boolean

任何兼容的布尔值

ByteTypeHandler

Byte,byte

任何兼容的数字或字节类型

ShortTypeHandler

Short,short

任何兼容的数字或短整型

IntegerTypeHandler

Integer,int

任何兼容的数字和整型

LongTypeHandler

Long,long

任何兼容的数字或长整型

FloatTypeHandler

Float,float

任何兼容的数字或单精度浮点型

DoubleTypeHandler

Double,double

任何兼容的数字或双精度浮点型

BigDecimalTypeHandler

BigDecimal

任何兼容的数字或十进制小数类型

StringTypeHandler

String

CHAR和VARCHAR类型

ClobTypeHandler

String

CLOB和LONGVARCHAR类型

NStringTypeHandler

String

NVARCHAR和NCHAR类型

NClobTypeHandler

String

NCLOB类型

ByteArrayTypeHandler

byte[]

任何兼容的字节流类型

BlobTypeHandler

byte[]

BLOB和LONGVARBINARY类型

DateTypeHandler

Date(java.util)

TIMESTAMP类型

DateOnlyTypeHandler

Date(java.util)

DATE类型

TimeOnlyTypeHandler

Date(java.util)

TIME类型

SqlTimestampTypeHandler

Timestamp(java.sql)

TIMESTAMP类型

SqlDateTypeHandler

Date(java.sql)

DATE类型

SqlTimeTypeHandler

Time(java.sql)

TIME类型

ObjectTypeHandler

任意

其他或未指定类型

EnumTypeHandler

Enumeration类型

VARCHAR-任何兼容的字符串类型,作为代码存储(而不是索引)。

4.6.映射配置

4.6.1.通过resource加载单个配置文件

4.6.2.url加载绝对路径映射文件

使用完全限定路径

如:<mapper url="file:///D:workspace_spingmvcmybatis01configsqlmapUser.xml" />

4.6.3.接口class加载单个配置文件

根据以上要求:接口和配置文件必须在同一个目录

或者:

4.6.4.package批量加载Mapper文件

5.输入映射(parameterType)

通过parameterType指定输入参数类型,参数类型可以是基本类型,pojo,map类型

5.1.传递pojo包装类对象

5.1.1.需求

需求:完成用户的综合信息查询,输入参数比较复杂。(包含用户信息和其他信息)

5.1.2.定义包装类型pojo

注意:我们为什么不直接使用User来进行封装参数呢?

这是因为我们可以在隔离类里面进行封装很多参数,并且我们还有一些其他和业务不相关的查询条件。我们都可以定义在custom中。

在开发中和复杂查询条件也可直接封装在Javabean中,这样叫做非持久化属。

还有一种就是我们进行隔离开发,在定义一个公共封装属性的类。

5.1.3.mapper.xml文件

5.1.4.mapper接口代码

5.1.5.测试代码

5.2.传递Map

5.2.1.映射文件

5.2.2.接口代码

5.2.3.测试代码

6.输出映射(resultType|resultMap)

使用resultType进行查询结果映射,只要数据库列名和javabean的属性相同就可以映射成功

如果不相同:resultMap进行映射

如果查询出来对象的列名和javabean的属性全部不一致,不会创建javabean对象。

如果查询结果中仅有一个列名和属性一致,javabean对象就会被创建。

6.1.resultType

6.1.1.输出简单类型

6.1.1.1.需求

查询用户综合信息总记录数,和用户列表就可以实现分页

6.1.1.2.映射文件

6.1.1.3.测试代码

总结:输出结果是简单类型,可以使用简单类型进行映射

6.1.2.输出pojo

无论resultType返回结果是单个对象还是List集合对象,resultType返回类型都是一样的。

但是在代码中需要指定返回值结果类型。

尤其是在接口代理中:mybatis是根据返回值类型进行判断调用selectOne还是selectList

6.1.2.1.输出pojo对象

6.1.2.2.输出pojo集合

6.2.resultMap

mybatis使用resultMap完成高级映射

使用方法:如果mybatis查询结果列名和Javabean属性不一致,通过resultMap把javabean属性和数据库的列名进行关系映射。

6.2.1.映射文件

6.2.2.输出类型(resultMap)

使用resultMap作为输出结果集类型:

如果不在同一个Mapper文件中,需要指明包名。

6.2.3.接口代码

6.2.4.测试代码

6.3.总结

使用resultType进行映射:pojo中的属性必须和查询的类名相同

使用resultMap进行映射:pojo中的属性和查询的类名可以相同也可以不相同

7.动态sql(掌握)

7.1.什么是动态sql

Mybatis对sql进行灵活操作,可以通过mybatis语法的判断对sql进行灵活封装,拼接

7.2.需求

用户信息综合查询列表和用户信息查询总记录使用动态sql进行查询

对查询条件进行判断:

如果值为空就不能进行sql的拼接

7.3.映射文件

7.4.接口代码

7.5.测试代码

7.6.sql片段

7.6.1.需求

将上面的动态sql判断代码进行抽取,组成一个sql片段,其他的statement可以引用这个片段,方便程序员开发。

7.6.2.定义sql片段

7.6.3.引用sql片段

7.7.foreach

向mybatis传递数组,或者List集合使用foreach就可以解析

7.7.1.需求

在用户综合信息查询时使用多个ID进行查询:

SELECT * FROM USER WHERE id=1 OR id=10 OR id=16
SELECT * FROM USER WHERE id IN(1,10,16)

单独传递集合和数组

7.7.2.输入参数中定义集合List<Integer>

7.7.3.映射文件(修改)

WHERE id=1 OR id=10 OR id=16

在查询条件中,查询条件定义成一个sql片段,需要修改sql片段。

7.7.4.测试代码

7.7.5.另一个IN(…)实现

7.8.补充内容

多参数集合查询

即除了包含in条件,还包含至少一个其它条件的)

select * from student where class = #{class} and level in (1,2,3,4)

对第二种的实现,必须掌握StudentWapper.xml中语法。

如下:

1) 接口代码

List getStudentsByLevels(Map paramMap)

其中这个map中放的是:

map.put("levels", new String[]{1,2,3,4});
map.put("class", "good");

注:

#这里的levels和下面xml中的collection中的相对应

#对于字符串的in,MyBatis已作处理,不需要再自己给数组中的每个元素加上单引号。

2)xml文件中配置

<select id="getStudentsByLevels" resultType="xxx.Student">
select * from student where class = #{class} and level in
<foreach collection="levels" item="item" open="(" separator="," close=")">
#{item}
</foreach>
<select/>

更新使用set动态更新

<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>

Trim

trim是更灵活的去处多余关键字的标签,他可以实践where和set的效果、

choose (when, otherwise)

有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。而使用if标签时,只要test中的表达式为true,就会执行if标签中的条件。MyBatis提供了choose 元素。if标签是与(and)的关系,而choose是或(or)的关系。

choose标签是按顺序判断其内部when标签中的test条件出否成立,如果有一个成立,则choose结束。当choose中所有when的条件都不满则时,则执行otherwise中的sql。类似于Java 的switch 语句,choose为switch,when为case,otherwise则为default