第一节:对象关系映射(ORM)
对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。本质上就是将数据从一种形式转换到另外一种形式。
这也同时暗示着额外的执行开销;然而,如果ORM作为一种中间件实现,则会有很多机会做优化,而这些在手写的持久层并不存在。 更重要的是用于控制转换的元数据需要提供和管理;但是同样,这些花费要比维护手写的方案要少;而且就算是遵守ODMG规范的对象数据库依然需要类级别的元数据。(百度百科)
ORM : Object RelationShip Mapping
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(sDAO)
mybaits的代码由github.com管理,下载地址:https://github.com/mybatis/mybatis-3/releases
依赖信息
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
学习地址:http://www.mybatis.org/mybatis-3/zh/index.html
使用版本:3.4.6
1.1 概述
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
MyBatis主要就完成2件事情
- 封装JDBC操作
- 利用反射打通Java类与SQL语句之间的相互转换
MyBatis的主要设计目的就是让我们对执行SQL语句时对输入输出的数据管理更加方便,所以方便地写出SQL和方便地获取SQL的执行结果才是MyBatis的核心竞争力。
1.2 特点
- 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
- 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多。
- 解除sql与程序代码的耦合:通过提供DAL层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
- 提供映射标签,支持对象与数据库的orm字段关系映射
- 提供对象关系映射标签,支持对象关系组建维护
- 提供xml标签,支持编写动态sql
1.3 体系结构

