title: Hello-MyBatis
tag: JAVA
1.框架入门 2.What is MyBatis 3.Hello MyBatis 4.Dao 5.动态SQL 6.mybatis配置文件 7.PageHelper插件
框架是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法,另一种说法;框架是可被应用开发者定制的应用骨架、模板。简单的说,框架其实是半成品软件,就是一组组件,供你使用完成你自己的系统。框架是安全的,可复用的,不断升级的软件
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。
MyBatis提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)
开发人员要做的就是:提供SQL语句,把精力放在写好SQL语句上即可!
- 新建student表
- 加入maven的mybatis依赖和mysql驱动
- 创建实体类 Student- 用来保存表中的一行数据
- 创建持久层的dao接口 定义操作数据库的方法
- 创建mybatis配置文件,叫做sql映射文件,用来写sql语句的。一般一个表一个sql映射文件
- 写在Dao接口所在的目录中
- 文件名称与接口名保持一致
- 创建mybatis的主配置文件,主配置文件提供了数据库的连接信息和sq1映射文件的位置信息
- 创建使用mybatis的类,通过mybatis访问数据库
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.1version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.25version>
dependency>
package xyz.guawaz.domain;
//类名推荐和表名一致,方便记忆
public class Student {
private Integer id;
private String name;
private String email;
private Integer age;
...
}
public interface StudentDao {
//查询Student表的所有数据
public List<Student> selectStudents();
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="xyz.guawaz.dao.StudentDao">
<select id="selectStudents" resultType="xyz.guawaz.domain.Student">
select id,name,email,age from student order by id
select>
mapper>
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/guawaz.xyz"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="xyz/guawaz/dao/StudentDao.xml"/>
mappers>
configuration>
package xyz.guawaz;
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 xyz.guawaz.domain.Student;
import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLOutput;
import java.util.List;
public class MyApp {
public static void main(String[] args) throws IOException {
//1.定义mybatis主配置文件的名称
String config = "mybatis.xml";
//2.读取这个config表示的文件
InputStream in = Resources.getResourceAsStream(config);
//3.创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//4.创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(in);
//5.【重要】获取SqlSession对象,从SqlSessionFactory中获取SqlSession
SqlSession sqlSession = factory.openSession();
//6.【重要】指定要执行的sql语句的标识。sql映射文件中的namespace + "." + 标签的id值
String sqlId = "xyz.guawaz.dao.StudentDao" + "." + "selectStudents";
//7.执行sql语句,通过sqlId找到语句
List<Student> studentList = sqlSession.selectList(sqlId);
//8.输出结果
studentList.forEach(stu -> System.out.println(stu));
//9.关闭sqlSession对象
sqlSession.close();
}
}
前面我们利用MyBatis实现了对数据库的访问,接下来对这个过程进行优化,更优雅方便地进行数据库访问
package xyz.guawaz.utils;
import com.sun.tools.javac.util.JCDiagnostic;
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.InputStream;
public class MyBatisUtils {
private static SqlSessionFactory factory = null;
static {
String config = "mybatis.xml";
InputStream in = null;
try {
in = Resources.getResourceAsStream(config);
} catch (IOException e) {
e.printStackTrace();
}
factory = new SqlSessionFactoryBuilder().build(in);
}
//获取sqlSession的方法
public static SqlSession getSqlSession(){
SqlSession sqlSession = null;
if (factory != null){
sqlSession = factory.openSession(); //不自动提交事务,需要手动提交 sqlSession.commit();
}
return sqlSession;
}
}
package xyz.guawaz.dao.impl;
import org.apache.ibatis.session.SqlSession;
import xyz.guawaz.dao.StudentDao;
import xyz.guawaz.domain.Student;
import xyz.guawaz.utils.MyBatisUtils;
import java.util.List;
public class StudentDaoImpl implements StudentDao {
@Override
public List<Student> selectStudents() {
//使用工具类获取SqlSession对象
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//使用SqlSession执行sql语句
List<Student> students = sqlSession.selectList("xyz.guawaz.dao.StudentDao.selectStudents");
//输出结果
students.forEach( stu -> System.out.println(stu));
//关闭SqlSession
sqlSession.close();
return students;
}
@Override
public int insertStudent(Student student) {
//使用工具类获取SqlSession对象
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//使用SqlSession执行sql语句
int num = sqlSession.insert("xyz.guawaz.dao.StudentDao.insertStudent",student);
//提交事务
sqlSession.commit();
//关闭SqlSession
sqlSession.close();
return num;
}
}
这样再操作数据库就可以用Dao实现类对象操作了:
package xyz.guawaz;
import org.junit.Test;
import xyz.guawaz.dao.impl.StudentDaoImpl;
import xyz.guawaz.domain.Student;
import java.util.List;
public class MyTest {
@Test
public void test1(){
StudentDaoImpl studentDao = new StudentDaoImpl();
List<Student> students = studentDao.selectStudents();
}
@Test
public void test2(){
StudentDaoImpl studentDao = new StudentDaoImpl();
Student student = new Student();
student.setId(1008);
student.setName("赵云");
student.setEmail("[email protected]");
student.setAge(25);
int num = studentDao.insertStudent(student);
}
}
public class MyTest {
@Test
public void test(){
/*使用mybatis的动态代理机制,使用SqlSession.getMapper(dao接口)
* 获取dao接口对应的实现类对象
* */
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> students = dao.selectStudents();
students.forEach(student -> System.out.println(student));
sqlSession.close();
}
}
传参指的是从Java代码中把实际的值传入mapper文件中
package xyz.guawaz.dao;
import org.apache.ibatis.annotations.Param;
import xyz.guawaz.domain.Student;
import java.util.List;
public interface StudentDao {
/*
* 一个简单类型的参数:
* 简单类型:mybatis把java基本数据类型和String都叫简单数据类型
*
* 在mapper文件获取简单类型的一个参数的值,使用#{任意字符}
*
*多个参数;
* 1.使用@Param命名参数:在形参定义的前面加上@Param("自定义参数名称")
* 在mapper文件使用#{自定义参数名称}获取多个参数的值
* 2.使用对象作为接口中方法的参数
* 在mapper文件使用#{对象的属性名}获取多个参数的值
*
*
* 在mapper文件使用#{}获取参数的值,#也可以换位$
* #和$的区别:
*
* #:使用PreparedStatement执行sql,效率高
* $:使用Statement执行sql,效率低,有sql注入问题
* 在确定数据安全时可以使用$,$可以进行sql拼接,一般用来替换表名、列名等
*
* */
//一个简单类型的参数
Student selectStudentById(Integer id);
//多个参数;
// @Param参数命名
List<Student> selectStudentsByMultiParam(@Param("myname") String name,@Param("myage") Integer age);
//对象方式
List<Student> selectStudentsByObject(Student student);
// # $
List<Student> selectStudentsInOrder(@Param("colName") String colName);
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="xyz.guawaz.dao.StudentDao">
<select id="selectStudentById" resultType="xyz.guawaz.domain.Student">
select * from student where id=#{sudentId}
select>
<select id="selectStudentsByMultiParam" resultType="xyz.guawaz.domain.Student">
select id,name,email,age from student where name=#{myname} or age=#{myage}
select>
<select id="selectStudentsByObject" resultType="xyz.guawaz.domain.Student">
select id,name,email,age from student where name=#{name} or age=#{age}
select>
<select id="selectStudentsInOrder" resultType="xyz.guawaz.domain.Student">
select * from student order by ${colName}
select>
mapper>
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="xyz.guawaz.dao.StudentDao">
<select id="countStudent" resultType="int">
select count(*) from student
select>
<select id="selectViewStudent" resultType="xyz.guawaz.vo.ViewStudent">
select id,name from student where name=#{name} or age=#{age}
select>
<select id="selectMapById" resultType="java.util.HashMap">
select id,name from student where id=#{id}
select>
<resultMap id="myResultMap" type="xyz.guawaz.domain.MyStudent">
<id column="id" property="myId"/>
<result column="name" property="myName"/>
<result column="email" property="myEmail"/>
<result column="age" property="myAge"/>
resultMap>
<select id="selectMyStudent" resultMap="myResultMap">
select * from student
select>
<select id="selectMyStudent2" resultType="xyz.guawaz.domain.MyStudent">
select id as myId,name as myName,email as myEmail,age as myAge from student
select>
<select id="selectLikeOne" resultType="xyz.guawaz.domain.Student">
select id ,name ,email ,age from student where name like #{name}
select>
<select id="selectLikeTwo" resultType="xyz.guawaz.domain.Student">
select id ,name ,email ,age from student where name like #{name} "%"
select>
mapper>
动态SQL是指,SQL语句的内容是变化的,可以根据条件获取到不同的SQL语句,主要是where部分发生变化。动态sql的实现,使用的是mybatis提供的标签if/where/foreach
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="xyz.guawaz.dao.StudentDao">
<select id="selectStudentIf" resultType="xyz.guawaz.domain.Student">
select id,name,email,age from student
where
<if test="name!=null and name !=''">
name = #{name}
if>
<if test="age > 0">
or age > #{age}
if>
select>
<select id="selectStudentWhere" resultType="xyz.guawaz.domain.Student">
select id,name,email,age from student
<where>
<if test="name!=null and name !=''">
name = #{name}
if>
<if test="age > 0">
or age > #{age}
if>
where>
select>
<select id="selectStudentForOne" resultType="xyz.guawaz.domain.Student">
select * from student where id in
<foreach collection="list" item="myid" open="(" close=")" separator=",">
#{myid}
foreach>
select>
<select id="selectStudentForTwo" resultType="xyz.guawaz.domain.Student">
select * from student where id in
<foreach collection="list" item="mystu" open="(" close=")" separator=",">
#{mystu.id}
foreach>
select>
<sql id="studentSql">
select id,name,email,age from student
sql>
mapper>
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties" />
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
settings>
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">plugin>
plugins>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value= "${jdbc.driver}" />
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="xyz/guawaz/dao/StudentDao.xml"/>
mappers>
configuration>
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>5.2.1version>
dependency>
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">plugin>
plugins>
查询语句之前调用PageHelper.startPage 静态方法,紧跟在这个 方法后的第一个 MyBatis 查询方法会被进行分页。
public void testSelectAll() {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
PageHelper.startPage(1,3);//获取第 1 页,3 条内容
List<Student> students = dao.selectAll();
students.forEach(stu -> System.out.println(stu));
sqlSession.close();
}