这篇文章主要给大家介绍了关于Mybatis新手教程之简单入门的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
1、Mybatis概述
MyBatis 是支持普通 SQL 查询(相比较于Hibernate的封装,Mybatis是半自动化的JDBC封装,一个特点就是Mybatis执行的SQL查询语句需要自己在配置文件中写),存储过程和高级映射的优秀持久层框架。MyBatis 消除了几乎所有的 JDBC 代码和参数的手工设置以及对结果集的检索。MyBatis 可以使用简单的XML 或注解用于配置和原始映射,将接口和 Java 的 POJO(Plain Old Java Objects,普通的Java 对象)映射成数据库中的记录。
2、Mybatis原理解析
下面以Mybatis简单的执行流程
1、加载mybatis全局配置文件(数据源、mapper映射文件等),解析配置文件,MyBatis基于XML配置文件生成Configuration,和一个个MappedStatement(包括了参数映射配置、动态SQL语句、结果映射配置),其对应着标签项。
2、SqlSessionFactoryBuilder通过Configuration对象生成SqlSessionFactory,用来开启SqlSession。
3、SqlSession对象完成和数据库的交互:
a、用户程序调用mybatis接口层api(即Mapper接口中的方法)
b、SqlSession通过调用api的Statement ID找到对应的MappedStatement对象
c、通过Executor(负责动态SQL的生成和查询缓存的维护)将MappedStatement对象进行解析,sql参数转化、动态sql拼接,生成jdbc Statement对象
d、JDBC执行sql。
e、借助MappedStatement中的结果映射关系,将返回结果转化成HashMap、JavaBean等存储结构并返回。
下面是Mybatis的框架原理图
3、Mybatis简单实例
(1)导入相关jar包以及Mybatis运行环境核心jar包和连接数据库的包
(2)创建一张简单的数据表
(3)创建Java对象(PO类型)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package
cn.mybatis.po;
public
class
User {
private
int
id;
private
String username;
private
String password;
private
String address;
private
String sex;
public
int
getId() {
return
id;
}
public
String getUsername() {
return
username;
}
public
String getPassword() {
return
password;
}
public
String getAddress() {
return
address;
}
public
String getSex() {
return
sex;
}
public
void
setId(
int
id) {
this
.id = id;
}
public
void
setUsername(String username) {
this
.username = username;
}
public
void
setPassword(String password) {
this
.password = password;
}
public
void
setAddress(String address) {
this
.address = address;
}
public
void
setSex(String sex) {
this
.sex = sex;
}
@Override
public
String toString() {
return
"User{"
+
"id="
+ id +
", username='"
+ username + '\
''
+
", password='"
+ password + '\
''
+
", address='"
+ address + '\
''
+
", sex='"
+ sex + '\
''
+
'}'
;
}
}
User实体类
(4)创建Mybatis核心配置文件(SqlMapConfig.xml)
在核心配置文件配置连接数据库的相关信息,(如果是和Spring整合,则可以放在Spring配置文件中进行对数据库的配置)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<
configuration
>
<
environments
default
=
"development"
>
<
environment
id
=
"development"
>
<
transactionManager
type
=
"JDBC"
>
transactionManager
>
<
dataSource
type
=
"POOLED"
>
<
property
name
=
"driver"
value
=
"com.mysql.jdbc.Driver"
/>
<
property
name
=
"url"
value
=
"jdbc:mysql:///mybatis01"
/>
<
property
name
=
"username"
value
=
"root"
/>
<
property
name
=
"password"
value
=
"123"
/>
dataSource
>
environment
>
environments
>
<
mappers
>
<
mapper
resource
=
"UserMapper.xml"
/>
mappers
>
configuration
>
Mybatis核心配置文件
(5)创建一个Mapper.xml文件,对应编写所需要的Sql查询操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<
mapper
namespace
=
"test"
>
<
select
id
=
"findUserById"
parameterType
=
"int"
resultType
=
"cn.mybatis.po.User"
>
SELECT * FROM t_user WHERE id = #{id}
select
>
mapper
>
UserMapper配置文件
(7)创建测试程序,对刚刚编写的select查询进行测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package
cn.mybatis.first;
import
cn.mybatis.po.User;
import
org.apache.ibatis.io.Resources;
import
org.apache.ibatis.session.SqlSession;
import
org.apache.ibatis.session.SqlSessionFactory;
import
org.apache.ibatis.session.SqlSessionFactoryBuilder;
import
java.io.IOException;
import
java.io.InputStream;
public
class
Test {
public
User findUserById()
throws
IOException {
//得到mybatis配置文件
String resource =
"SqlMapConfig.xml"
;
//得到配置文件的文件流信息
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建会话工厂 传入mybatis的配置文件信息
SqlSessionFactory sqlSessionFactory =
new
SqlSessionFactoryBuilder().build(inputStream);
//通过会话工厂得到SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//通过sqlSession来操作数据库
//第一个参数就是映射文件中statment的id:namespace +statment的id
//第二个参数就是制定映射文件中的parameterType类型的参数
User user = sqlSession.selectOne(
"test.findUserById"
,
1
);
//System.out.println(user);
//释放会话资源
try
{
sqlSession.close();
}
catch
(Exception e) {
e.printStackTrace();
}
return
user;
}
public
static
void
main(String[] args) {
// TODO Auto-generated method stub
Test test =
new
Test();
try
{
System.out.println(test.findUserById());
}
catch
(IOException e) {
e.printStackTrace();
}
}
}
Test测试程序
(8)加入Log4j日志文件
1
2
3
4
5
6
7
8
9
### direct log messages to stdout ###
log4j.rootLogger=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
Log4j.properties
(9)测试结果
4.其他CRUD操作
(1)insert操作
在Mapper文件中添加响应的SQL配置,以及使用MySQL中的LAST_INSERT_ID()函数得到增加的数据的主键值
1
2
3
4
5
6
7
8
9
10
11
12
13
"addUser"
parameterType=
"cn.mybatis.po.User"
>
"id"
order=
"AFTER"
resultType=
"java.lang.Integer"
>
SELECT LAST_INSERT_ID()
INSERT INTO t_user(id,username,password,address,sex) VALUES(#{id},#{username},#{password},#{address}, #{sex});
插入数据的日志信息,没有使用sqlSession.commit();之前的日志情况
从上面的图中可以看出,没有添加commit的时候,事务进行了回滚,所以要想添加数据,需要自己手动提交(在没有整合Spring之前)
附上insertUser的函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public
void
inserUser()
throws
IOException {
//得到配置文件的文件流信息
InputStream inputStream = Resources.getResourceAsStream(
"SqlMapConfig.xml"
);
SqlSessionFactory sqlSessionFactory =
new
SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
User user =
new
User(
"World"
,
"1234"
,
"武汉市"
,
"男"
);
sqlSession.insert(
"test.addUser"
,user);
System.out.println(user.getId());
sqlSession.commit();
//释放会话资源
try
{
sqlSession.close();
}
catch
(Exception e) {
e.printStackTrace();
}
}
inserUser函数
(2)模糊查询
首先配置Mapper文件,${}和#{}的简单区别如下:
1
2
3
4
5
6
7
8
9
10
"findUserByUsername"
parameterType=
"java.lang.String"
resultType=
"cn.mybatis.po.User"
>
SELECT * FROM t_user WHERE username LIKE
'%${value}%'
使用查询的时候碰到一个小错误,由于之前测试的insert方法,其中在User实体类中添加了有参构造函数,所以出现了下面的错误,分析原因就是:使用Mybatis查询的时候需要在实体类中加入无参构造方法(当然如果实体类本身没有构造函数,就会是默认的无参构造函数)
附上findByUsername的函数实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public
void
findUserByUsername()
throws
IOException {
//得到配置文件的文件流信息
InputStream inputStream = Resources.getResourceAsStream(
"SqlMapConfig.xml"
);
SqlSessionFactory sqlSessionFactory =
new
SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
List userList = sqlSession.selectList(
"test.findUserByUsername"
,
"u"
);
System.out.println(userList);
//释放会话资源
try
{
sqlSession.close();
}
catch
(Exception e) {
e.printStackTrace();
}
}
findByUsername函数实现
(3)删除操作
首先在Mapper中配置删除的操作
1
2
3
"deleteUser"
parameterType=
"java.lang.Integer"
>
DELETE FROM t_user WHERE id = #{value}
运行测试程序,同insert中一样,需要手动提交事务,如下面所示
最终结果:
数据表中删除了编号为10的数据记录
5.细节整理
(1)关于示例程序中一些相关类的理解
a)SqlSessionFactoryBuilder
用来创建SqlSessionFactory。因为SqlSessionFactory使用了单例模式,所以不需要使用单例模式来管理SqlSessionFactoryBuilder,只需要在创建SqlSessionFactory时 候使用一次就可以
b)SqlSessionFactory
会话工厂,用来创建SqlSession。可以使用单例模式来管理SqlSessionFactory这个会话工厂,工厂创建之后,就一直使用一个实例。
c)SqlSession
面向程序员的接口,提供了操作数据库的方法。SqlSession是线程不安全的(原因:在SqlSession实现类中除了接口中的操作数据库的方法之外,还有数据域的属性,比如说一些提交的数据等等,所以在多线程并发请求的时候,会导致线程不安全),所以我们可以将SqlSession使用在方法体里面,这样每个线程都有自己的方法,就不会冲突
(2)Mybatis中mapper映射文件
如同解释Mybatis执行原理的时候一样,Mapper映射文件中配置的Sql语句,实际上在执行的时候都被封装称为一个个MapperStatment对象,即Mapper映射文件是按照statment来管理不同的Sql。在编写程序的时候,我们在使用SqlSession其中的操作数据库的方法(selectOne,selectList等等)的时候,传入的参数除了实参(id,模糊查询的字符串等等)之外,还需要传入的就是相应的Sql位置,而Sql是被Statment管理,所以就是传入namespace+statmentId
(3)占位符
#{id}:其中的id表示的就是接受的输入参数,参数名称就是id,这里指出:如果输入参数是简单类型,#{}中的参数名可以任意设置(value或者其他名称)
${value}:表示将输入的参数不加任何的修饰,直接作为字符串拼接在SQL中但是这样直接拼接,容易导致SQL注入的隐患${value}中的value表示接受的输入参数,注意如果输入参数是简单类型,其中的形参只能用value
(4)别名定义
①单个别名的定义
1
2
3
4
"cn.mybatis.po.User"
alias=
"user"
>
定义别名后的使用
1
2
3
"findUserByIdTest"
parameterType=
"int"
resultType=
"user"
>
SELECT * FROM t_user WHERE id = #{id}
②批量别名的定义
1
2
3
4
<
package
name=
"cn.mybatis.po"
>
package
>
(5)在SqlMapConfig.xml中加载Mapper映射文件的时候,除了通过resource的方式,还可以使用mapper接口加载的方式来实现
①首先先注意一点:
在配置mybatis-config.xml时,其中的节点是有顺序的,配置顺序依次为:
properties/settings/typeAliases/typeHandlers/objectFactory/objectWrapperFactory/plugins/environments/databaseIdProvider/mappers
②使用mapper加载的方式,要将mapper接口和mapper配置文件放在同一目录下面,并且文件名称一致,而且要遵循mapper代理的方式进行开发
1
2
3
class
=
"cn.mybatis.mapper.UserMapper"
>
6.Mybatis开发dao方法简介
(1)使用dao接口+实现类的方式
a)首先编写接口,如同一般编写模式方式进行编写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package
cn.mybatis.dao;
import
cn.mybatis.po.User;
/**
* 原始Dao方式开发:dao接口+dao实现类的方式
*/
public
interface
UserDao {
//根据id查询信息
public
User findUserById(
int
id)
throws
Exception;
//添加信息
public
void
insertUser(User user)
throws
Exception;
//删除信息
public
void
deleteUser(
int
id)
throws
Exception;
}
dao接口
b)然后编写接口实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package
cn.mybatis.dao.daoImpl;
import
cn.mybatis.dao.UserDao;
import
cn.mybatis.po.User;
import
org.apache.ibatis.session.SqlSession;
import
org.apache.ibatis.session.SqlSessionFactory;
import
org.junit.Test;
public
class
UserDaoImpl
implements
UserDao {
//使用构造方法注入SqlSessionFactory
private
SqlSessionFactory sqlSessionFactory;
public
UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
this
.sqlSessionFactory = sqlSessionFactory;
}
@Override
@Test
public
User findUserById(
int
id)
throws
Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = sqlSession.selectOne(
"test.findUserById"
,id);
sqlSession.close();
return
user;
}
@Override
public
void
insertUser(User user)
throws
Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
// User user1 = new User("test1","123","洪山区","男");
sqlSession.insert(
"test.findUserById"
,user);
sqlSession.commit();
sqlSession.close();
}
@Override
public
void
deleteUser(
int
id)
throws
Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.delete(
"test.findUserById"
,id);
sqlSession.commit();
sqlSession.close();
}
}
dao接口实现类
c)Mapper配置文件和SqlConfig配置文件不变
d)使用Junit进行测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package
cn.mybatis.testdao;
import
cn.mybatis.dao.UserDao;
import
cn.mybatis.dao.daoImpl.UserDaoImpl;
import
cn.mybatis.po.User;
import
org.apache.ibatis.io.Resources;
import
org.apache.ibatis.session.SqlSessionFactory;
import
org.apache.ibatis.session.SqlSessionFactoryBuilder;
import
org.junit.After;
import
org.junit.Before;
import
org.junit.Test;
import
java.io.InputStream;
public
class
UserDaoImplTest {
private
SqlSessionFactory sqlSessionFactory;
@Before
public
void
setUp()
throws
Exception {
InputStream inputStream = Resources.getResourceAsStream(
"SqlMapConfig.xml"
);
sqlSessionFactory =
new
SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public
void
testFindUserById()
throws
Exception{
//创建UserDao的对象
UserDao userDao =
new
UserDaoImpl(sqlSessionFactory);
//调用UserDao的方法
User user = userDao.findUserById(
1
);
System.out.println(user );
}
}
Junit测试
e)测试结果
f)原始dao方法的问题
①dao接口实现中存在大量的模板方法(即很多重复性的代码 )
②调用SqlSession方法的时候将statmentid硬编码了
③条用SqlSession方法的时候传入的参数,由于使用泛型,所以在编译阶段不会报错(即使传入参数错误)
(2)使用Mapper代理的方法(即只需要Mapper接口)
(a)使用mapper方式的规范
①在使用mapper代理的方式中,namespace的值应该是mapper接口的路径
②在mapper.java接口文件中的接口方法名称和mapper.xml中的statment的id一致
③在mapper.java接口文件中的接口方法的输入参数和mapper.xml中的statment的parameterType一致
④在mapper.java接口文件中的接口方法的返回值类型和mapper.xml中的statment的resultType一致
(b)查询、删除操作实例
①编写mapper.xml配置文件,其中包含select和delete的sql配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<
mapper
namespace
=
"cn.mybatis.mapper.UserMapper"
>
<
select
id
=
"findUserById"
parameterType
=
"int"
resultType
=
"cn.mybatis.po.User"
>
SELECT * FROM t_user WHERE id = #{id}
select
>
<
delete
id
=
"deleteUser"
parameterType
=
"java.lang.Integer"
>
DELETE FROM t_user WHERE id = #{value}
delete
>
mapper
>
mapper.xml配置文件
②编写mapper接口,按照mapper代理的方式开发规范来编写mapper的接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package
cn.mybatis.testmapper;
import
cn.mybatis.mapper.UserMapper;
import
cn.mybatis.po.User;
import
org.apache.ibatis.io.Resources;
import
org.apache.ibatis.session.SqlSession;
import
org.apache.ibatis.session.SqlSessionFactory;
import
org.apache.ibatis.session.SqlSessionFactoryBuilder;
import
org.junit.After;
import
org.junit.Before;
import
org.junit.Test;
import
java.io.InputStream;
public
class
UserMapperTest {
private
SqlSessionFactory sqlSessionFactory;
@Before
public
void
setUp()
throws
Exception {
InputStream inputStream = Resources.getResourceAsStream(
"SqlMapConfig.xml"
);
sqlSessionFactory =
new
SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public
void
testFindUserById()
throws
Exception{
SqlSession sqlSession = sqlSessionFactory.openSession();
//得到UserMapper的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.
class
);
User user = userMapper.findUserById(
9
);
System.out.println(user);
}
@Test
public
void
testDeleteUser()
throws
Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.
class
);
userMapper.deleteUser(
9
);
sqlSession.commit();
}
@After
public
void
tearDown()
throws
Exception {
}
}
mapper接口
③Junit测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package
cn.mybatis.testmapper;
import
cn.mybatis.mapper.UserMapper;
import
cn.mybatis.po.User;
import
org.apache.ibatis.io.Resources;
import
org.apache.ibatis.session.SqlSession;
import
org.apache.ibatis.session.SqlSessionFactory;
import
org.apache.ibatis.session.SqlSessionFactoryBuilder;
import
org.junit.After;
import
org.junit.Before;
import
org.junit.Test;
import
java.io.InputStream;
public
class
UserMapperTest {
private
SqlSessionFactory sqlSessionFactory;
@Before
public
void
setUp()
throws
Exception {
InputStream inputStream = Resources.getResourceAsStream(
"SqlMapConfig.xml"
);
sqlSessionFactory =
new
SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public
void
testFindUserById()
throws
Exception{
SqlSession sqlSession = sqlSessionFactory.openSession();
//得到UserMapper的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.
class
);
User user = userMapper.findUserById(
8
);
System.out.println(user);
}
@Test
public
void
testDeleteUser()
throws
Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.
class
);
userMapper.deleteUser(
8
);
}
@After
public
void
tearDown()
throws
Exception {
}
}
Junit测试
④查询结果展示
⑤删除结果展示
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。