回顾之前使用Mybatis来操作数据库的步骤:
(1)启动mybatis框架( SqlSession---->SqlSessionFactory---->SqlSessionFactoryBuilder)
(2)通过 SqlSessionFactoryBuilder来得到SqlSessionFactory ;
(3)通过SqlSessionFactory 来创建SqlSession;
(4)读source文件下的mybatis.xml,将mybatis.xml文件转化成流
(5)创建SqlSession对象
public static SqlSession session;
//启动mybatis框架,读配置文件,获取Session对象
public void getSession() throws IOException{
// (1)启动mybatis框架
// SqlSession---->SqlSessionFactory---->SqlSessionFactoryBuilder
SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
// 读source文件下的mybatis.xml,将mybatis.xml文件转化成流
InputStream ins = Resources.getResourceAsStream("mybatis.xml");
// (2)创建SQLSessionFactory工厂对象
SqlSessionFactory ssf = sfb.build(ins);
// (3)创建SqlSession对象
session = ssf.openSession();
}
每次操作数据库都要重复上述步骤,因此,可以像封装jdbcUtil一样,将它封装成一个工具类!
package cn.java.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.IOException;
import java.io.InputStream;
public class MybatisUtil {
//1.SqlSessionFactoryBuilder:
// 作用:负责构建SqlSessionFactory对象,使用build()方法可创建多个SqlSessionFactory对象
// 生命周期:只存在于方法体内,用过就不需要了
// 一旦创建了SqlSessionFactory,就不再需要该类了,一般用于局部变量
//2.SqlSessionFactory:MyBatis应用的核心
//作用:创建SqlSession对象
//生命周期:与应用的生命周期相同,作用于Application
// 单例模式:factory的实例化的过程是一个比较耗费性能的过程
// 一旦被创建就应该在应用的运行期间一直存在,保证有且只有一个factory,不要重新创建另一个,常使用单例模式
//3.SqlSession:用于请求或方法的作用域,用完之后需要关闭,不要占用资源
//作用:包含了执行SQL语句的所有方法
//对应一次数据库会话,会话结束必须关闭
private static SqlSessionFactory factory;
//静态代码块,随着类的加载而执行,而且只执行一次
static{
try {
InputStream is = Resources.getResourceAsStream("mybatis.xml");
factory = new SqlSessionFactoryBuilder().build(is);
// threadLocal = new ThreadLocal();
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSession(){
SqlSession session=null;
//通过session工厂获取到一个session
session = factory.openSession();
//调用session的查询集合方法
return session;
}
// 关闭SqlSession
public static void closeSession(SqlSession sqlSession){
sqlSession.close();
}
//测试
public static void main(String[] args) {
//System.out.println(MybatisUtil.factory==MybatisUtil.factory);
for (int i = 0; i < 5; i++) {
System.out.println(MybatisUtil.factory.hashCode());
}
}
}
以后每次使用只需要调用即可,不用重复编写加载配置文件和创建SqlSession代码,数据库操作完成后,SqlSession关闭。
引入数据库配置文件
<properties resource="database.properties"/>
<settings>
<setting name="logImpl" value="LOG4j"/>
settings>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
dataSource>
environment>
environments>
目的是简化项目结构
Mybatis局部配置文件名一定要与它所支持的mapper层中的接口同名,如:UserMapper.xml要与UserMapper.java同名。可以将mapper层接口与Mybatis局部配置文件放在同一个包下,mapper层接口中定义的方法名,一定要与Mybatis局部配置文件的SQL语句的id同名,注意mapper层中,没有接口的实现类。
在测试类中的某个方法前加@Before注解,可以使得在执行其他方法前,先执行该方法。
//Before注解:在每次调用测试方法之前,自动调用init()方法
@Before
public void init(){
session= MybatisUtil.getSession();
//um就是Mapper的实现类
um=session.getMapper(UserMapper.class);
}
在测试类中的某个方法前加@After注解,可以使得在执行其他方法后,再执行该方法。
//每次调用测试方法之后,自动调用一下destory()
@After
public void destory(){
MybatisUtil.closeSession(session);
}
给包下所有的实体类取别名
<typeAliases>
<typeAlias type="cn.java.pojo.Student" alias="student"/>
<typeAlias type="cn.java.pojo.User" alias="user"/>
typeAliases>
在MySchool数据库中,建立一个student表,表结构如下:
student(
id bigint(20) 自增,
sname varchar(40),
dept varchar(40),
age int)
并在表中插入几条数据,其中一条为自己的信息
#mysql8
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql:///myschool?serverTimezone=Hongkong
username=root
password=你的密码
log4j.rootLogger=DEBUG, CONSOLE
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="database.properties"/>
<settings>
<setting name="logImpl" value="LOG4j"/>
settings>
<typeAliases>
<typeAlias type="cn.java.pojo.Student" alias="student"/>
<typeAlias type="cn.java.pojo.User" alias="user"/>
typeAliases>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
dataSource>
environment>
environments>
<mappers>
<package name="cn.java.mapper"/>
mappers>
configuration>
package cn.java.pojo;
public class Student {
private Long id;
private String sname;
private String dept;
private int age;
public Student() {
}
public Student(Long id, String sname, String dept, int age) {
this.id = id;
this.sname = sname;
this.dept = dept;
this.age = age;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getDept() {
return dept;
}
public void setDept(String dept) {
this.dept = dept;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student[" + "id=" + id + ", " +
"sname='" + sname + '\'' +
", dept='" + dept + '\'' +
", age=" + age +
']';
}
}
package cn.java.mapper;
import cn.java.pojo.Student;
import org.apache.ibatis.annotations.Select;
import java.util.List;
import java.util.Map;
public interface StudentMapper {
// 该方法使用Student实体类
public List<Student> getAllStudent();
//直接在以下方法上加@Select注解,简化代码
@Select("select * from student")
public List<Student> findAllStudent();
// 该方法返回多条记录,不使用实体类,用Map数据类型去接受
public List<Map<String, Object>> getAllStudentMap();
// 该方法使用了带一个参数的查询语句,返回一条记录
public Map<String, Object> getStudentById(long id);
// 该方法使用了有多个参数的 select语句
public Map<String, Object> getStudentByMulCondition(Map<String, Object> map);
// 该方法插入一条记录,带参数,更新操作一定要提交事务
public int addStudent(Map<String, Object> map);
// 该方法插入多条记录,带参数,更新操作一定要提交事务
public int addStudentBatch(List<Student> list) ;
// 该方法使用了动态查询,查询条件不确定
public List<Map<String, Object>> getStudentByDynam(Map<String, Object> map) ;
// 该方法使用了动态修改,查询条件不确定
public int updateStudentByDynam(Map<String, Object> map) ;
// 根据id删除记录
public long deleteStudentById(long id);
// 根据多个id删除多条记录
public int deleteStudentByIds(long[] ids);
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.java.mapper.StudentMapper">
<select id="getAllStudent" resultType="student">
SELECT * FROM student
select>
<select id="getAllStudentMap" resultType="Map">
SELECT * FROM student
select>
<select id="getStudentById" resultType="map" parameterType="Long">
SELECT * FROM student WHERE id=#{0}
select>
<select id="getStudentByMulCondition" resultType="map" parameterType="Map">
SELECT * FROM student WHERE sname='${sname}' AND dept='${dept}' AND age='${age}'
select>
<insert id="addStudent" parameterType="Map">
INSERT INTO student SET sname=#{sname},dept=#{dept},age=#{age}
insert>
<insert id="addStudentBatch" parameterType="student">
insert into
student(sname,dept,age)
values
<foreach collection="list" item="student" separator=",">
(#{student.sname},#{student.dept},#{student.age})
foreach>
insert>
<select id="getStudentByDynam" resultType="Map" parameterType="Map">
SELECT * FROM student
<where>
<if test="sname!=null">
sname=#{sname}
if>
<if test="dept!=null">
and dept=#{dept}
if>
<if test="age!=null">
and age=#{age}
if>
where>
select>
<update id="updateStudentByDynam" parameterType="Map">
update student
<set>
<if test="sname!=null">
sname=#{sname},
if>
<if test="dept!=null">
dept=#{dept},
if>
<if test="age!=null">
age=#{age},
if>
id=#{id}
set>
where id=#{id}
update>
<delete id="deleteStudentById" parameterType="long">
DELETE FROM student WHERE id=#{id}
delete>
<delete id="deleteStudentByIds" parameterType="long[]" >
DELETE FROM student WHERE id IN
<foreach collection="array" item="id" open="(" close=")" separator=",">
#{id}
foreach>
delete>
mapper>
package cn.java.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.IOException;
import java.io.InputStream;
public class MybatisUtil {
// 获取SqlSession
public static SqlSession getSession(){
SqlSession session=null;
InputStream inputStream=null;
try {
//配置文件的路径
String resource = "mybatis.xml";
//加载配置文件,得到一个输入流
inputStream = Resources.getResourceAsStream(resource);
//获取MyBatis的Session工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过session工厂获取到一个session
session = sqlSessionFactory.openSession(true); //true表示自动提交事务
//调用session的查询集合方法
return session;
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
// 关闭SqlSession
public static void closeSession(SqlSession session){
if(session!=null){
session.close();
}
}
}
import cn.java.mapper.StudentMapper;
import cn.java.pojo.Student;
import cn.java.utils.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Test_Student {
// SqlSession session=null;
SqlSession session=null;
StudentMapper um=null;
//Before注解:在每次调用测试方法之前,自动调用init()方法
@Before
public void init(){
session= MybatisUtil.getSession();
//um就是Mapper的实现类
um=session.getMapper(StudentMapper.class);
}
//每次调用测试方法之后,自动调用一下destory()
@After
public void destory(){
MybatisUtil.closeSession(session);
}
@Test
public void testGetAllStudent(){
um= session.getMapper(StudentMapper.class);
List<Student> studentList = um.getAllStudent();
for (Student student : studentList) {
System.out.println(student);
}
}
@Test
public void testFindAllStudent(){
List<Student> studentList = um.findAllStudent();
for (Student student : studentList) {
System.out.println(student);
}
}
@Test
// 2.该方法返回多条记录,不使用实体类,用Map数据类型去接受
public void testGetAllStudentMap() {
List<Map<String, Object>> studentList =um.getAllStudentMap();
for (Map<String, Object> map : studentList) {
System.out.println(map);
}
}
@Test
// 3.该方法使用了带一个参数的查询语句,返回一条记录
public void testGetStudentById() {
// 传递参数,直接传
Long id =20201002222L;
Map<String, Object> studentMap = um.getStudentById(id);
System.out.println(studentMap);
}
@Test
// 4.该方法使用了有多个参数的 select语句
public void testGetStudentByMulCondition() {
// 声明一个Map对象,可以使用Map或实体类同时传递多个参数,用map更简单
Map<String, Object> paramMap = new HashMap<String, Object>();
// 封装参数
paramMap.put("sname", "李四");
paramMap.put("dept", "软件工程");
paramMap.put("age", "21");
// 传递参数
Map<String, Object> studentMap = um.getStudentByMulCondition(paramMap);
System.out.println(studentMap);
}
// 5.该方法插入一条记录,带参数,更新操作一定要提交事务
@Test
public void testAddStudent() {
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("sname", "徐三");
paramMap.put("dept", "计算机");
paramMap.put("age", "19");
int resultInt = um.addStudent(paramMap);
System.out.println(resultInt);
}
// 6.该方法插入多条记录,带参数,更新操作一定要提交事务
@Test
public void testAddStudentBatch() {
List<Student> list = new ArrayList<>();
Student student;
for (int i = 0; i < 5; i++) {
student = new Student();
student.setSname("test" + i);
student.setDept("网络安全");
student.setAge(19);
list.add(student);
}
int resultInt = um.addStudentBatch(list);
System.out.println(resultInt);
};
// 7.该方法使用了动态查询,查询条件不确定
@Test
public void getStudentByDynam() {
// 可以使用Map或实体类同时传递多个参数
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("age", "20");
List<Map<String, Object>> studentList =um.getStudentByDynam(paramMap);
for (Map<String, Object> map : studentList) {
System.out.println(map);
}
}
// 8.该方法使用了动态修改,查询条件不确定
@Test
public void updateStudentByDynam() {
// 可以使用Map或实体类同时传递多个参数
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("id","20201001111");
paramMap.put("dept", "计算机");
int resultInt = um.updateStudentByDynam(paramMap);
System.out.println(resultInt);
}
@Test
public void deleteStudentById(){
long id = 20201005582L;
long resInt = um.deleteStudentById(id);
System.out.println(resInt);
}
@Test
public void deleteStudentByIds(){
long[] ids = new long[]{20201005574L,20201005575L,20201005576L,
20201005577L,20201005578L,20201005579L,20201005581L};
long resInt = um.deleteStudentByIds(ids);
System.out.println(resInt);
}
}