1.什么是MyBatis ?
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。
Mybatisd的特点
- 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
- 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
- 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
- 提供映射标签,支持对象与数据库的orm字段关系映射
- 提供对象关系映射标签,支持对象关系组建维护
- 提供xml标签,支持编写动态sql。
2Mybatis的工作流程
- 返回创建SqlSessionFactory对象
- 返回SqlSession的实现类DefaultSqlSession对象
- 返回一个MapperProxy的代理对象
- 执行查询流程。
3.Mybatis工程搭建
1.创建一个maven工程
2.在pom.xml文件下引入依赖
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!-日志->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!-单元测试->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>
3.编写实体类
/**
* 学生实体类 与 student_tb一一对应
*/
package com.yyf.entity;
import java.io.Serializable;
/**
* @Author: yyf
* @Date: 2020/10/14 11:14
*/
public class Student implements Serializable {
private int id;
private String name;
private int age;
private String sex;
private float height;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
public Student(int id, String name, int age, String sex, float height) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
this.height = height;
}
public Student() {
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", height=" + height +
'}';
}
}
4.编写持久层IStudentDao接口
package com.yyf.dao;
import com.yyf.entity.Student;
import java.util.List;
/**
* @Author: yyf
* @Date: 2020/10/14 11:13
*/
public interface IStudentDao {
/**
* 查找所有学生
*/
List<Student> findAllStudent();
/**
* 根据 查询学生
*/
Student findStudentById(int id);
/**
* 保存学生
*/
int saveStudent(Student student);
/**
* 更新学生
*/
int updateStudent(Student student);
/**
* 删除学生
*/
int deleteStudentById(int id);
/**
* 添加学生后 获取自增id
*
* 返回值是 修改数据库的影响行数
* @param student
*/
int addStudentGetId(Student student);
/**n
* 根据名称模糊查询
* @param likeName
*/
List<Student> findStudentListByName(String name);
}
5.编写持久层配置文件IStudentDao.xml
注意:
- 1.配置文件的名称必须以 接口名+.xml命名
- 2.文件的位置必须放在main目录下resources\com\yyf\dao对应目录
说明:
< select id=“findStudentById” parameterType=“java.lang.Integer” resultType=“com.yyf.entity.Student”>
select * from student_tb where id=#{id}
<select/ >
- parameterType:为传入参数的类型
- resultType:为输出参数的类型
- #{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.yyf.dao.IStudentDao">
<!--配置查询所有学生的 方法
id:为对应的方法方法名
resultType:返回数据类型的全限定名
-->
<select id="findAllStudent" resultType="Student">
select * from student_tb;
</select>
<select id="findStudentById" parameterType="java.lang.Integer" resultType="com.yyf.entity.Student">
select * from student_tb where id=#{id}
</select>
<select id="findStudentListByName" resultType="com.yyf.entity.Student">
select * from student_tb where name like #{name}
</select>
<insert id="saveStudent" parameterType="com.yyf.entity.Student" >
insert into student_tb (name,age,sex,height)values (#{name},#{age},#{sex},#{height})
</insert>
<delete id="deleteStudentById" parameterType="java.lang.Integer">
delete from student_tb where id = #{id}
</delete>
<update id="updateStudent" parameterType="com.yyf.entity.Student">
update student_tb set name=#{name},age=#{age},height=#{height},sex=#{sex} where id=#{id}
</update>
<!--产生自增ID-->
<!-- 第一种插入学生 获取id
<selectKey 获取自增id
resultType="int" 自增id 类型
keyColumn="id" 对应数据库表中自增主键列名
keyProperty="id" 传入的实体类中 主键的属性
order="AFTER" 插入完成之后执行 select last_insert_id()
-->
<insert id="addStudentGetId" parameterType="com.yyf.entity.Student">
insert into student_tb (name,age,sex,height) values (#{name},#{age},#{sex},#{height})
<selectKey resultType="int" keyColumn="id" keyProperty="id" order="AFTER">
select last_insert_id()
</selectKey>
</insert>
<!-- 第二种插入学生 获取id-->
<!-- <insert id="addStudentGetId" parameterType="com.yyf.entity.Student" useGeneratedKeys="true" keyProperty="id" keyColumn="id" >-->
<!-- insert into student_tb (name,age,sex,height,birthday)values (#{name},#{age},#{sex},#{height},#{birthday})-->
<!-- </insert>-->
</mapper>
6.在 创建sqlMapConfig.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">
<!--
mybatis主配置
-->
<configuration >
<!--
为包下的类取别名
Student -Student
-->
<typeAliases>
<package name="com.yyf.entity"/>
</typeAliases>
<!--配置mybatis环境-->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/yyf/dao/IStudentDao.xml"></mapper>
</mappers>
</configuration>
7.创建测试类
import com.yyf.dao.IStudentDao;
import com.yyf.entity.Student;
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.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* @Author: yyf
* @Date: 2020/10/14 14:05
*/
public class TestMybatis {
public static void main(String[] args) {
try {
// 1.读取配置文件
InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
// 2.创建session工厂
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(in);
// 3.获取session
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4.使用sqlSession 创建代理对象
// 方式一 通过代理:
// IStudentDao studentDao = sqlSession.getMapper(IStudentDao.class);
// List<Student> studentList = studentDao.findAllStudent();
// //查
// IStudentDao studentDao = sqlSession.getMapper(IStudentDao.class);
// Student student1 = studentDao.findStudentById(1);
// System.out.println(student1);
// 方式二:方式儿直接指明方法名
List<Student> studentList = sqlSession.selectList("com.yyf.dao.IStudentDao.findAllStudent");
for (Student student:studentList){
System.out.println(student);
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void add() throws IOException {
InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
// 2.创建session工厂
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(in);
// 3.获取session
SqlSession sqlSession = sqlSessionFactory.openSession();
IStudentDao studentDao = sqlSession.getMapper(IStudentDao.class);
Student student2 = new Student();
student2.setAge(19);
student2.setName("张三");
student2.setHeight(178);
student2.setSex("男");
studentDao.saveStudent(student2);
sqlSession.commit();
sqlSession.close();
}
@Test
public void delete() throws IOException {
InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
// 2.创建session工厂
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(in);
// 3.获取session
SqlSession sqlSession = sqlSessionFactory.openSession();
IStudentDao studentDao = sqlSession.getMapper(IStudentDao.class);
studentDao.deleteStudentById(7);
sqlSession.commit();
if (sqlSession!=null){
sqlSession.close();
}
}
@Test
public void addStudentAndGetId() throws IOException {
InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
// 2.创建session工厂
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(in);
// 3.获取session
SqlSession sqlSession = sqlSessionFactory.openSession();
IStudentDao studentDao = sqlSession.getMapper(IStudentDao.class);
Student student3 = new Student();
student3.setAge(19);
student3.setName("鞠婧祎");
student3.setHeight(170);
student3.setSex("女");
studentDao.addStudentGetId(student3);
System.out.println("新增学生信息的ID为" + student3.getId());
sqlSession.commit();
sqlSession.close();
}
@Test
public void findStudentListByName() throws IOException {
InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
// 2.创建session工厂
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(in);
// 3.获取session
SqlSession sqlSession = sqlSessionFactory.openSession();
IStudentDao studentDao = sqlSession.getMapper(IStudentDao.class);
List<Student> studentList = studentDao.findStudentListByName("%鞠%");
for (Student student:studentList){
System.out.println(student);
}
}
}
4.别名的配置
在mybatis中使用parameterType或者resultType 是必须写全限定名,其实在mybatis已经为我们配置好了一些类型别名,我们也可以自定配置别名
系统别名
在mybatis中TypeAliasRegistry已经为我们配置的默认别名
registerAlias(“string”, String.class);
registerAlias(“byte”, Byte.class);
registerAlias(“long”, Long.class);
registerAlias(“short”, Short.class);
registerAlias(“int”, Integer.class);
registerAlias(“integer”, Integer.class);
registerAlias(“double”, Double.class);
registerAlias(“float”, Float.class);
registerAlias(“boolean”, Boolean.class);
自定义别名
在mybatis配置文件sqlMapConfig.xml配置,**注意typeAliases要写在environments标签之前
<typeAliases>
<!--声明单个别名 使用时忽略大小写-->
<!-- <typeAlias type="com.yyf.entity.MiddleStudent" alias="middleStudent"></typeAlias>-->
<!--扫描包声明别名-->
<package name="com.yyf.entity"/>
</typeAliases>
使用
<select id="findStudentListByName" parameterType="string" resultType="Student">
select * from student_tb where name like '%${value}%'
</select>
当sql 语句需要参数 时,就要指定对应 参数类型 parameter(基本类型可以不指定),
当sql语句是查询时 需要指定resultType 增删改返回的的时影响到的行数 不需要指定
5.resultMap配置结果类型
当实体类中的字段和数据库中的字段不匹配时,我们可以有两种方式解决
- 1.使用sql语句的 as 修改查询结果的名称
- 2.使用resultMap,可以实现多个sql语句共用
<resultMap id="studentMap" type="student">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<result property="age" column="age"/>
<result property="height" column="height"/>
</resultMap>
<select id="findStudentById" parameterType="java.lang.Integer" resultMap="studentMap">
select * from student_tb where id=#{id}
</select>
说明
为sql语句结果的主键与实体类的映射,property为实体类字段,column为数据表主键字段
为普通sql语句字段实体类的属性映射,property为实体类字段,column为数据表主键字段
resultMap=“studentMap” 使用resultMap作为查询结果
6.SqlMapConfig.xml配置文件
SqlMapConfig.xml 中配置的内容和顺序 ,**必须为以下顺序,否则会出现错误
<configuration><!--配置-->
<properties/><!--属性-->
<settings/><!--设置-->
<typeAliases/><!--类型别名-->
<typeHandlers/><!--类型处理器-->
<objectFactory/><!--对象工厂-->
<plugins/><!--插件-->
<environments><!--配置环境-->
<environment><!--环境变量-->
<transactionManager/><!--事务管理器-->
<dataSource/><!--数据源-->
</environment>
</environments>
<databaseidProvider/><!--数据库厂商标识-->
<mappers/><!--映射器-->
</configuration>
typeAliases别名
<typeAliases>
<!--声明单个别名 使用时忽略大小写-->
<!-- <typeAlias type="com.yyf.entity.MiddleStudent" alias="middleStudent"></typeAlias>-->
<!--扫描包声明别名-->
<package name="com.yyf.entity"/>
</typeAliases>
mappers映射器配置
<mappers>
<!--在map 中声明 映射文件 两种方式 -->
<!--方式一:resource声明xml-->
<!-- <mapper resource="com/wgz/dao/IStudentDao.xml"></mapper>-->
<!--方式二:class 声明类名-->
<!--<mapper class="com.wgz.dao.IStudentDao"></mapper>-->
<!-- <mapper class="com.wgz.dao.IStudentDao2"/>
<mapper class="com.wgz.dao.IMiddleStudentDao"></mapper>-->
<!--方式三:扫描包名-->
<package name="com.wgz.dao"/>
</mappers>
mapUnderscoreToCamelCase 开启驼峰映射
<!-- 开启驼峰映射 ,为自定义的SQL语句服务-->
<!--设置启用数据库字段下划线映射到java对象的驼峰式命名属性,默认为false
user_name ---userName
-->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
多请求参数时:
1) parameterType 可以不写
- 参数较少
findStudentByAgeAndSex(int age,String sex) 配置文件 select * from student_tb where age >= #{arg0} and sex = #{arg1}
select * from student_tb where age >= #{param1} and sex = #{param2}
findStudentByAgeAndSex(@Param("age") int age,@Param("sex") String sex);
配置文件 select * from student_tb where age >= #{age} and sex = #{sex}
多参数
1.将参数封装为 实体类
2.将参数封装为map
List<Student> findStudentByAgeAndSexMap(Map<String,Object> map);
配置文件 select * from student_tb where age >= #{age} and sex = #{sex}
-->
<select id="findStudentByAgeAndSex" resultType="student">
select * from student_tb where age >= #{age} and sex = #{sex}
</select>
<select id="findStudentByAgeAndSexMap" resultType="student">
select * from student_tb where age >= #{age} and sex = #{sex}
</select>