mybatis配置文件,包括Mybatis全局配置文件和Mybatis映射文件,其中全局配置文件配置了数据源、事务等信息;映射文件配置了SQL执行相关的信息。
- mybatis通过读取配置文件信息(全局配置文件和映射文件),构造出SqlSessionFactory,即会话工厂。
- 通过SqlSessionFactory,可以创建SqlSession即会话。Mybatis是通过SqlSession来操作数据库的。
- SqlSession本身不能直接操作数据库,它是通过底层的Executor执行器接口来操作数据库的。Executor接口有两个实现类,一个是普通执行器,一个是缓存执行器(默认)。
- Executor执行器要处理的SQL信息是封装到一个底层对象MappedStatement中。该对象包括:SQL语句、输入参数映射信息、输出结果集映射信息。其中输入参数和输出结果的映射类型包括java的简单类型、HashMap集合对象、POJO对象类型。
第二节:MyBatis入门
2.1 下载MyBatis
使用Maven创建项目,此步可以省略
2.2 搭建MyBatis环境
第一步:创建数据库
创建数据库mybatis_01,并创建表、添加数据
#用户表
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) NOT NULL COMMENT '用户名称',
`birthday` date DEFAULT NULL COMMENT '生日',
`sex` char(1) DEFAULT NULL COMMENT '性别',
`address` varchar(256) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
#订单表
CREATE TABLE `orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL COMMENT '下单用户id',
`number` varchar(40) NOT NULL COMMENT '订单号',
`createtime` datetime NOT NULL COMMENT '创建订单时间',
`note` varchar(100) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`),
KEY `FK_orders_1` (`user_id`),
CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
insert into `user`(`id`,`username`,`birthday`,`sex`,`address`) values (1,'王五',NULL,'2',NULL),(10,'张三','2014-07-10','1','北京市'),(16,'张小明',NULL,'1','湖南长沙'),(22,'陈小明',NULL,'1','河南郑州'),(24,'张三丰',NULL,'1','河北保定'),(25,'陈小明',NULL,'1','深圳'),(26,'王五',NULL,NULL,NULL);
insert into `orders`(`id`,`user_id`,`number`,`createtime`,`note`) values (3,1,'1000010','2015-02-04 13:22:35',NULL),(4,1,'1000011','2015-02-03 13:22:41',NULL),(5,10,'1000012','2015-02-12 16:13:23',NULL);
第二步:创建java项目,并添加依赖
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
第三步:加入配置文件
在resources目录中添加Mybatis的核心配置mybatis-config.xml、log4j日志文件log4j.properties
<?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配置将废除 -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis_01?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
</configuration>
### set log levels - for more verbose logging change 'info' to 'debug' , 'off' ###
log4j.rootLogger=info, stdout,file
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=d:\\mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
第四步:创建POJO
domain
bean
entity
pojo
在不同的场合使用的对象的分类:
po : Persistent Object (持久化对象)
vo:View Object (视图对象 ,PageBean)
dto: Data Transfer Object (数据传输对象 ,系统与系统之间传递数据)
bo : Business Object (业务对象)
什么是POJO:
POJO是Plain Old Java Objects的缩写,POJO实质上可以理解为简单的实体类,顾名思义POJO类的作用是方便程序员使用数据库中的数据表,对于广大的程序员,可以很方便的将POJO类当做对象来进行使用,当然也是可以方便的调用其get,set方法。
User.java
User.java
public class User {
private int id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
//getter和setter
}
第五步:加入sql映射文件
在resources目录下创建com.qf.mapper文件夹(注意要一个一个的创建),然后创建UserMapper.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>
第六步:加载映射文件
MyBatis框架需要加载UserMapper.xml映射文件,将UserMapper.xml添加在mybatis-config.xml,如下:
<mappers>
<mapper resource="com/qf/mapper/UserMapper.xml"/>
</mappers>
2.3 实现根据id查询用户
2.3 实现根据id查询用户
(1)使用SQL语句:SELECT * FROM user WHERE id = 1
(2)映射文件中添加:
<?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">
<!-- id:statement的id 或者叫做sql的id-->
<!-- parameterType:声明输入参数的类型 -->
<!-- resultType:声明输出结果的类型,应该填写pojo的全路径 -->
<!-- #{}:输入参数的占位符,相当于jdbc的?
如果是简单类型(基本类型、字符串类型)名称可以任意-->
<select id="queryUserById" parameterType="Integer"
resultType="com.qf.pojo.User">
SELECT * FROM `user` WHERE id = #{id}
</select>
</mapper
(3)测试程序:
1. 创建SqlSessionFactoryBuilder对象
2. 加载SqlMapConfig.xml配置文件
3. 创建SqlSessionFactory对象
4. 创建SqlSession对象
5. 执行SqlSession对象执行查询,获取结果User
6. 打印结果
7. 释放资源
MyBatis框架中涉及到的几个API:
- SqlSessionFactoryBuilder:该对象负责根据MyBatis配置文件SqlMapConfig.xml构建SqlSessionFactory实例
- SqlSessionFactory:每一个MyBatis的应用程序都以一个SqlSessionFactory对象为核心。该对象负责创建SqlSession对象实例。
- SqlSession:该对象包含了所有执行SQL操作的方法,用于执行已映射的SQL语句
代码如下
@Test
public void test1(){
try {
// 1. 创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 2. 加载SqlMapConfig.xml配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
// 3. 创建SqlSessionFactory对象
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(inputStream);
//4.创建SqlSession
SqlSession sqlSession = factory.openSession();
//5执行
User user = sqlSession.selectOne("test.queryUserById", 1);
// 6. 打印结果
System.out.println(user);
// 7. 释放资源
sqlSession.close();
} catch (IOException e) {
e.printStackTrace();
}
}
2.4 根据用户名模糊查询用户
使用SQL语句:
SELECT * FROM `user` WHERE username LIKE '%王%'
映射文件中添加
方式1
<select id="queryUserByUsername1" parameterType="String"
resultType="com.qf.pojo.User">
SELECT * FROM `user` WHERE username LIKE #{username}
</select>
测试代码
@Test
public void test2() throws Exception {
// 1. 创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 2. 加载SqlMapConfig.xml配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
// 3. 创建SqlSessionFactory对象
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(inputStream);
// 4. 创建SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 5. 执行SqlSession对象执行查询,获取结果User
// 查询多条数据使用selectList方法
List<Object> list = sqlSession.selectList("queryUserByUsername1", "%王%");
// 6. 打印结果
for (Object user : list) {
System.out.println(user);
}
// 7. 释放资源
sqlSession.close();
}
方式2:
<!-- 如果传入的参数是简单数据类型,${}里面必须写value -->
<select id="queryUserByUsername2" parameterType="string"
resultType="com.qf.pojo.User">
SELECT * FROM `user` WHERE username LIKE '%${value}%'
</select>
测试代码:
//省略
// 4. 创建SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 5. 执行SqlSession对象执行查询,获取结果User
// 查询多条数据使用selectList方法
List<Object> list = sqlSession.selectList("queryUserByUsername2", "王");
// 6. 打印结果
for (Object user : list) {
System.out.println(user);
}
// 7. 释放资源
sqlSession.close();
#{}和${}的区别
(1)#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换。
#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中
可以是value或其它任意名称。
(2)${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收
简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。
parameterType和resultType
parameterType:指定输入参数类型,MyBatis通过ognl从输入对象中获取参数值拼接在sql中。
resultType:指定输出结果类型,MyBatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。如果有多条数据,则分别进行映射,并把对象放到容器List中
2.5 实现新增用户
使用的SQL语句
INSERT INTO `user` (username,birthday,sex,address) VALUES
('aaa','2010-05-20','1','南京')
映射文件配置标签,用于执行插入操作。
<!-- 保存用户 -->
<insert id="add" parameterType="com.qf.pojo.User">
INSERT INTO `user`
(username,birthday,sex,address) VALUES
(#{username},#{birthday},#{sex},#{address})
</insert>
测试代码
@Test
public void test4() {
// 4. 创建SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 5. 执行SqlSession对象执行保存
// 创建需要保存的User
User user = new User();
user.setUsername("黄晓明");
user.setSex("1");
user.setBirthday(new Date());
user.setAddress("南京");
sqlSession.insert("test.add", user);
System.out.println(user);
// 需要进行事务提交
sqlSession.commit();
// 7. 释放资源
sqlSession.close();
}
在插入操作完成之前或之后,可以配置标签获得生成的主键的值,获得插入之前还是之后的值,可以通过配置order属性来指定。
LAST_INSERT_ID:该函数是mysql的函数,获取自增主键的ID,它必须配合insert语句一起使用
<!-- 添加用户 -->
<!-- selectKey:查询主键,在标签内需要输入查询主键的sql -->
<!-- order:指定查询主键的sql和insert语句的执行顺序,相当于insert语句来说 -->
<!-- LAST_INSERT_ID:该函数是mysql的函数,获取自增主键的ID,它必须配合insert语句一起使用 -->
<insert id="addUser" parameterType="com.qf.po.User”>
<!-- selectKey 标签实现主键返回 -->
<!-- keyProperty:主键对应的pojo中的哪一个属性 -->
<!-- order:设置在执行insert语句前执行查询id的sql,还是在执行insert语句之后执行查询id的sql -->
<!-- resultType:设置返回的id的类型 -->
<selectKey keyProperty="id" resultType="int" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTO USER(username,birthday,sex,address)
VALUES(#{username},#{birthday},#{sex},#{address})
</insert>
测试代码如下,直接执行配置的statement,可以查看结果。
SqlSession session = sqlSessionFactory.openSession();
session.insert("test.add",user);
session.commit();
2.6 实现删除操作
使用SQL语句
DELETE FROM `user` WHERE id = 47
在映射文件文件中使用标签配置删除的statement。
<delete id="deleteUser" parameterType="int">
delete from user where id=#{id}
</delete>
测试代码如下,直接执行配置的statement,可以查看结果。
SqlSession session = sqlSessionFactory.openSession();
session.delete("test.deleteUser",1);
session.commit();
2.7 实现修改操作
使用SQL语句
UPDATE `user` SET username = '马云' WHERE id = 26
在映射文件使用标签配置修改的statement。
<update id="updateUser" parameterType="com.qf.pojo.User">
update user set username=#{username},sex=#{sex},birthday=#{birthday},address=#{address} where id= #{id}
</update>
测试代码如下,直接执行配置的statement,可以查看结果。
//构建user参数,没有赋值的属性采取默认值
User user = new User();
user.setId(20);
user.setUsername("admin");
user.setAddress("beijing");
// 第一个参数:statement的id,建议:namespace.statementId(确保唯一)
// 第二个参数:入参的值,它的类型要和映射文件中对应的statement的入参类型一致
sqlSession.update("test.updateUser", user);


被折叠的 条评论
为什么被折叠?



