MyBatis框架常用优化方法

一、优化之Session工具类

1、单独使用 MyBatis时,可以封装一个用来获取MyBatis中Session的工具类

回顾之前使用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一样,将它封装成一个工具类!

2、MybatisUtil.java

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>

三、优化之去DAO层

目的是简化项目结构
MyBatis框架常用优化方法_第1张图片
Mybatis局部配置文件名一定要与它所支持的mapper层中的接口同名,如:UserMapper.xml要与UserMapper.java同名。可以将mapper层接口与Mybatis局部配置文件放在同一个包下,mapper层接口中定义的方法名,一定要与Mybatis局部配置文件的SQL语句的id同名,注意mapper层中,没有接口的实现类。

四、优化之使用@Before、@After注解

1、@Before注解

在测试类中的某个方法前加@Before注解,可以使得在执行其他方法,先执行该方法。

 //Before注解:在每次调用测试方法之前,自动调用init()方法
    @Before
    public void init(){
        session= MybatisUtil.getSession();
        //um就是Mapper的实现类
        um=session.getMapper(UserMapper.class);
    }

2、@After注解

在测试类中的某个方法前加@After注解,可以使得在执行其他方法,再执行该方法。

 //每次调用测试方法之后,自动调用一下destory()
    @After
    public void destory(){
        MybatisUtil.closeSession(session);
    }

五、优化之使用@Select注解

六、优化之使用别名

给包下所有的实体类取别名


	<typeAliases>
		<typeAlias type="cn.java.pojo.Student" alias="student"/>
		<typeAlias type="cn.java.pojo.User" alias="user"/>
	typeAliases>

七、MyBatis 框架的优化练习

1、数据库准备

在MySchool数据库中,建立一个student表,表结构如下:

student(
id bigint(20) 自增,
sname varchar(40),
dept varchar(40),
age int)

并在表中插入几条数据,其中一条为自己的信息

2、完整代码

database.properties
#mysql8
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql:///myschool?serverTimezone=Hongkong
username=root
password=你的密码
log4j.properties
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 
mybatis.xml

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>
Student.java
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 +
                ']';
    }
}
StudentMapper.java
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);

}
StudentMapper.xml

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>


MybatisUtil.java
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();
        }
    }
}

Test_Student.java
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);
    }



}

你可能感兴趣的:(软件工程综合实践,mybatis,java,数据库)