1.
总结
jdbc
开发的问题
1.
频繁创建数据库连接对象、释放,容易造成系统资源浪费,影响系统性能。企业项目中可以使用连接池解决这个问题,但是使用Jdbc
需要自己实现连接池。mybatis
已经提供了连接池。
2.
sql
语句定义、参数设置、结果集处理存在硬编码。企业项目中,sql
语句变化的可能性较大,一旦发生变化,需要修改Java
代码,系统需要重新编译,重新发布。不好维护。
3.
结果集处理存在重复代码,处理麻烦。如果可以映射为java
对象会比较方便。
2.
mybatis
介绍
mybatis
是Apache
软件基金会下的一个开源项目,前身是Ibatis
框架。2010
年这个项目由apache
软件基金会迁移到google code
下,改名为mybatis
。2013
年11
月又迁移到了github
(https://github.com/mybatis/mybatis-3/releases
)。
mybatis
是一个
持久层
的框架,是对JDBC
操作数据库的封装,使开发者
只需要
关注业务本身,
不需要
花费精力去处理加载驱动、创建数据库连接对象、创建statement
语句对象、参数设置、结果集处理等一系列
繁杂的
过程代码。
mybatis
通过xml
或注解进行配置,将java
对象与sql
语句中的参数
自动映射
生成最终执行的sql
语句,并将sql
语句执行结果
自动映射
成java
对象,返回给业务层(service
)应用。
3.
mybatis
入门程序
3.1.
需求
实现用户表(user
)增、删、改、查操作。
1.
根据用户Id
查询用户
2.
根据用户名称模糊查询用户
3.
新增用户
4.
根据用户Id
修改用户
5.
根据用户Id
删除用户
3.2.
需求实现
3.2.1.
配置
pom.xml
文件,加入
mybatis
依赖
<
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
>
cn.itheima
</
groupId
>
<
artifactId
>
mybatis
-first
</
artifactId
>
<
version
>
0.0.1-SNAPSHOT
</
version
>
<
packaging
>
jar
</
packaging
>
<
name
>
mybatis
-first
</
name
>
<
url
>
http://maven.apache.org
</
url
>
<
properties
>
<
project.build.sourceEncoding
>
UTF-8
</
project.build.sourceEncoding
>
<!--
mysql
版本 -->
<
mysql.version
>
5.1.30
</
mysql.version
>
<!--
junit
版本 -->
<
junit.version
>
4.12
</
junit.version
>
<!--
mybatis
版本号 -->
<mybatis.version>3.4.5</mybatis.version>
<!-- log4j日志包版本 -->
<slf4j.version>1.7.7</slf4j.version>
<log4j.version>1.2.17</log4j.version>
</
properties
>
<
dependencies
>
<!--
mysql
数据库依赖 -->
<
dependency
>
<
groupId
>
mysql
</
groupId
>
<
artifactId
>
mysql
-connector-java
</
artifactId
>
<
version
>
${mysql.version}
</
version
>
</
dependency
>
<!--
mybatis
核心包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>
mybatis
</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!-- log4j日志包 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-
api
</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!--
junit
依赖 -->
<
dependency
>
<
groupId
>
junit
</
groupId
>
<
artifactId
>
junit
</
artifactId
>
<
version
>
${junit.version}
</
version
>
<
scope
>
test
</
scope
>
</
dependency
>
</
dependencies
>
</
project
>
|
3.2.2.
准备配置文件
3.2.2.1.
sqlMapConfig.xml
说明:mybatis
框架核心配置文件。
<?
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
>
<!-- 运行环境配置 -->
<!-- default属性:指定使用哪一个运行环境 -->
<
environments
default
=
"development"
>
<!-- id属性:唯一标识一个运行环境 -->
<
environment
id
=
"development"
>
<!-- 事务管理器配置,JDBC:mybatis默认使用
jdbc
事务 -->
<
transactionManager
type
=
"JDBC"
/>
<!-- 数据源配置,POOLED:mybatis提供的连接池 -->
<
dataSource
type
=
"POOLED"
>
<
property
name
=
"driver"
value
=
"com.mysql.jdbc.Driver"
/>
<
property
name
=
"url"
value
=
"jdbc:mysql://127.0.0.1:3306/mybatis"
/>
<
property
name
=
"username"
value
=
"root"
/>
<
property
name
=
"password"
value
=
"admin"
/>
</
dataSource
>
</
environment
>
</
environments
>
</
configuration
>
|
3.2.2.2.
log4j.properties
# Global logging configuration
log4j.rootLogger=
DEBUG,
stdout
# 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
|
3.2.3.
准备用户
pojo
public
class
User {
private
Integer
id
;
//
int
(11) NOT NULL AUTO_INCREMENT,
private
String
username
;
//
varchar
(32) NOT NULL COMMENT '用户名称',
private
Date
birthday
;
// date DEFAULT NULL COMMENT '生日',
private
String
sex
;
// char(1) DEFAULT NULL COMMENT '性别',
private
String
address
;
//
varchar
(256) DEFAULT NULL COMMENT '地址',
/**
*
@return
the id
*/
public
Integer getId() {
return
id
;
}
/**
*
@param
id the id to set
*/
public
void
setId(Integer id) {
this
.
id
= id;
}
/**
*
@return
the
username
*/
public
String getUsername() {
return
username
;
}
/**
*
@param
username the
username
to set
*/
public
void
setUsername(String username) {
this
.
username
= username;
}
/**
*
@return
the birthday
*/
public
Date getBirthday() {
return
birthday
;
}
/**
*
@param
birthday the birthday to set
*/
public
void
setBirthday(Date birthday) {
this
.
birthday
= birthday;
}
/**
*
@return
the sex
*/
public
String getSex() {
return
sex
;
}
/**
*
@param
sex the sex to set
*/
public
void
setSex(String sex) {
this
.
sex
= sex;
}
/**
*
@return
the address
*/
public
String getAddress() {
return
address
;
}
/**
*
@param
address the address to set
*/
public
void
setAddress(String address) {
this
.
address
= address;
}
/* (non-
Javadoc
)
* @see java.lang.Object#toString()
*/
@Override
public
String toString() {
return
"User [id="
+
id
+
", username="
+
username
+
", birthday="
+
birthday
+
", sex="
+
sex
+
", address="
+
address
+
"]"
;
}
}
|
3.2.4.
准备
sql
语句
select * from `user` where id=24
|
3.2.5.
准备
mapper
映射文件
说明:用于配置java
对象,与sql
语句的对应关系。
<?
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
属性:名称空间,相当于java中的package,用于放置
sql
语句冲突 -->
<
mapper
namespace
=
"test"
>
<!--说明:
mybatis
框架针对每一种
sql
语句:新增/修改/删除/查询,提供了对应的标签:
insert/update/delete/select来放置 -->
<!-- 根据用户Id查询用户,说明:
select标签:用于放置查询
sql
语句
id属性:唯一标识一条
sql
语句
parameterType属性:输入参数类型
resultType属性:返回值类型
#{id}:占位符,相当于
jdbc
中的问号:?-->
<
select
id
=
"queryUserById"
parameterType
=
"int"
resultType
=
"cn.itheima.mybatis.po.User"
>
select * from `user` where id=#{id}
</
select
>
</
mapper
>
|
3.2.6.
在
sqlMapcConfig.xml
文件中,加载
User.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
>
<!-- 运行环境配置 -->
<!-- default属性:指定使用哪一个运行环境 -->
<
environments
default
=
"development"
>
<!-- id属性:唯一标识一个运行环境 -->
<
environment
id
=
"development"
>
<!-- 事务管理器配置,JDBC:mybatis默认使用
jdbc
事务 -->
<
transactionManager
type
=
"JDBC"
/>
<!-- 数据源配置,POOLED:mybatis提供的连接池 -->
<
dataSource
type
=
"POOLED"
>
<
property
name
=
"driver"
value
=
"com.mysql.jdbc.Driver"
/>
<
property
name
=
"url"
value
=
"jdbc:mysql://127.0.0.1:3306/mybatis"
/>
<
property
name
=
"username"
value
=
"root"
/>
<
property
name
=
"password"
value
=
"admin"
/>
</
dataSource
>
</
environment
>
</
environments
>
<!-- 加载
mapper
映射文件 -->
<mappers>
<!--加载User.xml文件,说明:
resource属性:指定配置文件的位置-->
<mapper resource=
"sqlmap/User.xml"
/>
</mappers>
</
configuration
>
|
3.2.7.
编写测试代码
public
class
MybatisTest {
// 1.测试根据用户Id查询用户
@Test
public
void
queryUserByIdTest()
throws
IOException{
// 1.加载核心配置文件:sqlMapConfig.xml
// resource属性:指定核心配置文件位置
InputStream inputStream = Resources.
getResourceAsStream
(
"sqlMapConfig.xml"
);
// 2.读取配置文件内容
SqlSessionFactoryBuilder builder =
new
SqlSessionFactoryBuilder();
// SqlSessionFactory对象:
mybatis
框架的核心对象,一个项目中只需要一个(单例设计模式)
SqlSessionFactory sqlSessionFactory = builder.build(inputStream);
// 3.使用SqlSessionFactory对象,创建sqlSession对象
// sqlSession对象:
// 3.1相当于
jdbc
中的connection对象
// 3.2 sqlSession对象是线程不安全,每一个执行操作的方法,都需要创建一个sqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4.使用sqlSession对象,调用方法执行
// selectOne方法:查询单条记录
// statement参数:执行的
sql
语句(名称空间+
sql
语句Id)
// parameter参数:传入的参数值
Object
user = sqlSession.selectOne(
"test.queryUserById"
, 24);
System.
out
.println(user);
// 5.释放资源
sqlSession.close();
}
}
|
3.3.
其他需求实现
3.3.1.
根据用户名称模糊查询用户
3.3.1.1.
准备
sql
语句
select * from `user` where username like '%
小明
%'
|
3.3.1.2.
配置映射文件
<!-- 根据用户名称模糊查询用户,说明 -->
<
select
id
=
"queryUserByName"
parameterType
=
"string"
resultType
=
"cn.itheima.mybatis.po.User"
>
select * from `user` where
username
like #{
username
}
</
select
>
|
3.3.1.3.
编写测试代码
// 2.测试根据用户名称模糊查询用户
@Test
public
void
queryUserByNameTest
()
throws
IOException{
// 1.加载核心配置文件
InputStream inputStream = Resources.
getResourceAsStream
(
"sqlMapConfig.xml"
);
// 2.读取配置文件内容
SqlSessionFactoryBuilder builder =
new
SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(inputStream);
// 3.使用sqlSessionFactory对象,创建sqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4.使用sqlSession对象,调用方法执行
// selectList方法:查询多条记录
// statement参数:执行的
sql
语句(名称空间+
sql
语句Id)
// parameter参数:传入的参数值
List<Object> list = sqlSession.selectList(
"test.queryUserByName"
,
"%小明%"
);
for
(Object o :list){
System.
out
.println(o);
}
// 5.释放资源
sqlSession.close();
}
|
3.3.1.4.
使用字符串拼接符
${}
,拼接参数
<!-- 根据用户名称模糊查询用户,说明 -->
<
select
id
=
"queryUserByName"
parameterType
=
"string"
resultType
=
"cn.itheima.mybatis.po.User"
>
<!-- select * from `user` where
username
like #{
username
} -->
<!-- where
username
like '%小明%',说明:
使用字符串拼接符${},拼接参数 -->
select * from `user` where
username
like '%${value}%'
</
select
>
|
3.3.1.5.
占位符
#{}
与字符串拼接符
${}
区别
1.
占位符#{}
,相当于jdbc
中的问号?
,当参数传递的是
java
简单类型
的时候,花括号中的内容可以是任意字符串。
2.
字符串拼接符 ${}
,当参数传递的是
java
简单类型
的时候,花括号中的内容只能是:value
3.
在sql
语句中使用字符串拼接符${}
,可能引起sql
注入的问题。但是mybatis
中字符串拼接符可以使用,原因是是后端dao
层的开发,项目中参数传递经过表现层(action
),业务层(service
)已经处理好。
3.3.2.
新增用户
3.3.2.1.
准备
sql
语句
insert into `user`(id,username,birthday,sex,address) values(2,'
小李飞刀
','2017-11-06','1','
来自明朝
')
|
3.3.2.2.
配置映射文件
<!-- 新增用户,说明
insert标签:用于放置新增
sql
语句
#{id}:占位符,当参数传递的是
pojo
的时候,换括号中的内容是
pojo
的属性
-->
<
insert
id
=
"insertUser"
parameterType
=
"cn.itheima.mybatis.po.User"
>
insert into `user`(id,
username
,birthday,sex,address)
values(#{id},#{
username
},#{birthday},#{sex},#{address})
</
insert
>
|
3.3.2.3.
编写测试代码
// 3.测试新增用户
@Test
public
void
insertUserTest
(){
// 1.创建sqlSession对象
SqlSession sqlSession =
sqlSessionFactory
.openSession();
// 2.使用sqlSession对象,调用方法执行
// insert方法:新增记录
// statement参数:执行的
sql
语句(名称空间+
sql
语句Id)
// parameter参数:传入的参数值
// 创建用户对象
User user =
new
User();
user.setId(3);
user.setUsername(
"林诗音"
);
user.setBirthday(
new
Date());
user.setSex(
"2"
);
user.setAddress(
"来自大明朝"
);
sqlSession.insert(
"test.insertUser"
, user);
// 3.释放资源
sqlSession.close();
}
|
问题:
java
程序执行成功,但是数据库中并没有林诗音的数据,原因是没有提交事务。
3.3.2.4.
提交事务
3.3.2.4.1.
方式一
// 3.测试新增用户
@Test
public
void
insertUserTest
(){
// 1.创建sqlSession对象
SqlSession sqlSession =
sqlSessionFactory
.openSession();
// 2.使用sqlSession对象,调用方法执行
// insert方法:新增记录
// statement参数:执行的
sql
语句(名称空间+
sql
语句Id)
// parameter参数:传入的参数值
// 创建用户对象
User user =
new
User();
user.setId(3);
user.setUsername(
"林诗音"
);
user.setBirthday(
new
Date());
user.setSex(
"2"
);
user.setAddress(
"来自大明朝"
);
sqlSession.insert(
"test.insertUser"
, user);
// 数据库提交事务:commit
sqlSession.commit();
// 3.释放资源
sqlSession.close();
}
|
3.3.2.4.2.
方式二
// 3.测试新增用户
@Test
public
void
insertUserTest
(){
// 1.创建sqlSession对象
//SqlSession sqlSession = sqlSessionFactory.openSession();
// 创建sqlSession对象,指定自动提交事务。true:表示提交;false:表示不提交。默认是false
SqlSession sqlSession =
this
.sqlSessionFactory.openSession(
true
);
// 2.使用sqlSession对象,调用方法执行
// insert方法:新增记录
// statement参数:执行的
sql
语句(名称空间+
sql
语句Id)
// parameter参数:传入的参数值
// 创建用户对象
User user =
new
User();
user.setId(4);
user.setUsername(
"林诗音"
);
user.setBirthday(
new
Date());
user.setSex(
"2"
);
user.setAddress(
"来自大明朝"
);
sqlSession.insert(
"test.insertUser"
, user);
// 数据库提交事务:commit
//sqlSession.commit();
// 3.释放资源
sqlSession.close();
}
|
问题:用户表中
id
是自增长,不需要传递,但是
mybatis
中如何获取到新增以后的用户
Id
???
mysql
数据库查询新增Id
:
select LAST_INSERT_ID()
3.3.2.5.
获取新增的用户
Id
3.3.2.5.1.
方式一
<!-- 新增用户,说明
insert标签:用于放置新增
sql
语句
#{id}:占位符,当参数传递的是
pojo
的时候,换括号中的内容是
pojo
的属性-->
<
insert
id
=
"insertUser"
parameterType
=
"cn.itheima.mybatis.po.User"
>
<!-- insert into `user`(id,
username
,birthday,sex,address)
values(#{id},#{
username
},#{birthday},#{sex},#{address}) -->
<!-- selectKey标签:查询主键id,说明
keyColumn属性:主键字段(表)
keyProperty属性:主键属性(
pojo
)
resultType属性:指定主键字段类型
order属性:指定在insert语句之前,还是之后获取主键值.
BEFORE:在insert语句前;AFTER:在insert语句之后-->
<selectKey keyColumn=
"id"
keyProperty=
"id"
resultType=
"int"
order=
"AFTER"
>
select LAST_INSERT_ID()
</selectKey>
insert into `user`(
username
,birthday,sex,address)
values(#{
username
},#{birthday},#{sex},#{address})
</
insert
>
|
3.3.2.5.2.
方式二
<!-- 新增用户,说明
insert标签:用于放置新增
sql
语句
#{id}:占位符,当参数传递的是
pojo
的时候,换括号中的内容是
pojo
的属性-->
<
insert
id
=
"insertUser"
parameterType
=
"cn.itheima.mybatis.po.User"
useGeneratedKeys=
"true"
keyColumn=
"id"
keyProperty=
"id"
>
<!-- insert into `user`(id,
username
,birthday,sex,address)
values(#{id},#{
username
},#{birthday},#{sex},#{address}) -->
<!-- selectKey标签:查询主键id,说明
keyColumn属性:主键字段(表)
keyProperty属性:主键属性(
pojo
)
resultType属性:指定主键字段类型
order属性:指定在insert语句之前,还是之后获取主键值.
BEFORE:在insert语句前;AFTER:在insert语句之后-->
<!-- <selectKey keyColumn="id" keyProperty="id" resultType="
int
" order="AFTER">
select LAST_INSERT_ID()
</selectKey> -->
insert into `user`(
username
,birthday,sex,address)
values(#{
username
},#{birthday},#{sex},#{address})
</
insert
>
|
3.3.3.
根据用户
Id
修改用户
3.3.3.1.
准备
sql
语句
update `user` set username='
小李飞刀和林诗音
',sex='2' where id=2
|
3.3.3.2.
配置映射文件
<!-- 根据用户id修改用户,说明:
update标签:用于放置修改
sql
语句-->
<
update
id
=
"updateUserById"
parameterType
=
"cn.itheima.mybatis.po.User"
>
update `user`
set
username
=#{
username
},sex=#{sex} where id=#{id}
</
update
>
|
3.3.3.3.
编写测试代码
// 4.测试根据用户Id修改用户
@Test
public
void
updateUserByIdTest
(){
// 1.创建sqlSession对象
SqlSession sqlSession =
this
.
sqlSessionFactory
.openSession(
true
);
// 2.使用sqlSession对象,调用方法执行
// update方法:修改记录
// statement参数:执行的
sql
语句(名称空间+
sql
语句Id)
// parameter参数:传入的参数值
// 创建用户对象
User user =
new
User();
user.setId(3);
user.setUsername(
"林诗音和小李飞刀"
);
user.setSex(
"1"
);
sqlSession.update(
"test.updateUserById"
, user);
// 3.释放资源
sqlSession.close();
}
|
3.3.4.
根据用户
Id
删除用户
3.3.4.1.
准备
sql
语句
delete from `user` where id=4
|
3.3.4.2.
配置映射文件
<!-- 根据用户id删除用户,说明:
delete标签:用于放置删除的
sql
语句-->
<
delete
id
=
"deleteUserById"
parameterType
=
"int"
>
delete from `user` where id=#{id}
</
delete
>
|
3.3.4.3.
编写测试代码
// 5.测试根据用户Id删除用户
@Test
public
void
deleteUserByIdTest
(){
// 1.创建sqlSession对象
SqlSession sqlSession =
this
.
sqlSessionFactory
.openSession(
true
);
// 2.使用sqlSession对象,调用方法执行
// delete方法:删除记录
// statement参数:执行的
sql
语句(名称空间+
sql
语句Id)
// parameter参数:传入的参数值
sqlSession.delete(
"test.deleteUserById"
, 35);
// 3.释放资源
sqlSession.close();
}
|
4.
mybatis
框架原理
1.
Configuration
配置对象:sqlMapConfig.xl
,User.xml......
2.
MappedStatement
对象:负责输入输出映射,ParameterType
参数输入,ResultType
返回值输出
3.
Executor
执行器对象:负责执行数据库的CRUD
操作
5.
mybatis
两种开发方法
1.
原始的dao
开发方法
2.
mapper
代理开发方法
5.1.
原始的
dao
开发方法
5.1.1.
需求
1.
根据用户Id
查询用户
2.
新增用户
5.1.2.
需求实现
5.1.2.1.
准备用户
dao
接口
public
interface
UserDao {
// 1.根据用户Id查询用户
User queryUserById(Integer id);
// 2.新增用户
void
insertUser
(User user);
}
|
5.1.2.2.
实现用户
dao
接口
public
class
UserDaoImpl
implements
UserDao {
// 定义sqlSessionFactory对象
private
SqlSessionFactory sqlSessionFactory;
/**
*
*/
public
UserDaoImpl() {
super
();
}
/**
*
@param
sqlSessionFactory
*/
public
UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
super
();
this
.
sqlSessionFactory
= sqlSessionFactory;
}
/* (non-
Javadoc
)
* @see cn.itheima.mybatis.dao.UserDao#queryUserById(java.lang.Integer)
*/
public
User queryUserById(Integer id) {
//
TODO
Auto-generated method stub
// 1.创建sqlSession对象
SqlSession sqlSession =
this
.
sqlSessionFactory
.openSession();
// 2.使用sqlSession对象,调用方法执行
Object
user = sqlSession.selectOne(
"test.queryUserById"
, id);
// 3.释放资源
sqlSession.close();
return
(User) user;
}
/* (non-
Javadoc
)
* @see cn.itheima.mybatis.dao.UserDao#insertUser(cn.itheima.mybatis.po.User)
*/
public
void
insertUser(User user) {
//
TODO
Auto-generated method stub
// 1.创建sqlSession对象
SqlSession sqlSession =
this
.
sqlSessionFactory
.openSession(
true
);
// 2.使用sqlSession对象,调用方法执行
sqlSession.insert(
"test.insertUser"
, user);
// 3.释放资源
sqlSession.close();
}
}
|
5.1.2.3.
编写测试代码
public
class
UserDaoTest {
private
SqlSessionFactory
sqlSessionFactory
=
null
;
@Before
public
void
init()
throws
IOException{
// 1.加载核心配置文件:sqlMapConfig.xml
// resource属性:指定核心配置文件位置
InputStream inputStream = Resources.
getResourceAsStream
(
"sqlMapConfig.xml"
);
// 2.读取配置文件内容
SqlSessionFactoryBuilder builder =
new
SqlSessionFactoryBuilder();
// SqlSessionFactory对象:
mybatis
框架的核心对象,一个项目中只需要一个(单例设计模式)
sqlSessionFactory
= builder.build(inputStream);
}
// 测试根据用户Id查询用户
@Test
public
void
queryUserByIdTest(){
// 1.创建用户
dao
对象
UserDao userDao =
new
UserDaoImpl(
sqlSessionFactory
);
// 2.使用userDao对象,调用方法执行
User user = userDao.queryUserById(2);
System.
out
.println(user);
}
}
|
测试新增用户:
// 测试新增用户
@Test
public
void
insertUserTest
(){
// 1.创建用户
dao
对象
UserDao userDao =
new
UserDaoImpl(
sqlSessionFactory
);
// 2.使用userDao对象,调用方法执行
// 创建用户对象
User user =
new
User();
user.setUsername(
"阿飞"
);
user.setSex(
"1"
);
user.setBirthday(
new
Date());
user.setAddress(
"来自大明朝"
);
System.
out
.println(
"执行前:"
+user);
userDao.insertUser(user);
System.
out
.println(
"执行后:"
+user);
}
|
5.2. mapper
代理开发方法
5.2.1.
注意事项
1.
要求mapper
映射文件中namespace
属性值,必须是mapper
接口的全路径(包名称+
接口名称)
2.
要求mapper
映射文件中sql
语句的声明,与mapper
接口方法的声明一致
2.1.mapper
接口返回值类型,与sql
语句标签的resultType
属性指定的类型一致
2.2.mapper
接口的方法名称,与sql
语句id
属性值一致
2.3.mapper
接口的方法的形参,与sql
语句的parameterType
属性指定的类型一致
5.2.2.
需求
1.
根据用户Id
查询用户
2.
新增用户
5.2.3.
需求实现
5.2.3.1.
准备用户
mapper
接口
public
interface
UserMapper {
// 1.根据用户Id查询用户
User queryUserById(Integer id);
// 2.新增用户
void
insertUser(User
user
);
}
|
5.2.3.2.
准备用户
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
属性:名称空间,相当于java中的package,用于放置
sql
语句冲突 -->
<!--
mapper
代理开发方法中,
namespace
属性值,必须是
mapper
接口的全路径 -->
<
mapper
namespace
=
"cn.itheima.mybatis.mapper.UserMapper"
>
<!-- 根据用户Id查询用户,说明:
select标签:用于放置查询
sql
语句
id属性:唯一标识一条
sql
语句
parameterType属性:输入参数类型
resultType属性:返回值类型
#{id}:占位符,相当于
jdbc
中的问号:?-->
<
select
id
=
"queryUserById"
parameterType
=
"int"
resultType
=
"cn.itheima.mybatis.po.User"
>
select * from `user` where id=#{id}
</
select
>
<!-- 新增用户,说明
insert标签:用于放置新增
sql
语句
#{id}:占位符,当参数传递的是
pojo
的时候,换括号中的内容是
pojo
的属性-->
<
insert
id
=
"insertUser"
parameterType
=
"cn.itheima.mybatis.po.User"
useGeneratedKeys
=
"true"
keyColumn
=
"id"
keyProperty
=
"id"
>
insert into `user`(
username
,birthday,sex,address)
values(#{
username
},#{birthday},#{sex},#{address})
</
insert
>
</
mapper
>
|
5.2.3.3.
在
sqlMapConfig.xml
,加载
UserMapper.xml
文件
<!-- 加载
mapper
映射文件 -->
<
mappers
>
<!--加载User.xml文件,说明:
resource属性:指定配置文件的位置-->
<
mapper
resource
=
"sqlmap/User.xml"
/>
<!-- 加载UserMapper.xml文件 -->
<mapper resource=
"sqlmap/UserMapper.xml"
/>
</
mappers
>
|
5.2.3.4.
编写测试代码
public
class
UserMapperTest {
private
SqlSessionFactory
sqlSessionFactory
=
null
;
@Before
public
void
init()
throws
IOException{
// 1.加载核心配置文件:sqlMapConfig.xml
// resource属性:指定核心配置文件位置
InputStream inputStream = Resources.
getResourceAsStream
(
"sqlMapConfig.xml"
);
// 2.读取配置文件内容
SqlSessionFactoryBuilder builder =
new
SqlSessionFactoryBuilder();
// SqlSessionFactory对象:
mybatis
框架的核心对象,一个项目中只需要一个(单例设计模式)
sqlSessionFactory
= builder.build(inputStream);
}
// 测试根据用户Id查询用户
@Test
public
void
queryUserByIdTest(){
// 1.创建sqlSession对象
SqlSession sqlSession =
this
.
sqlSessionFactory
.openSession();
// 2.使用sqlSession对象,获取
mapper
代理对象
// getMapper方法:获取
mapper
代理对象
// type参数:
mapper
接口的class
UserMapper mapper = sqlSession.getMapper(UserMapper.
class
);
// 3.使用
mapper
代理对象,调用方法执行
User user = mapper.queryUserById(2);
System.
out
.println(user);
// 4.释放资源
sqlSession.close();
}
}
|
测试新增用户:
// 测试新增用户
@Test
public
void
insertUserTest
(){
// 1.创建sqlSession对象
SqlSession sqlSession =
this
.
sqlSessionFactory
.openSession(
true
);
// 2.使用sqlSession对象,获取
mapper
代理对象
UserMapper mapper = sqlSession.getMapper(UserMapper.
class
);
// 3.使用
mapper
对象,调用方法执行
// 创建用户对象
User user =
new
User();
user.setUsername(
"天机老人"
);
user.setSex(
"1"
);
user.setBirthday(
new
Date());
user.setAddress(
"来自大明朝"
);
mapper.insertUser(user);
// 4.释放资源
sqlSession.close();
}
|
5.3.
两种开发方法总结
1.
原始的dao
开发方法:需要开发接口和实现类
2.
mapper
代理开发方法:只需要开发接口
3.
企业项目中,推荐使用mapper
代理开发
6.
mybatis
核心配置文件
sqlMapConfig.xml
:配置运行环境(数据源),mapper
映射文件。
顺序
|
配置标签名称
|
说明
|
1
|
properties
|
属性
|
2
|
settings
|
配置全局参数
|
3
|
typeAliases
|
类型别名
|
4
|
typeHandlers
|
类型处理器
|
5
|
objectFactory
|
对象工厂
|
6
|
plugins
|
插件
|
7
|
environments
|
环境集合属性对象
|
8
|
databaseIdProvider
|
多数据库支持
|
9
|
mappers
|
映射器
|
说明:
1.
红色字体内容要求掌握
2.
在
sqlMapConfig.xml
中
必须
是从上往下的配置顺序
|
6.1. properties
(属性)
作用:加载属性文件(比如db.properties
)和定义属性
6.1.1.
准备
db.properties
文件
db.driver=
com.mysql.jdbc.Driver
db.url=
jdbc:mysql://127.0.0.1:3306/
mybatis
db.username=
root
db.password=
admin
|
6.1.2.
加载
db.properties
属性文件
<!--加载属性文件,说明:
1.resource属性:指定本地配置文件的位置
2.
url
属性:指定网络上的配置文件位置-->
<
properties
resource
=
"db.properties"
>
</
properties
>
|
6.1.3.
使用
db.propertis
属性文件中的属性
<!-- 运行环境配置 -->
<!-- default属性:指定使用哪一个运行环境 -->
<
environments
default
=
"development"
>
<!-- id属性:唯一标识一个运行环境 -->
<
environment
id
=
"development"
>
<!-- 事务管理器配置,JDBC:mybatis默认使用
jdbc
事务 -->
<
transactionManager
type
=
"JDBC"
/>
<!-- 数据源配置,POOLED:mybatis提供的连接池 -->
<
dataSource
type
=
"POOLED"
>
<!-- <property name="driver" value="com.mysql.jdbc.Driver" />
<property name="
url
" value="jdbc:mysql://127.0.0.1:3306/
mybatis
" />
<property name="
username
" value="root" />
<property name="password" value="
admin
" /> -->
<!-- 使用db.properties属性文件的属性 -->
<property name=
"driver"
value=
"${db.driver}"
/>
<property name=
"url"
value=
"${db.url}"
/>
<property name=
"username"
value=
"${db.username}"
/>
<property name=
"password"
value=
"${db.password}"
/>
</
dataSource
>
</
environment
>
</
environments
>
|
6.1.4.
使用内部
property
标签定义属性
<!--加载属性文件,说明:
1.resource属性:指定本地配置文件的位置
2.
url
属性:指定网络上的配置文件位置
3.使用内部property标签定义属性
4.加载顺序:首先加载内部property标签定义的属性,再加载属性文件中的属性,
如果有相同的属性,属性文件中的属性,覆盖内部property标签的属性
-->
<
properties
resource
=
"db.properties"
>
<
property
name
=
"db.username"
value
=
"root123"
/>
<
property
name
=
"db.password"
value
=
"admin"
/>
</
properties
>
|
6.2. typeAliases
(类型别名)
作用:简称。比如中华人民共和国,简称中国。
6.2.1.
内置别名
别名
|
映射类型
|
_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
|
object
|
Object
|
map
|
Map
|
hashmap
|
HashMap
|
list
|
List
|
arraylist
|
ArrayList
|
collection
|
Collection
|
iterator
|
Iterator
|
说明:
1.
内置别名可以直接使用
2.
别名不区分大小写
6.2.2.
自定义别名
6.2.2.1.
自定义别名方式一
<!-- 自定义别名配置 -->
<
typeAliases
>
<!-- 自定义用户别名配置,说明:
1.type属性:别名的类型
2.默认使用类名称,作为别名
3.alias属性:指定别名的名称 -->
<
typeAlias
type
=
"cn.itheima.mybatis.po.User"
alias
=
"user"
/>
</
typeAliases
>
|
6.2.2.2.
自定义别名方式二
<!-- 自定义别名配置 -->
<
typeAliases
>
<!-- 自定义用户别名配置,说明:
1.type属性:别名的类型
2.默认使用类名称,作为别名
3.alias属性:指定别名的名称 -->
<!-- <typeAlias type="cn.itheima.mybatis.po.User" alias="user"/> -->
<!--包扫描方式配置别名,说明:
1.name属性:指定扫描的包
2.默认使用类名称,作为别名
3.如果有多个包,配置多个package
4.企业项目中,推荐使用包扫描方式 -->
<package name=
"cn.itheima.mybatis.po"
/>
</
typeAliases
>
|
6.3. mappers
(映射器)
作用:加载mapper
映射文件。
6.3.1.
加载
mapper
映射文件方式一
<!-- 加载
mapper
映射文件 -->
<
mappers
>
<!--加载User.xml文件,说明:
resource属性:指定配置文件的位置-->
<
mapper
resource
=
"sqlmap/User.xml"
/>
<!-- 加载UserMapper.xml文件 -->
<
mapper
resource
=
"sqlmap/UserMapper.xml"
/>
</
mappers
>
|
6.3.2.
加载
mapper
映射文件方式二
<!-- 加载
mapper
映射文件 -->
<
mappers
>
<!--加载User.xml文件,说明:
resource属性:指定配置文件的位置-->
<
mapper
resource
=
"sqlmap/User.xml"
/>
<!-- 加载UserMapper.xml文件 -->
<!-- <mapper resource="
sqlmap
/UserMapper.xml"/> -->
<!-- 包扫描方式加载
mapper
映射文件,说明:
1.前提必须是
mapper
代理开发方法
2.要求
mapper
映射文件,与
mapper
接口在同一个目录
3.要求
mapper
映射文件的名称,与
mapper
接口的名称一致 -->
<package name=
"cn.itheima.mybatis.mapper"
/>
</
mappers
>
|
7.
mybatis
与
hibernate
比较
7.1.
相同点
都是对jdbc
的封装,都是持久层的框架,都用于dao
层的开发。
7.2.
不同点
1.
hibernate
是对sql
语句做了封装,提供HQL
语言操作数据库,数据库无关性支持好,在项目需要支持多种数据库的情况下,代码开发量较少,sql
语句优化困难;mybatis
是直接使用sql
语句操作数据库,不支持数据库无关性,在项目需要支持多种数据库的情况下,代码开发量较多,sql
语句优化容易。
2.
hibernate
是配置java
对象与数据库表的对应关系,多表关联关系配置复杂。mybatis
是配置java
对象,与sql
语句对应关系,多表关联关系配置容易。
3.
hibernate
是重量级的框架,学习使用门槛高,适合于需求相对稳定,中小型的项目,比如:办公自动化系统(OA
);mybatis
是轻量级的框架,学习使用门槛低,适合于需求变化频繁,大型的项目,比如:互联网电子商务网站项目。目前在企业项目中,mybatis
框架使用更多一些。
8.
扩展
8.1.
注解开发
// 3.根据用户Id查询用户,使用注解开发实现
@Select
(
"select * from `user` where id=#{id}"
)
User queryUserById_1(Integer id);
|
// 测试根据用户Id查询用户,测试注解开发
@Test
public
void
queryUserById_1Test(){
// 1.创建sqlSession对象
SqlSession sqlSession =
this
.
sqlSessionFactory
.openSession();
// 2.使用sqlSession对象,获取
mapper
代理对象
// getMapper方法:获取
mapper
代理对象
// type参数:
mapper
接口的class
UserMapper mapper = sqlSession.getMapper(UserMapper.
class
);
// 3.使用
mapper
代理对象,调用方法执行
User user = mapper.queryUserById_1(2);
System.
out
.println(user);
// 4.释放资源
sqlSession.close();
}
|
说明:注解开发,只做了解,企业项目中不推荐使用。
8.2.
缓存
8.2.1.
一级缓存(
sqlSession
级别)
// 测试根据用户Id查询用户,测试一级缓存
@Test
public
void
oneCacheTest
(){
// 1.创建sqlSession对象
SqlSession sqlSession =
this
.
sqlSessionFactory
.openSession();
// 2.使用sqlSession对象,获取
mapper
代理对象
// getMapper方法:获取
mapper
代理对象
// type参数:
mapper
接口的class
UserMapper mapper = sqlSession.getMapper(UserMapper.
class
);
// 3.使用
mapper
代理对象,调用方法执行
User user = mapper.queryUserById(2);
System.
out
.println(user);
System.
out
.println(
"-------------------------------------"
);
User user1 = mapper.queryUserById(2);
System.
out
.println(user1);
// 4.释放资源
sqlSession.close();
}
|
说明:一级缓存
mybatis
框架就已经默认使用,不需要关心。
8.2.2.
二级缓存(
mapper
级别缓存,在多个
SqlSession
之间共享)
8.2.2.1.
在
sqlMapConfig.xml
中,配置开启二级缓存
<!-- 全局参数配置 -->
<
settings
>
<!-- 配置开启二级缓存 -->
<
setting
name
=
"cacheEnabled"
value
=
"true"
/>
</
settings
>
|
8.2.2.2.
修改用户
pojo
,实现序列化接口
public
class
User
implements
java.io.Serializable
{
private
Integer
id
;
//
int
(11) NOT NULL AUTO_INCREMENT,
private
String
username
;
//
varchar
(32) NOT NULL COMMENT '用户名称',
private
Date
birthday
;
// date DEFAULT NULL COMMENT '生日',
private
String
sex
;
// char(1) DEFAULT NULL COMMENT '性别',
private
String
address
;
//
varchar
(256) DEFAULT NULL COMMENT '地址',
|
8.2.2.3.
在
UserMapper.xml
中,开启使用二级缓存
8.2.2.4.
测试二级缓存
// 测试根据用户Id查询用户,测试二级缓存
@Test
public
void
twoCacheTest(){
// 1.创建sqlSession对象
SqlSession
sqlSession =
this
.
sqlSessionFactory
.openSession();
// 2.使用sqlSession对象,获取
mapper
代理对象
// getMapper方法:获取
mapper
代理对象
// type参数:
mapper
接口的class
UserMapper mapper = sqlSession.getMapper(UserMapper.
class
);
// 3.使用
mapper
代理对象,调用方法执行
User user = mapper.queryUserById(2);
System.
out
.println(user);
// 4.释放资源
sqlSession.close();
System.
out
.println(
"-----------------------------------------"
);
// 5.创建sqlSession对象
SqlSession
sqlSession1 =
this
.
sqlSessionFactory
.openSession();
// 6.使用sqlSession对象,获取
mapper
代理对象
// getMapper方法:获取
mapper
代理对象
// type参数:
mapper
接口的class
UserMapper mapper1 = sqlSession1.getMapper(UserMapper.
class
);
// 7.使用
mapper
代理对象,调用方法执行
User user1 = mapper1.queryUserById(2);
System.
out
.println(user1);
// 8.释放资源
sqlSession1.close();
}
说明:
mybatis
框架的二级缓存,只做了解,企业项目中不推荐使用。原因是
mybatis
框架的二级缓存不能实现
细粒度
的控制。
|