一、MyBatis的介绍:
MyBatis本是apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到google code,并改名为MyBatis。
册驱动、 创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。MyBtis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需关注sql本身,而不需要花费精力去处理如注
MyBatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatement、Callablestatement)配置起来,并通过Java
对象和statement中的sql进行映射生成最终的执行sql语句,最后由MyBatis框架执行sql并将结果映射成java对象并返回。
二、MyBatis的入门案例以及基本配置:
需求:使用MyBatis完成增删改查的基本功能
1、创建数据库,加入测试数据(以下是sql执行文件)
/*
Navicat MySQL Data Transfer
Source Server : RBAC_permission
Source Server Version : 50527
Source Host : localhost:3306
Source Database : mybatis
Target Server Type : MYSQL
Target Server Version : 50527
File Encoding : 65001
Date: 2018-01-27 20:08:42
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
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=31 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', '王五', null, '2', null);
INSERT INTO `user` VALUES ('10', '张三', '2014-07-10', '1', '北京市');
INSERT INTO `user` VALUES ('16', '张小明', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('24', '张三丰', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('25', '狗剩', null, '1', '北海道');
INSERT INTO `user` VALUES ('26', '王五', null, null, null);
INSERT INTO `user` VALUES ('28', '李逍遥', '2017-11-23', '男', '青岛');
INSERT INTO `user` VALUES ('30', '菜呀', '2017-11-23', '男', '中国');
2、创建java工程,加入mybtis的核心包、依赖包、数据驱动包(项目结构图如下)
3、创建SqlMapConfig.xml配置文件。SqlMapConfig是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>
<typeAliases>
<!--
typeAlias: 起别名
type: 指定pojo的类型
alias: 别名,大小写不敏感
<typeAlias type="com.heima.pojo.User" alias="user"/>
-->
<!--
package: 批量起别名,
name: 指定扫描的报名
别名: 就是类名,大小写不敏感
-->
<package name="com.evil.pojo"/>
</typeAliases>
<!-- 和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?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<!-- 加载映射文件 -->
<mappers>
<!--
mapper标签: 引入映射文件
url: 绝对路径,不推荐使用
resource: 相对路径
-->
<!-- <mapper resource="User.xml"/> -->
<!--
class: 指定接口的全路径名称
1: 接口文件和映射文件必须在同一个包下
2: 接口文件和映射文件名称必须相同,除了扩展名
<mapper class="com.evil.mapper.UserMapper"/>
-->
<!--
package标签: 批量扫描映射文件
name: 指定扫描的包名
1: 接口文件和映射文件必须在同一个包下
2: 接口文件和映射文件名称必须相同,除了扩展名
-->
<package name="com.evil.mapper"/>
</mappers>
</configuration>
4.创建实体类
package com.evil.pojo;
import java.util.Date;
public class User {
/**
*
*/
private Integer id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
..............getXXX/setXX略
5.创建接口(相当于Dao,采用的是Mybatis的动态代理方式)
Mapper接口开发方法只需要我们编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象。
Mapper接口开发需要遵循以下规范:
1、映射文件的Namespace必须等于接口的全路径名称
2、映射文件的sql唯一标示id必须等于接口方法的名称
3、映射文件的parameterType必须等于接口方法的参数类型
4、映射文件的resultType必须等于接口方法的返回类型
package com.evil.mapper;
import java.util.List;
import com.evil.pojo.User;
public interface UserMapper {
//根据用户id查询一个用户信息
public User findUserById(Integer id);
//根据用户名称模糊查询用户信息列表
public List<User> findByUserUsername(String Username);
//添加用户信息
public void addUser(User user);
}
6.创建接口的映射文件
<?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">
<mapper namespace="com.evil.mapper.UserMapper">
<!--
mybatis动态代理的开发规范
1: 映射文件的namespace必须等于接口的全路径名称
2: 映射文件的sql唯一标示id必须等于 接口方法的名称
3: 映射文件的parameterType必须等于接口方法的 参数类型
4: 映射文件的resultType必须等于接口方法的返回类型
-->
<select id="findUserById" parameterType="int" resultType="com.evil.pojo.User">
select * from user where id = #{id}
</select>
<select id="findByUserUsername" parameterType="string" resultType="com.evil.pojo.User">
select * from user where username like '%${value}%';
</select>
<insert id="addUser" parameterType="com.evil.pojo.User">
insert into user(username,sex,birthday,address) values(#{username},#{sex},#{birthday},#{address});
</insert>
</mapper>
7.测试
只需要定义一个全局的变量,创建一次就好。说明:@Before是在执行JUnit的@Test之前实例化SqlSessionFactory。没必要每次访问Mybatis的时候都要创建一个SqlSessionFactory,
package com.evil.test;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
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.Before;
import org.junit.Test;
import com.evil.mapper.UserMapper;
import com.evil.pojo.User;
public class UserMapperTest {
SqlSessionFactory sessionFactory;
@Before
public void testName() throws Exception {
String resource="SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
//添加用户信息
@Test
public void addUser(){
SqlSession session = sessionFactory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = new User();
user.setUsername("菜呀");
user.setSex("男");
user.setBirthday(new Date());
user.setAddress("中国");
userMapper.addUser(user);
session.commit();
}
//模糊查询用户信息列表
@Test
public void findUserByUsername(){
SqlSession session = sessionFactory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
List<User> list = userMapper.findByUserUsername("张");
for (User user : list) {
System.out.println(user);
}
}
@Test
public void findById(){
SqlSession session = sessionFactory.openSession();
UserMapper usermapper = session.getMapper(UserMapper.class);
User user = usermapper.findUserById(1);
System.out.println(user);
}
}
三、具体的执行流程?
MyBatis流程图(图片来自网络:侵删)
1、mybatis的配置
对应一个MappedStatement对象,sql的id即是MappedStatement的id。SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了myatis的运行环境等信息。
mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig中加载。
2、通过mybatis环境信息构造SqlSessionFactory工厂即会话工厂,它是由SqlSessionFactoryBuilder对象调用build()方法创建的。
3、由会话工厂创建sqlSession即会话,该会话的作用就是完成数据库的访问和结果的映射。
4、mybatis底层自定义了Executor执行器接口来操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
5、MappedStatement也是mybatis一个底层封装对象,它包装了mybatis配置信息以及sql映射信息等。Mapper.xml文件中一个sql
将输入的java对象映射到sql中.6、MappedStatement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过MappedStatement在执行sql前
输出结果映射至java对象中。7、MappedStatement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Excutor通过MappedStatement在执行sql后将
四、小问题?
会导致sql注入攻击,能用#号的地方就不要使用$,写OrderBy子句时应该用$而不是#。1.MyBatis是怎么样完成实体和表之间的映射?
<select id="findUserById" parameterType="int" resultType="com.heima.pojo.User">
select * from user where id = #{id}
</select>
parameterType:参数类型,将传入的java对象,映射成表中的字段,加入到sql语句中。
resultType:将执行sql的的返回结果映射成Java对象。
2.MyBatis中使用#{}和${}书写占位符有什么区别?
#将传入的数据都当成一个字符串,会对传入的数据自动加上引号;$将传入的数据直接显示生成在SQL中。注意:使用$占位符可能