Mybatis:本身是apache的一个开源项目iBatis,2010年由Apache softwarefoundation迁移到Google code,并改名为Mybatis。是一个基于Java的持久层框架。
Hibernate、Mybatis都是ORM的一种实现框架,都是对JDBC的一种封装,只是Hibernate的框架写的不够灵活,很多东西写死了,不方便修改。
mybatis的开发jar包
log4j.jar
mybatis-3.4.1.jar
mysql-connector-java-5.1.6.jar
创建一张表
create table student{
id int(10) primary key auto_increment,
name varchar(10),
age int(10),
score int(15)
}
项目结构
创建实体
public class Student {
private Integer id;
private String name;
private int age;
private double score;
public Student() {
}
//构造器尽量不要把id写进去
public Student(String name, int age, double score) {
super();
this.name = name;
this.age = age;
this.score = score;
}
public Integer getId() {
return id;
}
public void setId(Integer 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 double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + ", score=" + score + "]";
}
}
创建mybatis配置文件mybatis-config.xml
配置数据库的信息,数据库我们可以配置为多个,因为数据库有mysql,oracle等,但是默认的只能用一个。
<?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>
<typeAliases>
<package name="com.b204.bean"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--数据库mysql驱动-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="root"/>
<!--数据库密码-->
<property name="password" value="xxx"/>
</dataSource>
</environment>
</environments>
<!--这里映射的是mapper.xml文件,如果有多个mapper文件,记得修改此处-->
<mappers>
<mapper resource="com/b204/dao/mapper.xml"/>
</mappers>
</configuration>
工具类
通过Mybatis配置文件与数据库的信息,得到Connection对象。因为每次获取SqlConnection对象是非常消耗资源的,所以在这里使用优化后的方法获取。
package com.b204.utils;
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.InputStream;
/**
* @author xxp
* @date 2020/10/10-14:34
*/
public class MyBatisUtils {
private static SqlSessionFactory sqlSessionFactory;
private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();
private MyBatisUtils(){
}
static {
try{
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
if (sqlSessionFactory==null) {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
}
} catch (Exception e){
e.printStackTrace();
}
}
public static SqlSession getSqlSession() {
//从当前线程中获取SqlSession对象
SqlSession sqlSession = threadLocal.get();
//如果SqlSession对象为空
if(sqlSession == null){
//在SqlSessionFactory非空的情况下,获取SqlSession对象
sqlSession = sqlSessionFactory.openSession();
//将SqlSession对象与当前线程绑定在一起
threadLocal.set(sqlSession);
}
//返回SqlSession对象
return sqlSession;
}
public static void closeSqlSession(){
SqlSession sqlSession = threadLocal.get();
if(sqlSession!=null){
//关闭sqlSession对象
sqlSession.close();
//分开当前线程与SqlSession对象的关系,目的是让GC尽早回收
threadLocal.remove();
}
}
public static void main(String[] args) {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
System.out.println(sqlSession!=null?"获取成功":"获取失败");
}
}
有了Mybatis的配置文件和表与实体之间的映射文件了,因此我们需要将配置文件和映射文件关联起来。
mapper.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.b204.dao.IStudentDao">
<insert id="insertStudent" parameterType="com.b204.bean.Student">
insert into student(name,age,score) values(#{name},#{age},#{score})
</insert>
<insert id="insertStudentCacheId" parameterType="com.b204.bean.Student">
insert into student(name,age,score) values(#{name},#{age},#{score})
-- 指定和insert语句执行的先后顺序、执行完insert语句之后生成的id再写入到student对象中的id
<selectKey resultType="int" keyProperty="id" order="AFTER">
select @@identity
</selectKey>
</insert>
<delete id="deleteStudent" parameterType="int">
delete from student where id=#{id}
</delete>
<update id="updateStudent">
update student set name=#{name},age=#{age},score=#{score} where id=#{id}
</update>
<select id="selectAllStudents" resultType="com.b204.bean.Student">
select id,name,age,score from student
</select>
<select id="selectStudentById" resultType="com.b204.bean.Student">
select id,name,age,score from student where id=#{id}
</select>
<select id="selectStudentsByName" resultType="com.b204.bean.Student">
select id,name,age,score from student where name like '%' #{name} '%'
</select>
<select id="selectStudentByCondition" resultType="com.b204.bean.Student">
select id,name,age,score from student
where 1=1
<if test="name != null and name != ''">
and name like '%' #{name} '%'
</if>
<if test="age>0">
and age > #{age}
</if>
</select>
<select id="selectStudentByWhere" resultType="com.b204.bean.Student">
select id,name,age,score from student
<where>
<if test="name != null and name != ''">
and name like '%' #{name} '%'
</if>
<if test="age>0">
and age > #{age}
</if>
</where>
</select>
<select id="selectStudentsByChoose" resultType="com.b204.bean.Student">
select id,name,age,score from student
<where>
<choose>
<when test="name != null and name != ''">
and name like '%' #{name} '%'
</when>
<when test="age > 0">
and age > #{age}
</when>
<otherwise>
1 = 2
</otherwise>
</choose>
</where>
</select>
<select id="selectStudentsByForeach" resultType="com.b204.bean.Student">
select id,name,age,score from student
<if test="array.length > 0">
where id in
<foreach collection="array" item="myid" open="(" close=")" separator=",">
#{myid}
</foreach>
</if>
</select>
<select id="selectStudentsByListForeach" resultType="com.b204.bean.Student">
select id,name,age,score from student
<if test="list.size > 0">
where id in
<foreach collection="list" item="myid" open="(" close=")" separator=",">
#{myid}
</foreach>
</if>
</select>
<select id="selectStudentsByListForeach2" resultType="com.b204.bean.Student">
select id,name,age,score from student
<if test="list.size > 0">
where id in
<foreach collection="list" item="stu" open="(" close=")" separator=",">
#{stu.id}
</foreach>
</if>
</select>
<sql id="selectColumns">
id,name,age,score
</sql>
<select id="selectStudentsByListFragment" resultType="com.b204.bean.Student">
select <include refid="selectColumns"/> from student
<if test="list.size > 0">
where id in
<foreach collection="list" item="stu" open="(" close=")" separator=",">
#{stu.id}
</foreach>
</if>
</select>
</mapper>
IStudentDao.java文件
public interface IStudentDao {
void insertStu(Student student);
void insertStudentCacheId(Student student);
void deleteStu(int id);
void updateStudent(Student student);
List<Student> selectAllStudents();
Map<String,Object> selectAllStudentsMap();
Student selectStudentById(int id);
List<Student> selectStudentsByName(String name);
List<Student> selectStudentByCondition(Student student);
List<Student> selectStudentsByIf(Student student);
List<Student> selectStudentsByWhere(Student student);
List<Student> selectStudentsByChoose(Student student);
List<Student> selectStudentsByForeach(int[] ads);
List<Student> selectStudentsByListForeach(List<Integer> ads);
List<Student> selectStudentsByListForeach2(List<Student> stuList);
List<Student> selectStudentsByListFragment(List<Student> stuList);
}
在StudentDaoImpl.java中提供了接口的实现,其实在mybatis标签中都已经实现了。
package com.b204.dao;
import com.b204.bean.Student;
import com.b204.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class StudentDaoImpl implements IStudentDao {
private SqlSession sqlSession;
@Override
public void insertStu(Student student) {
try {
sqlSession = MyBatisUtils.getSqlSession();
sqlSession.insert("insertStudent", student);
sqlSession.commit();
} finally {
if (sqlSession != null) {
//如果加sqlSession.close();那么就不需要再回滚
sqlSession.close();
}
}
}
@Override
public void deleteStu(String name) {
try {
sqlSession = MyBatisUtils.getSqlSession();
sqlSession.delete("deleteStudent",name);
sqlSession.commit();
} finally {
if(sqlSession!=null){
sqlSession.close();
}
}
}
@Override
public void insertStudentCacheId(Student student) {
try {
sqlSession = MyBatisUtils.getSqlSession();
sqlSession.insert("insertStudentCacheId", student);
sqlSession.commit();
} finally {
if (sqlSession != null) {
//如果加sqlSession.close();那么就不需要再回滚,源码可证
sqlSession.close();
}
}
}
@Override
public void deleteStu(int id) {
try {
sqlSession = MyBatisUtils.getSqlSession();
sqlSession.delete("deleteStudent", id);
sqlSession.commit();
} finally {
if (sqlSession != null) {
//如果加sqlSession.close();那么就不需要再回滚,源码可证
sqlSession.close();
}
}
}
@Override
public void updateStudent(Student student) {
try {
sqlSession = MyBatisUtils.getSqlSession();
sqlSession.update("updateStudent", student);
sqlSession.commit();
} finally {
if (sqlSession != null) {
//如果加sqlSession.close();那么就不需要再回滚,源码可证
sqlSession.close();
}
}
}
@Override
public List<Student> selectAllStudents() {
List<Student> students = null;
try {
sqlSession = MyBatisUtils.getSqlSession();
students = sqlSession.selectList("selectAllStudents");
sqlSession.commit();
return students;
} finally {
if (sqlSession != null) {
//如果加sqlSession.close();那么就不需要再回滚,源码可证
sqlSession.close();
}
}
}
@Override
public Map<String, Object> selectAllStudentsMap() {
Map<String, Object> map = new HashMap<>();
try {
sqlSession = MyBatisUtils.getSqlSession();
map = sqlSession.selectMap("selectAllStudents","name");
sqlSession.commit();
} finally {
if (sqlSession != null) {
//如果加sqlSession.close();那么就不需要再回滚,源码可证
sqlSession.close();
}
}
return map;
}
@Override
public Student selectStudentById(int id) {
Student student=null;
try {
sqlSession = MyBatisUtils.getSqlSession();
student = sqlSession.selectOne("selectStudentById", id);
sqlSession.commit();
} finally {
if (sqlSession != null) {
//如果加sqlSession.close();那么就不需要再回滚,源码可证
sqlSession.close();
}
}
return student;
}
@Override
public List<Student> selectStudentsByName(String name) {
List<Student> students=null;
try {
sqlSession = MyBatisUtils.getSqlSession();
students = sqlSession.selectList("selectStudentsByName", name);
sqlSession.commit();
} finally {
if (sqlSession != null) {
//如果加sqlSession.close();那么就不需要再回滚,源码可证
sqlSession.close();
}
}
return students;
}
@Override
public List<Student> selectStudentByCondition(Student student) {
List<Student> students=null;
try {
sqlSession = MyBatisUtils.getSqlSession();
students = sqlSession.selectList("selectStudentByCondition", student);
sqlSession.commit();
} finally {
if (sqlSession != null) {
//如果加sqlSession.close();那么就不需要再回滚,源码可证
sqlSession.close();
}
}
return students;
}
@Override
public List<Student> selectStudentsByIf(Student student) {
List<Student> students=null;
try {
sqlSession = MyBatisUtils.getSqlSession();
students = sqlSession.selectList("selectStudentByIf", student);
sqlSession.commit();
} finally {
if (sqlSession != null) {
//如果加sqlSession.close();那么就不需要再回滚,源码可证
sqlSession.close();
}
}
return students;
}
@Override
public List<Student> selectStudentsByWhere(Student student) {
List<Student> students=null;
try {
sqlSession = MyBatisUtils.getSqlSession();
students = sqlSession.selectList("selectStudentByWhere", student);
sqlSession.commit();
} finally {
if (sqlSession != null) {
//如果加sqlSession.close();那么就不需要再回滚,源码可证
sqlSession.close();
}
}
return students;
}
@Override
public List<Student> selectStudentsByChoose(Student student) {
List<Student> students=null;
try {
sqlSession = MyBatisUtils.getSqlSession();
students = sqlSession.selectList("selectStudentsByChoose", student);
sqlSession.commit();
} finally {
if (sqlSession != null) {
//如果加sqlSession.close();那么就不需要再回滚,源码可证
sqlSession.close();
}
}
return students;
}
@Override
public List<Student> selectStudentsByForeach(int[] ids) {
List<Student> students=null;
try {
sqlSession = MyBatisUtils.getSqlSession();
students = sqlSession.selectList("selectStudentsByForeach", ids);
sqlSession.commit();
} finally {
if (sqlSession != null) {
//如果加sqlSession.close();那么就不需要再回滚,源码可证
sqlSession.close();
}
}
return students;
}
@Override
public List<Student> selectStudentsByListForeach(List<Integer> ids) {
List<Student> students=null;
try {
sqlSession = MyBatisUtils.getSqlSession();
students = sqlSession.selectList("selectStudentsByListForeach", ids);
sqlSession.commit();
} finally {
if (sqlSession != null) {
//如果加sqlSession.close();那么就不需要再回滚,源码可证
sqlSession.close();
}
}
return students;
}
@Override
public List<Student> selectStudentsByListForeach2(List<Student> stuList) {
List<Student> students=null;
try {
sqlSession = MyBatisUtils.getSqlSession();
students = sqlSession.selectList("selectStudentsByListForeach2", stuList);
sqlSession.commit();
} finally {
if (sqlSession != null) {
//如果加sqlSession.close();那么就不需要再回滚,源码可证
sqlSession.close();
}
}
return students;
}
@Override
public List<Student> selectStudentsByListFragment(List<Student> stuList) {
List<Student> students=null;
try {
sqlSession = MyBatisUtils.getSqlSession();
students = sqlSession.selectList("selectStudentsByListFragment", stuList);
sqlSession.commit();
} finally {
if (sqlSession != null) {
//如果加sqlSession.close();那么就不需要再回滚,源码可证
sqlSession.close();
}
}
return students;
}
}
Mybatis实体与表的映射文件中提供了insert标签【SQL代码片段】供我们使用
下面举例说明:
接口:
public interface ICountryDao {
Country selectCountryById(int cid);
}
public class MyTest2 {
private ICountryDao dao;
private SqlSession sqlSession;
@Before
public void before() {
sqlSession = MyBatisUtils.getSqlSession();
dao = sqlSession.getMapper(ICountryDao.class);
}
@After
public void after(){
if(sqlSession!=null){
sqlSession.close();
}
}
@Test
public void test01(){
Country country = dao.selectCountryById(2);
System.out.println(country);
}
}
<?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.b204.dao.ICountryDao">
<select id="selectMinisterByCountry" resultType="com.b204.bean.Minister">
select mid,mname from minister where countryId=#{xxx}
</select>
<resultMap id="CountryMapper" type="com.b204.bean.Country">
<id column="cid" property="cid"/>
<result column="cname" property="cname"/>
<collection property="ministers" ofType="com.b204.bean.Minister" select="selectMinisterByCountry" column="cid"/>
</resultMap>
<select id="selectCountryById" resultMap="CountryMapper">
select cid,cname
from country
where cid=#{xxx}
</select>
</mapper>
Mybatis工作流程:
通过Reader对象读取Mybatis映射文件
通过SqlSessionFactoryBuilder对象创建SqlSessionFactory对象
获取当前线程的SQLSession
事务默认开启
通过SQLSession读取映射文件中的操作编号,从而读取SQL语句
提交事务
关闭资源