一. 简介
1.1 什么是 MyBatis
- MyBatis 是一款优秀的 持久层框架
- 它支持定制化 SQL,存储过程以及高级映射
- MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果
- MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型,接口和 Java 的 POJO (普通老师 Java 对象)为数据库中的记录
- MyBatis 本质是 Apache 的一个开源项目,原名是 itbais
1.2 持久化
数据持久化
- 持久化就是将程序的数据在持久状态和瞬时状态的过程
- 内存:断电即失
- 数据库(jdbc)、io 文件持久化
为什么持久化?
- 一些对象不能丢掉
- 内存比较贵
1.3 持久层
Dao 层,Service 层,Controller 层。。
- 完成持久化工作的代码块
- 层界限十分明显
1.4 为什么学习 MyBatis ?
- 方便
- 简化 JDBC 代码,使用框架完成持久层的操作
- 不用 MyBatis 也可以,更容易上手
- 优点:
- 简单易学
- 灵活
- sql 代码的分离,提高可维护性
- 提供标签映射,支持对象与数据库的 ORM, 字段关系映射
- 提供映射标签,支持对象关系组建维护
- 提供 xml 标签,支持动态 SQL
二 快速入门
2.1 搭建一个 maven 项目
并导入 如下依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.10</version>
</dependency>
2.2 数据库创建
USE `test`;
/*Table structure for table `product` */
DROP TABLE IF EXISTS `product`;
CREATE TABLE `product` (
`pid` int(5) NOT NULL AUTO_INCREMENT,
`product_name` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
`price` float DEFAULT NULL,
`introduce` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
`address` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`pid`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Data for the table `product` */
insert into `product`(`pid`,`product_name`,`price`,`introduce`,`address`) values (1,'冰箱',2400,'海尔牌冰箱','杭州'),(2,'小米手机',2199,'小米牌手机,性价比之王','武汉'),(3,'MAC 口红',399,'MAC 最新上市','美国 加利福尼亚'),(4,'旺仔牛奶',40,'旺仔牛奶,你的最爱','北京'),(5,'辣条',5,'最爱辣条','江苏 南京'),(6,'牛奶',39.9,'蒙牛牛奶','新疆'),(7,'tedt',20,'test','你猜'),(8,'华为手机',3999,'华为 mate40 pro','武汉'),(9,'小米巨能写笔',22.3,'可以连续写字一个月以上','中国 湖北 武汉'),(11,'红米 note9',999.9,'老人机专属','暂时保密');
2.3 类编写
数据库对应实体类
public class Product {
private Integer id; // pid
private String name; //product_name
private Double price;
private String introduce;
private String address;
// 构造方法,getter,setter 省略
}
mapper 接口创建
package cn.gorit.mapper;
import cn.gorit.entity.Product;
import java.util.List;
public interface ProductMapper {
// 查询所有的数据
List<Product> selectAllProduct();
// 根据 id 查询
Product selectProductById(int id);
// 新增数据
void insertProduct(Product product);
// 修改数据,修改之前先查询数据
void updateProduct(Product product);
// 删除数据
void deleteProductById(int id);
}
2.4 配置文件编写
在 Resources 目录下创建 mybatis-config.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>
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 映射文件的路径配置 -->
<mappers>
<mapper resource="./productMapper.xml"/>
</mappers>
</configuration>
在 Resources 目录下创建 productMapper.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">
<mapper namespace="cn.gorit.mapper.ProductMapper">
<!-- 映射关系,当实体类字段和数据库字段不一致时,使用该字段解决数据库数据无法注入实体类中的情况 -->
<resultMap id="proMap" type="cn.gorit.entity.Product">
<id column="pid" property="id"/>
<result column="product_name" property="name"/>
<result column="price" property="price"/>
<result column="introduce" property="introduce"/>
<result column="address" property="address"/>
</resultMap>
<!-- 这里封装一些通用的 sql 语句 -->
<sql id="s1">
select * from product
</sql>
<!-- 下面的标签对应着增删改查的方法
id 就对应着 上面的 ProductMapper 中的一个具体的方法名
resultMap 代表结果集使用 上面的映射
parameterType 传入的参数类型
parameterType 传入的参数为 Product 实体类
-->
<select id="selectAllProduct" resultMap="proMap">
<include refid="s1"/>
</select>
<select id="selectProductById" parameterType="int" resultMap="proMap">
<include refid="s1"/>
where pid = #{id}
</select>
<insert id="insertProduct" parameterType="cn.gorit.entity.Product">
insert into product(product_name,price,introduce,address) values (#{name},#{price},#{introduce},#{address})
</insert>
<update id="updateProduct" parameterType="cn.gorit.entity.Product">
update product set product_name = #{name},price = #{price},introduce = #{introduce},address = #{address}
where pid = #{id}
</update>
<delete id="deleteProductById" parameterType="int">
delete from product where pid = #{id}
</delete>
</mapper>
2.5 测试类
package cn.gorit.test;
import cn.gorit.entity.Product;
import cn.gorit.mapper.ProductMapper;
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.Reader;
import java.util.List;
public class Test {
public static void main(String[] args) throws IOException {
// 加载配置文件
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
// 创建能执行映射文件中的 SqlSession
SqlSession session = sessionFactory.openSession();
// 获取映射,自动创建 mapper 接口的实现,直接调用数据库的方法
ProductMapper mapper = session.getMapper(ProductMapper.class);
// 查询一条记录
// Product product = mapper.selectProductById(1);
// System.out.println(product.toString());
// 查询多条记录
List<Product> list = mapper.selectAllProduct();
for (Product p:list) {
System.out.println(p);
}
// 修改记录
// product.setName("小米巨能写笔");
// product.setIntroduce("可以连续写字一个月以上");
// product.setAdress("中国 湖北 武汉");
//
// mapper.updateProduct(product);
// session.commit();
// 添加记录
// Product product1 = new Product("红米 note9",999.9,"老人机专属", "暂时保密");
// mapper.insertProduct(product1);
// session.commit();
// 删除记录
// mapper.deleteProductById(10);
// session.commit();
}
}
三、常用开发技巧 —— 使用 HashMap 映射
3.1 mybatis-config.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>
<!-- mybatis 的基础配置文件 -->
<settings>
<!-- 打印 SQL 信息 -->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<!-- 使用主键 -->
<setting name="useGeneratedKeys" value="true"/>
</settings>
<!-- 代码风格,是否为 驼峰命名法 -->
<typeAliases>
<!-- <typeAlias type="cn.gorit.entity.Student" alias="student"></typeAlias>-->
<package name="cn.gorit.entity"/> <!-- 默认的别名是首字母小写 -->
</typeAliases>
<!-- 环境配置 -->
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value=""/>
</dataSource>
</environment>
</environments>
<!-- 项目 mapper 配置 -->
<mappers>
<mapper resource="./StudentMapper.xml"/>
</mappers>
</configuration>
3.2 mapper.xml 配置
<!-- 使用 hashmap 映射 -->
<select id="selectStudentById" parameterType="int" resultType="hashmap">
select * from student where id = #{id}
</select>
3.3 实体类
public class Student {
private Integer id;
private String name;
private String gender;
private int age;
// getter 和 setter 构造方法省略
}
3.4 接口
public interface StudentMapper {
// 使用 map 获得数据
public Map selectStudentById(int id);
}
3.5 测试
Map<Object,Object> map = mapper.selectStudentById(1);
System.out.println(map.toString());
四、常用开发技巧 —— 循环插入数据
4.1 mapper.xml 配置
<!-- <sql id="s2">-->
<!-- insert into student(sname,gender,age) values-->
<!-- </sql>-->
<!-- 使用循环插入多条数据,useGenerated 上面已经添加过了 -->
<insert id="insertStudents" keyProperty="id">
<!-- 使用 foreach 实现循环遍历 -->
<include refid="s2"/>
<foreach collection="slist" item="stu" separator=",">
(#{stu.name},#{stu.gender},#{stu.age})
</foreach>
</insert>
4.2 接口
// 在 xml 中使用 foreach 循环插入数据
public void insertStudents(Map<String,List<Student>> map);
4.3 测试
List<Student> list = new ArrayList<>();
list.add(new Student("a1","男",14));
list.add(new Student("a2","女",16));
list.add(new Student("a3","男",18));
Map<String,List<Student>> map = new HashMap<>();
map.put("slist",list);
mapper.insertStudents(map);
session.commit();