目录
前言
mybatis本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
mybatis不会对应用程序或者数据库的现有设计强加任何影响。sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
提供映射标签,支持对象与数据库的orm字段关系映射
提供对象关系映射标签,支持对象关系组建维护
提供xml标签,支持编写动态sql。
———————————————————————————————————————————
一、mybatis是什么?
mybatis是一个持久层框架。
作用是跟数据库交互完成增删改查。
概述:
就是对jdbc数据库操作进行封装,使用户开发者只用关注sql语句。通过xml或者注解的方式,将要执行的各种sql语句配置起来,并通过Java对象和statement中的sql语句映射生成最终的sql语句,最后由mybatis框架执行sql语句,并将结果映射成Java对象返回。
官网地址: https://mybatis.org/mybatis-3/zh/index.html
二、mybatis入门案例
1.导入jar包
代码如下(示例):
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
2.编辑User 对象
代码如下(示例):
@Data
public class User {
private int ID;
private String name;
private String sex;
private String address;
}
3.编辑UserDao接口
public interface UserDao {
public List<User> selectAll();
public User selectById(int ID);
public int insertUser(User user);
public int updateUser(User user);
public int deleteById(int ID);
public List<User> selectByCondition(@Param("name") String name, @Param("sex") String sex,@Param("address") String address);
}
4. 编辑接口实现类UserMapper映射文件
<?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:命名空间:它的值现在可以随便写。
以后必须和dao接口对应。
-->
<mapper namespace="com.wh.dao.UserDao">
<insert id="insertUser">
insert into role(name,sex,address) values (#{name},#{sex},#{address})
</insert>
<delete id="deleteById">
delete from role where ID=#{ID}
</delete>
<update id="updateUser">
update role set name=#{name},sex=#{sex},address=#{address} where ID=#{ID}
</update>
<select id="selectAll" resultType="com.wh.entity.User">
select * from role
</select>
<select id="selectById" resultType="com.wh.entity.User">
select ID,name,sex,address from role where ID=#{ID}
</select>
<select id="selectByCondition" resultType="com.wh.entity.User">
select * from role where name=#{name} and sex=#{sex} and address=#{address}
</select>
</mapper>
5.编辑mybaits.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>
<properties resource="db.properties"/>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
<mapper resource="mapper/StuMapper.xml"/>
</mappers>
</configuration>
6.编写数据源properties文件
jdbc.url=jdbc:mysql://localhost:3306/ssm?serverTimezone=Asia/Shanghai
jdbc.driverName=com.mysql.cj.jdbc.Driver
jdbc.username=root
jdbc.password=
7.日志输出 创建log4j.properties文件
### 设置###
log4j.rootLogger = debug,stdout,D,E
### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=E://AAA/Mybatis/logs/log.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://AAA/Mybatis/logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 输出ERROR 级别以上的日志到=E://AAA/Mybatis/logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://AAA/Mybatis/logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
8.编写测试方法(增删改查)
import com.sun.prism.impl.shape.MaskData;
import com.wh.dao.UserDao;
import com.wh.entity.User;
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 java.io.Reader;
import java.util.List;
/**
* @program: mybatis1
* @description:
* @author: WH
* @create:
**/
public class TestUserdao {
private SqlSession session;
@Before
public void before() throws Exception{
Reader resourceAsReader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(resourceAsReader);
session=sqlSessionFactory.openSession();
}
@Test
public void testInsert(){
UserDao userDao=session.getMapper(UserDao.class);
User user=new User();
user.setName("阿凡达");
user.setSex("女");
user.setAddress("道");
userDao.insertUser(user);
}
@Test
public void testDelete(){
UserDao userDao=session.getMapper(UserDao.class);
userDao.deleteById(7);
session.commit();
}
@Test
public void testUpdate(){
UserDao userDao=session.getMapper(UserDao.class);
User user=new User();
user.setName("爱仕达");
user.setSex("男");
user.setAddress("阿斯顿");
userDao.updateUser(user);
session.commit();
}
@Test
public void testSelectById(){
UserDao userDao=session.getMapper(UserDao.class);
userDao.selectById(3);
System.out.println(userDao.selectById(3));
session.commit();
}
@Test
public void textSelectAll(){
UserDao userDao=session.getMapper(UserDao.class);
List<User> users=userDao.selectAll();
System.out.println(users);
}
@Test
public void testSelectByCondition(){
UserDao userDao=session.getMapper(UserDao.class);
List<User> users=userDao.selectByCondition("孙悟空","公","花果山");
System.out.println(users);
}
}
数据库
三.动态sql
1.什么是动态 SQL
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
2.使用
-
if
-
choose (when, otherwise)
-
trim (where, set)
-
foreach
if 和 where 一起用
choose (when, otherwise)
trim (where, set)
foreach
分页:
① 自定义一个分页类
@Data
public class Limits implements Serializable {
private Integer page;
private Integer limit;
//自定义的方法
//跟分页查询时计算出来的那个下标对应 所以起名字叫 getIndex();
//(page-1)*limit 当前页码减一 乘以每页显示的条数。
public Integer getIndex(){
return (page-1)*limit;
}
}
② 接口
List<People> getPeoLimit(Limits limits);
③ xml
<select id="getPeoLimit" resultMap="queryPeo" parameterType="limits">
select * from people
limit #{index},#{limit}
</select>
模糊搜索分页:
① 接口
List<People> getPeoLikeLimit(People people);
② xml文件
<select id="getPeoLikeLimit" resultMap="queryPeo" parameterType="people" >
select * from people
<where>
<if test=" name!=null and name !='' ">
and p_name like concat('%' , #{name} ,'%')
</if>
<!--<if test=" author!=null and author != '' ">
and like concat('%' , #{author} ,'%')
</if>-->
<if test=" age > 4">
and p_age > 6
</if>
</where>
limit #{index},#{limit}
</select>
foreach : 批量操作:了解一下 批量删除,新增!
批量操作一般都由两种方式解决:
第一种:java代码中循环调用sql语句
第二种:使用mybatis动态sql的foreach
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>
四.Mybatis 链表查询
1. 多对一 员工和部门。 根据员工查询部门信息和员工信息。
2. 一对多 班级和学生。 从班级查询学生信息和班级信息。
1. 多对一
实体类
Dao接口
定义 sql 映射文件 UserMapper.xml与OrderMapper.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="com.wh.dao.OrderDao">
<resultMap id="wh" type="com.wh.entity.Order">
<id property="id" column="order_id"/>
<result property="no" column="order_no"/>
<result property="price" column="order_price"/>
<result property="num" column="num"/>
<!--association:表示多对一
property:表示对象属性名
javaType:表示该对象所属的类型
autoMapping必须写
-->
<association property="user" javaType="com.wh.entity.User" autoMapping="true">
<id property="id" column="id"/>
</association>
</resultMap>
<!--使用了resultMap不能在使用resultType-->
<select id="selectById" resultMap="wh">
select * from orders o join users u on o.uid=u.id where o.order_id=#{id}
</select>
<resultMap id="wh2" type="com.wh.entity.Order">
<id property="id" column="order_id"/>
<result property="no" column="order_no"/>
<result property="price" column="order_price"/>
<result property="num" column="num"/>
<!--column:把查询的哪一列作为另一个查询的条件值
select:表示引用另一个查询
-->
<association property="user" javaType="com.wh.entity.User"
column="uid" select="com.wh.dao.UserDao.selectById">
</association>
</resultMap>
<!--嵌套查询-->
<select id="selectById2" resultMap="wh2">
select * from orders where order_id=#{id}
</select>
</mapper>
编写测试类
import com.wh.dao.OrderDao;
import com.wh.entity.Order;
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 java.io.Reader;
/**
* @program: mydatis002
* @description:
* @author: WH
* @create:
**/
public class TestOrderDao {
private SqlSession session;
@Before
public void before()throws Exception{
Reader resourceAsReader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(resourceAsReader);
session=sqlSessionFactory.openSession();
}
@Test
public void testSelect(){
OrderDao orderDao=session.getMapper(OrderDao.class);
Order order=orderDao.selectById(2);
System.out.println(order);
}
@Test
public void testSelect02(){
OrderDao orderDao=session.getMapper(OrderDao.class);
Order order=orderDao.selectById(2);
System.out.println(order.getUser().getAge());
System.out.println(order.getId());
System.out.println(order.getUser().getName());
}
}
2.多对一
定义实体类:
dao接口
编写ClassMapper.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="com.wh.dao.Class1Dao">
<resultMap id="wh" type="com.wh.entity.Class1">
<id column="id" property="id" />
<result property="classname" column="classname"/>
<collection property="students" ofType="com.wh.entity.Student" autoMapping="true">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="classid" column="classid"/>
<result property="sex" column="sex"/>
</collection>
</resultMap>
<select id="findById" resultMap="wh">
select * from class1 c join student1 s on c.id=s.classid where classid=#{id}
</select>
</mapper>
测试TestClassDao
import com.wh.dao.Class1Dao;
import com.wh.entity.Class1;
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 java.io.Reader;
/**
* @program: mydatis002
* @description:
* @author: WH
* @create:
**/
public class TestClass1Dao {
private SqlSession session;
@Before
public void before()throws Exception{
Reader resourceAsReader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(resourceAsReader);
session=sqlSessionFactory.openSession();
}
@Test
public void testSelect(){
Class1Dao class1Dao=session.getMapper(Class1Dao.class);
Class1 class1=class1Dao.findById(3);
System.out.println(class1);
}
}
总结:
1. mybatis框架原理
- 持久层的框架
- 对原生态的jdbc程序进行总结
- mybatis开发dao的两种方式
- 原始的方式:程序需要编写dao接口和dao的实现类
- Mybatis的mapper接口:相当于dao接口代理开发
- Mybatis的核心:输入映射 输出映射 动态SQ
2. mybatis的原理
- Mybatis让程序的主要精力放在SQL上,通过mybatis提供的映射方式*灵活的生成满足需要的SQL语句.
- Mybatis可以将输入的参数自动的进行输入映射,将查询结果集灵活的映射出Java对象(输出映射).