一. Mybatis基础
1. 相关概念
1.1框架介绍
- 框架是一款半成品软件,我们可以基于这个半成品软件继续开发,来完成我们个性化的需求!
- 简单来说, 就是"框架把一些不变的东西提前写好, 让我们能更快更好的完成程序的开发"
1.2 ORM介绍
- ORM(Object Relational Mapping): 对象关系映射
- object:指的是实体对象,javabean
- relational:指的是关系型数据库,比如mysql
- Mapping: 映射,一 一对应的关系
- 简单来说,ORM可以实现对象与数据库表之间的自动映射
1.3 Mybatis
-
mybatis 是一个优秀的基于java的, 并且实现了ORM映射的持久层框架,它内部封装了jdbc
-
mybatis通过xml或注解的方式实现对数据库的持久化操作
-
MyBatis官网地址:http://www.mybatis.org/mybatis-3/
2. 快速入门
2.1 MyBatis开发步骤
①添加MyBatis的jar包
②编写实体类(对应数据库中的表)
③编写核心配置文件SqlMapConfig.xml
④编写映射配置文件
⑤编写测试类
2.2 具体操作
① 添加MyBatis的jar包
mysql-connector-java-5.1.37-bin.jar
mybatis-3.5.3.jar
og4j-1.2.17.jar
② 编写实体类
//学生类
//该类要和数据库表进行一一对应
public class Student {
private Integer id;
private String name;
private Integer age;
//省略get个set方法
}
③ 编写核心文件SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!--MyBatis的DTD约束-->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--configuration 核心根标签-->
<configuration>
<!--environments配置数据库环境,环境可以有多个。default属性指定使用的是哪个-->
<environments default="mysql">
<!--environment配置数据库环境 id属性唯一标识-->
<environment id="mysql">
<!-- transactionManager事务管理。 type属性,采用JDBC默认的事务-->
<transactionManager type="JDBC"></transactionManager>
<!-- dataSource数据源信息 type属性 连接池-->
<dataSource type="POOLED">
<!-- property获取数据库连接的配置信息 -->
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://192.168.59.143:3306/db1" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<!-- mappers引入映射配置文件 -->
<mappers>
<!-- resource属性指定映射配置文件的位置 -->
<mapper resource="StudentMapper.xml"/>
</mappers>
</configuration>
④ 编写映射配置文件StudentMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!--MyBatis的DTD约束 直接复制-->
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- mapper:核心根标签 namespace属性:名称空间 -->
<mapper namespace="StudentMapper">
<!--
select:查询功能的标签. insert:添加 update:修改 delete:删除
id属性:唯一标识
resultType属性:指定结果映射对象类型
parameterType属性:指定参数映射对象类型
-->
<select id="selectAll" resultType="com.shuai.bean.Student">
SELECT * FROM student
</select>
</mapper>
⑤ 编写测试类
@Test
public void selectAll() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过SqlSession工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.执行映射配置文件中的sql语句,并接收结果(参数是StudentMapper.xml中的selectAll)
List<Student> list = sqlSession.selectList("StudentMapper.selectAll");
//5.处理结果
for (Student stu : list) {
System.out.println(stu);
}
//6.释放资源
sqlSession.close();
is.close();
}
3. 映射配置文件
3.1 配置信息
<?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="StudentMapper">
<insert id="insert" parameterType="student">
INSERT INTO student VALUES (#{id},#{name},#{age})
</insert>
<update id="update" parameterType="student">
UPDATE student SET name = #{name},age = #{age} WHERE id = #{id}
</update>
<delete id="delete" parameterType="int">
DELETE FROM student WHERE id = #{id}
</delete>
<select id="selectAll" resultType="student">
SELECT * FROM student
</select>
<select id="selectById" resultType="student" parameterType="int">
SELECT * FROM student WHERE id = #{id}
</select>
</mapper
3.2 注意事项
//简单类型:基本数据类型+String 复杂类型:除了基本数据类型和String
1.参数是简单类型,则parameterType可以省略
2.参数如果只有一个,且是简单类型时,#{id}可以随便写,都可以获取参数的值
3.如果参数是复杂类型,则#{id}就相当于调用参数的getId方法,获取对应的参数值
4.返回值是简单类型,则resultType可以省略
5.返回值是集合类型,则resultType只写集合中元素的数据类型
4. 核心配置文件
4.1 引入外部properties
① jdbc.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://192.168.59.143:3306/db1
username=root
password=root
② 引入配置文件
<!--在MyBatis的核心配置文件中,引入数据库连接的配置文件-->
<properties resource="jdbc.properties"/>
③ 获取配置信息
<!-- 在MyBatis的核心配置文件中, 获取引入的properties文件中的配置信息 -->
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
4.2 起别名
4.2.1 语法
<!--起别名-->
<typeAliases>
<!-- 给Student类起别名为"student" -->
<typeAlias type="com.shuai.bean.Student" alias="student"/>
<!-- 给com.itheima.bean包下所有的类起别名,别名为类名的小写名字 -->
<!--<package name="com.shuai.bean"/>-->
</typeAliase>
</typeAliases>
4.2.1 作用
当给实体类起别名后, 在MyBatis映射配置文件中的参数或返回值中, 可以直接使用别名, 并且别名不区分大小写
5. selectKey标签
5.1 概述
selectKey标签只能用在增删改语句中, 它可以在"增删改"语句执行前后, 增加对应操作.
5.2 案例
<insert id="insert" parameterType="student">
<selectKey keyProperty="id" order="AFTER" >
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTO student VALUES (#{id},#{name},#{age})
</insert>
二. Mybatis进阶
1. 接口代理MyBatis
1.1 接口开发规范
- Mapper.xml文件中的namespace与mapper接口的全限定名相同
- Mapper接口的包名和Mapper.xml文件的文件夹路径相同
- Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
- Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同
- Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
1.2 实际代码实现
① 定义Mapper接口
public interface StudentMapper {
//查询全部
public abstract List<Student> selectAll();
//根据id查询
public abstract Student selectById(Integer id);
//新增数据
public abstract Integer insert(Student stu);
//修改数据
public abstract Integer update(Student stu);
//删除数据
public abstract Integer delete(Integer id);
}
② 创建映射文件
<?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.shuai.mapper.StudentMapper">
<select id="selectAll" resultType="student">
SELECT * FROM student
</select>
<select id="selectById" resultType="student" parameterType="int">
SELECT * FROM student WHERE id = #{id}
</select>
<insert id="insert" parameterType="student">
INSERT INTO student VALUES (#{id},#{name},#{age})
</insert>
<update id="update" parameterType="student">
UPDATE student SET name = #{name},age = #{age} WHERE id = #{id}
</update>
<delete id="delete" parameterType="int">
DELETE FROM student WHERE id = #{id}
</delete>
</mapper>
③ Service调用接口方法
public class StudentServiceImpl implements StudentService {
@Override
public List<Student> selectAll() {
//1.获取MyBatis的数据库联接对象SqlSession
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//2.获取Mapper的实现类对象, 相当于 StudentMapper mapper = new StudentMapperImpl();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//3.调用Mapper实现类对象的方法
List<Student> list = mapper.selectAll();
//4.关闭SqlSession
sqlSession.close();
//5.返回结果
return list;
}
@Override
public Student selectById(Integer id) {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student stu = mapper.selectById(id);
sqlSession.close();
return stu;
}
@Override
public Integer insert(Student stu) {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Integer result = mapper.insert(stu);
sqlSession.close();
return result;
}
@Override
public Integer update(Student stu) {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Integer result = mapper.update(stu);
sqlSession.close();
return result;
}
@Override
public Integer delete(Integer id) {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Integer result = mapper.delete(id);
sqlSession.close();
return result;
}
}
2. 动态sql语句
2.1 概述
MyBatis支持动态SQL语句, 也就是说, SQL语句可以动态生成
2.2 if标签
① 接口方法
//多条件查询. (id,name,age)有谁就查询谁
public abstract List<Student> selectCondition(Student stu);
② 配置文件
<select id="selectCondition" resultType="student" parameterType="student">
select * from student
<where>
<if test="id != null">
AND id = #{id}
</if>
<if test="name != null">
AND name = #{name}
</if>
<if test="age != null">
AND age = #{age}
</if>
</where>
</select>
③ 注意事项
1.if标签的test中,书写的就是判断条件
2.test中书写的id,也是调用参数的getId方法.
3.where标签会自动判断条件是否是第一个条件,如果是第一个条件,则会自动去掉AND联接符.
2.3 foreach标签
① 接口方法
//根据多个id查询
public abstract List<Student> selectByIds(List<Integer> ids);
② 配置文件
<select id="selectByIds" resultType="student" parameterType="list">
select * from student
<where>
<foreach collection="list" open="id IN (" close=")" item="id" separator=",">
#{id}
</foreach>
</where>
</select>
③ 注意事项
1.foreach标签的collection属性,在参数是list集合时,书写list. 参数是数组时,书写的是array
2.open属性表示的是拼接的时候的前缀,close属性表示的是拼接的时候的后缀
3.idea属性表示的是定义的变量,在遍历时,该变量依次存储着集合或数组中的每个元素
4.foreach标签体中的#{id}表示遍历时,每次都获取id中的值
5.separator表示在拼接时,变量之间的间隔.
6.上述配置,如果参数ids的值是1,2,3, 则拼接后的sql语句为"select * from student where id IN (1, 2, 3)"
2.4 SQL片段抽取
所谓的sql片段抽取, 就是把映射配置文件中的公共sql语句部分抽取.
<mapper namespace="com.shuai.mapper.StudentMapper">
<!--抽取-->
<sql id="select" >
SELECT * FROM student
</sql>
<select id="selectAll" resultType="student">
<!--引用,调用该片段时,会自动把抽取到的片段拼接到这里-->
<include refid="select"/>
</select>
<select id="selectById" resultType="student" parameterType="int">
<!--引用-->
<include refid="select"/> WHERE id = #{id}
</select>
</mapper>
3. 分页插件
3.1 开发步骤
① 导入jar包
jsqlparser-3.1.jar
pagehelper-5.1.10.jar
② 配置PageHelper插件
<!-- 在mybatis核心配置文件中配置,位置放在typeAliases之后 -->
<!-- 注意:interceptor:拦截器,插件都是以拦截器形式实现的 -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
③ 在查询语句前添加分页条件
@Test
public void selectPaging() throws Exception{
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//在查询语句前添加分页条件即可.
//注意: 参数1:当前页码,参数2:每页显示几条
PageHelper.startPage(3,3);
List<Student> list = mapper.selectAll();
for (Student student : list) {
System.out.println(student);
}
sqlSession.close();
is.close();
}
3.2 分页参数
把分页查询到的List集合,封装为PageInfo对象, 从PageInfo对象中获取分页参数
//获取分页相关参数
PageInfo<Student> info = new PageInfo<>(list);
System.out.println("总条数:" + info.getTotal());
System.out.println("总页数:" + info.getPages());
System.out.println("当前页:" + info.getPageNum());
System.out.println("每页显示条数:" + info.getPageSize());
System.out.println("上一页:" + info.getPrePage());
System.out.println("下一页:" + info.getNextPage());
System.out.println("是否是第一页:" + info.isIsFirstPage());
System.out.println("是否是最后一页:" + info.isIsLastPage());
4.多表操作
4.1 概述
在MyBatis中, 多表模型只需要分析两种即可:
一对一模型.
一对多模型.
4.2 一对一模型操作
4.2.1 模型示例
以用户表和订单表为例,站在订单表的角度看, 一个订单只从属于一个用户
4.2.2 修改Order实体
//主表-站在谁的角度,谁就是主表
public class Order {
private int id;
private Date ordertime;
private double total;
//在主表中,添加一个从表的对象.
//表示:一个订单只属于一个用户
private User user;
}
//从表
public class User {
private int id;
private String username;
private String password;
private Date birthday;
}
4.2.3 创建OrderMapper接口
public interface OrderMapper {
List<Order> findAll();
}
4.2.4 配置OrderMapper.xml
<mapper namespace="com.shuai.mapper.OrderMapper">
<resultMap id="orderMap" type="com.shuai.domain.Order">
<result column="uid" property="user.id"></result>
<result column="username" property="user.username"></result>
<result column="password" property="user.password"></result>
<result column="birthday" property="user.birthday"></result>
</resultMap>
<select id="findAll" resultMap="orderMap">
select * from shop_orders o,shop_user u where o.uid=u.id
</select>
</mapper>
其中<resultMap>
还可以配置如下:
<resultMap id="orderMap" type="com.shuai.domain.Order">
<result property="id" column="id"></result>
<result property="ordertime" column="ordertime"></result>
<result property="total" column="total"></result>
<association property="user" javaType="com.shuai.domain.User">
<result column="uid" property="id"></result>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="birthday" property="birthday"></result>
</association>
</resultMap>
4.2.5 测试
OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
List<Order> all = mapper.findAll();
for(Order order : all){
System.out.println(order);
}
4.3 一对多模型操作
4.2.1 模型示例
以用户表和订单表为例,站在用户表的角度看, 一个用户可以拥有多个订单
4.2.2 修改User实体
//从表
public class Order {
private int id;
private Date ordertime;
private double total;
}
//主表-站在谁的角度,谁就是主表
public class User {
private int id;
private String username;
private String password;
private Date birthday;
//在主表中,添加一个从表的集合对象.
//表示:一个用户拥有多个订单
private List<Order> orderList;
}
4.2.3 创建UserMapper接口
public interface UserMapper {
List<User> findAll();
}
4.2.4 配置UserMapper.xml
<mapper namespace="com.shuai.mapper.UserMapper">
<resultMap id="userMap" type="com.shuai.domain.User">
<result column="id" property="id"></result>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="birthday" property="birthday"></result>
<collection property="orderList" ofType="com.shuai.domain.Order">
<result column="oid" property="id"></result>
<result column="ordertime" property="ordertime"></result>
<result column="total" property="total"></result>
</collection>
</resultMap>
<select id="findAll" resultMap="userMap">
select *,o.id oid from shop_user u left join shop_orders o on u.id=o.uid
</select>
</mapper>
4.2.5 测试结果
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> all = mapper.findAll();
for(User user : all){
System.out.println(user.getUsername());
List<Order> orderList = user.getOrderList();
for(Order order : orderList){
System.out.println(order);
}
System.out.println("----------------------------------");
}
4.4 多对多模型操作
4.4.1 模型示例
以用户表和角色表为例,站在用户表的角度看, 一个用户可以拥有多个角色. 站在角色表的角度看, 一个角色也可以属于多个用户
4.4.2 实际操作
分别站在用户表的角度和角色表的角度, 各做一个"一对多"关系即可.
三. MyBatis高级
1. 注解开发
1.1 注意事项
- MyBatis的注解开发是把映射配置文件替换为注解形式, 核心配置文件该有还要有
- 在MyBatis的核心配置文件中, 配置Mapper时
<mapper class="Mapper接口的全名称"/>
<package name="Mapper接口所在的包"/>
必须是上述两种中的一种.
1.2 普通SQL
SQL语句直接书写在Mapper接口的方法上即可
public interface StudentMapper {
//查询全部
@Select("SELECT * FROM student")
public abstract List<Student> selectAll();
//新增操作
@Insert("INSERT INTO student VALUES (#{id},#{name},#{age})")
public abstract Integer insert(Student stu);
//修改操作
@Update("UPDATE student SET name=#{name},age=#{age} WHERE id=#{id}")
public abstract Integer update(Student stu);
//删除操作
@Delete("DELETE FROM student WHERE id=#{id}")
public abstract Integer delete(Integer id);
}
1.3 返回主键自增
1.3.1 概述
目的是在添加操作执行完毕后, 把数据库自动增长所生成的主键id, 放回参数的对应属性中.
1.3.2 @Options实现
//开启生层主键, 并把生成的主键放入stu对象的id属性中
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
@Insert("INSERT INTO student VALUES (#{id},#{name},#{age})")
public abstract Integer insert(Student stu);
1.3.3 @SelectKey实现
@SelectKey(statement = "select LAST_INSERT_ID()", keyProperty = "id",
before = false, resultType = int.class)
@Insert("INSERT INTO student VALUES (#{id},#{name},#{age})")
public abstract Integer insert(Student stu);
1.4 一对一模式
1.4.1 主表Mapper
public interface OrderMapper {
@Select("select * from shop_orders")
@Results({
@Result(id=true,property = "id",column = "id"),
@Result(property = "ordertime",column = "ordertime"),
@Result(property = "total",column = "total"),
@Result(property = "user",column = "uid",
javaType = User.class,
one = @One(select = "com.shuai.mapper.UserMapper.findById"))
})
List<Order> findAll();
}
1.4.2 从表Mapper
public interface UserMapper {
@Select("select * from shop_user where id=#{id}")
User findById(int id);
}
1.5 一对多模式
1.5.1 主表Mapper
public interface UserMapper {
@Select("select * from user")
@Results({
@Result(id = true,property = "id",column = "id"),
@Result(property = "username",column = "username"),
@Result(property = "password",column = "password"),
@Result(property = "birthday",column = "birthday"),
@Result(property = "orderList",column = "id",
javaType = List.class,
many = @Many(select = "com.shuai.mapper.OrderMapper.findByUid"))
})
List<User> findAllUserAndOrder();
}
1.5.2 从表Mapper
public interface OrderMapper {
@Select("select * from orders where uid=#{uid}")
List<Order> findByUid(int uid);
}