像MyBatis、Hibernate都是属于ORM框架
对象关系映射(英语:(Object Relational Mapping,简称ORM)
MySql、Oracle、SqlServer都是关系型数据库
O->R
studentDao.insert(student)
把一个java对象保存到数据库中的一行记录
R->O
Student student = sudentDao.findById(id)
把数据库里面的一行记录封装成一个java对象
![](https://i-blog.csdnimg.cn/blog_migrate/e9389710a75380018efad3c3bad05151.png)
mybatis框架运行流程
![](https://i-blog.csdnimg.cn/blog_migrate/8c25882b227553b8ce7edadc62d42206.png)
POJO(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBean。
SqlSession就是会话,类似于jdbc里面的Connection,开启了这次会话,就可以发送增删改查的操作,
直到你关闭这个会话。
SqlSessionFactory:生产SqlSession的工厂,作用就是构造返回SqlSession。
1、mybatis配置
SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。
mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
2、通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
3、由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
4、mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
5、Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。
6、Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
7、Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
MyBaits快速入门:
Student实体类:
MyBatis框架的核心配置文件:
mybaits.xml
<?
xml
version=
"1.0"
encoding=
"UTF-8"
?>
<!
DOCTYPE
configuration
<
configuration
>
<
environments
default=
"development"
>
<
environment
id=
"development"
>
<!-- 使用JDBC的事物管理 -->
<
transactionManager
type=
"JDBC"
/>
<!-- 配饰数据库连接池 -->
<
dataSource
type=
"POOLED"
>
<
property
name=
"driver"
value=
"com.mysql.jdbc.Driver"
/>
<
property
name=
"username"
value=
"root"
/>
<
property
name=
"password"
value=
"1234"
/>
</
dataSource
>
</
environment
>
</
environments
>
<!-- 加载映射文件 -->
<
mappers
>
<
mapper
resource=
"com/situ/mybatis/entity/StudentMapper.xml"
/>
</
mappers
>
</
configuration
>
StudentMapper.xml
<mapper namespace="student">
<!-- 通过id查找学生 -->
<
select
id=
"selectById"
parameterType=
"Integer"
resultType=
"com.situ.mybatis.entity.Student"
>
select id,name,age,gender,banji_id from student where id=#{id}
</
select
>
</
mapper
>
测试:
@Test
public
void testSelectById()
throws IOException {
String
resource =
"mybatis.xml";
InputStream
inputStream = Resources.
getResourceAsStream(
resource);
// 创建 SqlSessionFactory Session:会话 (连接数据库后就建立了一次会话,有了会话就可以操作数据库)
SqlSessionFactory
sqlSessionFactory =
new SqlSessionFactoryBuilder().build(
inputStream);
// 得到SqlSession
SqlSession
sqlSession =
sqlSessionFactory.openSession();
// 执行
sql
语句
Student
student =
sqlSession.selectOne(
"student.selectById", 59);
System.
out.println(
student);
}
Log4j: 专门用来帮助我们打印日志信息
# 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
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
封装工具类:
public
class MyBatisUtil {
private
static SqlSessionFactory
sqlSessionFactory;
static {
String
resource =
"mybatis.xml";
InputStream
inputStream;
try {
inputStream = Resources.
getResourceAsStream(
resource);
// 创建 SqlSessionFactory Session:会话 (连接数据库后就建立了一次会话,有了会话就可以操作数据库)
sqlSessionFactory =
new SqlSessionFactoryBuilder().build(
inputStream);
}
catch (IOException
e) {
e.printStackTrace();
}
}
public
static SqlSession getSqlSession() {
// 得到SqlSession
SqlSession
sqlSession =
sqlSessionFactory.
openSession();
return
sqlSession;
}
}
@Test
public
void testSelectById1()
throws IOException {
SqlSession
sqlSession = MyBatisUtil.
getSqlSession();
// 执行
sql
语句
Student
student =
sqlSession.selectOne(
"student.selectById", 66);
System.
out.println(
student);
}
typeAliases类型别名:alias
上图是mybatis3.3.0官方文档上提供的别名和java类型的映射关系
int/Integer/ineger
在配置int时通过上表可以看出,即可以是java中的基本类型int,也可以是java中的包装类型Integer,不过在配置为包装类型是必须是java.lang.Integer,所以在配置为int是我们的java接口中的参数类型最好是Integer的。
string/String
对应java中的java.lang.String
map
对应java.util.Map
hashmap
对应java.util.HashMap
list
对应java.util.List
arraylist
对应java.util.ArrayList
<
settings
>
<!-- 下划线字段对应实体类驼峰命名 数据库表:banji_id 映射到类里面:banjiId -->
<
setting
name=
"mapUnderscoreToCamelCase"
value=
"true"
/>
</
settings
>
<
typeAliases
>
<!--
<typeAlias alias="Student" type="com.situ.mybatis.entity.Student"/>
<typeAlias alias="
Banji
" type="com.situ.mybatis.entity.Banji"/> -->
<!-- 扫描包里面的类,批量起别名,别名即类名,不区分大小写 -->
<
package
name=
"com.situ.mybatis.entity"
/>
</
typeAliases
>
基本增删改查的操作:
<!-- 返回的是List<Student>,但是resultType直接写里面的类型就可以 -->
<
select
id=
"selectAll"
resultType=
"Student"
>
SELECT
<
include
refid=
"studentColumns"
/> FROM `student`
</
select
>
<!-- 对于更新类的操作返回的是影响的函数,但是resultType不需要写 -->
<
delete
id=
"deleteById"
parameterType=
"Integer"
>
DELETE FROM `student` WHERE `id`=#{id}
</
delete
>
<
insert
id=
"insert"
parameterType=
"Student"
>
INSERT INTO `student`(`name`,`age`,`gender`,`banji_id`) VALUES(#{name},#{age},#{gender},#{banjiId})
</
insert
>
<
update
id=
"update"
parameterType=
"Student"
>
UPDATE
`student`
SET
`name`=#{name},
`age`=#{age},
`gender`=#{gender},
`banji_id`=#{banjiId}
WHERE
`id`=#{id}
</
update
>
@Test
public
void testDeleteById()
throws IOException {
// Setting autocommit to false on JDBC Connection
// MyBatis把JDBC的autocommit设置为false,
// 当执行delete的时候并没有真正提交到数据库,对于更新类的操作需要手动提交。
// 在JDBC里面默认不需要用户手动提交因为autocommit 默认就是true,执行executeUpdate
// 的时候直接修改了数据库
SqlSession sqlSession = MyBatisUtil.getSqlSession();
int count = sqlSession.delete(
"student.deleteById", 59);
System.out.println(
"count: " + count);
// 对于更新类的操作需要手动提交
sqlSession.close();
}
Sql片段:
Sql中可以将重复代码提取出来,使用include引用,达到sql重用的目的。
<
sql
id=
"studentColums"
>
id,name,age,gender,banji_id
</
sql
>
<!-- 通过id查找学生
refid
reference
-->
<
select
id=
"selectById"
parameterType=
"Integer"
resultType=
"Student"
>
select
<
include
refid=
"studentColums"
/> from student where id=#{id}
</
select
>
输入映射和输出映射总结:
输入映射:
parameterType(输入类型)
1、传递简单类型:selectById(Integer id)
使用时候#{id}
2、传递实体类:insert(Student student)
使用时候#{age}括号中的值为实体类中属性的名字。
3、传递Map
@Test
public
void testSelectByPage()
throws IOException {
SqlSession
sqlSession = MyBatisUtil.
getSqlSession();
int
pageNo = 2;
int
pageSize = 3;
int
offset = (
pageNo - 1) *
pageSize;
Map<String, Integer>
map =
new HashMap<String, Integer>();
map.put(
"offset",
offset);
map.put(
"pageSize",
pageSize);
List<Student>
list =
sqlSession.selectList(
"student.selectByPage",
map);
for (Student
student :
list) {
System.
out.println(
student);
}
}
<
select
id=
"selectByPage"
parameterType=
"Map"
resultType=
"Student"
>
SELECT
<
include
refid=
"studentColumns"
/> FROM `student` LIMIT #{offset},#{pageSize}
</
select
>
输出映射:
1、基本数据类型:
查找一共有多少学生
<
select
id=
"selectTotalCount"
resultType=
"Integer"
>
SELECT count(*) FROM `student`
</
select
>
@Test
public
void testSelectTotalCount()
throws IOException {
SqlSession sqlSession = MyBatisUtil.getSqlSession();
int count = sqlSession.selectOne(
"student.selectTotalCount");
System.out.println(
"count: " + count);
}
2、输出实体类:Student
3、输出集合:List<Student>
resultMap:
如果查询出来的列名和实体类的属性不一致,通过定义一个resultMap对列名和实体类属性名做一个映射关系。
resultMap 元素是 MyBatis 中最重要最强大的元素。
结果集的映射是 MyBatis 最强大的特性,对其有一个很好的理解的话,许多复杂映射的情形都能迎刃而解。使用 resultMap 或 resultType,但不能同时使用。
![](https://i-blog.csdnimg.cn/blog_migrate/de43304806882dd8dff907ff66e90587.png)
<!-- resultMap最终是要将结果映射到Student上
当实体类的属性名和表的字段名不一致的时候,必须要写这个映射 -->
<
resultMap
type=
"Student"
id=
"studentMap"
>
<!-- 映射主键属性:如果有多个主键字段,则定义多个id -->
<!-- property:类的属性名 -->
<!-- column:表的字段名 -->
<
id
property=
"id"
column=
"id"
/>
<!-- result定义普通属性 -->
<
result
property
=
"name"
column
=
"student_name"
/>
<
result
property=
"age"
column=
"age"
/>
<
result
property=
"gender"
column=
"gender"
/>
</
resultMap
>
<
select
id=
"selectAll"
resultMap=
"studentMap"
>
select id,
student_name,age,gender from student
</select>