Mybatis学习总结二

Mybatis学习总结二

0、不需要修改的文件(在src下面)

jdbc.properties文件

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///mybatis
jdbc.username=root
jdbc.password=3306

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
log4j.logger.org.apache=INFO

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">
<configuration>
	
	<!-- 引入外部文件 -->
	<properties resource="jdbc.properties"></properties>
	
	<!-- 环境 -->
	<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>
	
	<!-- 加载UserMapper.xml文件 -->
	<mappers>
		<package name="UserMapper.xml" />
	</mappers>
</configuration>

1、高级结果映射

1.1、一对一

数据表内容

在这里插入图片描述
在这里插入图片描述

开发环境

在这里插入图片描述

Address类

package com.csa.po;
public class Address {
	private Integer addressId;
	private String province;
	private String city;
	// get/set...方法
	// toString方法
}

User类

package com.csa.po;
public class User {
	private Integer userId;
	private String name;
	private Integer age;
	private Address address;
	// get/set...方法
	// toString方法
}

UserMapper(Dao)接口

package com.csa.dao;
import com.csa.po.User;
public interface UserDao {
	/**
	 * 通过用户id,查找User
	 * @param id
	 * @return
	 */
	public User selectUserById(Integer id);
}

UserMapper.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.csa.dao.UserDao">
	
	<resultMap type="com.csa.po.User" id="User">
		<!-- user信息 -->
		<id column="user_id" property="userId"/>
		<result column="name" property="name"/>
		<result column="age" property="age"/>
		<!-- 一对一 -->
		<association property="address" javaType="com.csa.po.Address">
			<id column="address_id" property="addressId"/>
			<result column="province" property="province"/>
			<result column="city" property="city"/>
		</association>
	</resultMap>
	
	<!-- 查询用户,通过用户id -->
	<select id="selectUserById" parameterType="int" resultMap="User">
		select * from user,address
		where user_id = #{userId} and address = address_id
	</select>
	
</mapper>

测试

package com.csa.app;
import java.io.InputStream;
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 com.csa.dao.UserDao;
import com.csa.po.User;

public class App {
	public static void main(String[] args) throws Exception {
		// 读取全局配置文件
		String resource = "SqlMapConfig.xml";
		InputStream input = Resources.getResourceAsStream(resource);
		// 创建SqlSessionFactory
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
		// 创建sqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 创建dao
		UserDao userDao = sqlSession.getMapper(UserDao.class);
		User user = userDao.selectUserById(3);
		System.out.println(user);
		// 关闭sqlSession
		sqlSession.close();
	}
	
}

测试结果

在这里插入图片描述

1.2、一对多

数据库内容

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

开发环境

在这里插入图片描述

Address类

package com.csa.po;
public class Address {
	private Integer addressId;
	private String province;
	private String city;
	// get/set...方法
	// toString方法
}

Phone类

package com.csa.po;
public class Phone {
	private Integer phoneId;
	private String model;
	private String memory;
	// get/set...方法
	// toString方法
}

User类

package com.csa.po;
import java.util.List;
public class User {
	private Integer userId;
	private String name;
	private Integer age;
	private Address address;
	private List<Phone> phoneList;
	// get/set...方法
	// toString方法
}

UserMapper接口

package com.csa.dao;
import com.csa.po.User;
public interface UserMapper {
	/**
	 * 通过用户id,查找User
	 * @param id
	 * @return
	 */
	public User selectUserById(Integer id);
}

UserMapper.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.csa.dao.UserMapper">
	
	<resultMap type="com.csa.po.User" id="User">
		<!-- user信息 -->
		<id column="user_id" property="userId"/>
		<result column="name" property="name"/>
		<result column="age" property="age"/>
		<!-- 一对一 -->
		<association property="address" javaType="com.csa.po.Address">
			<id column="address_id" property="addressId"/>
			<result column="province" property="province"/>
			<result column="city" property="city"/>
		</association>
		<!-- 一对多 -->
		<collection property="phoneList" ofType="com.csa.po.Phone">
			<id column="phone_id" property="phoneId"/>
			<result column="model" property="model"/>
			<result column="memory" property="memory"/>
		</collection>
	</resultMap>
	
	<!-- 查询用户,通过用户id -->
	<select id="selectUserById" parameterType="int" resultMap="User">
		select * from user,address,phone
		where user_id = #{id} 
		and address = address_id 
		and user = user_id
	</select>
	
</mapper>

UserMapper.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.csa.dao.UserMapper">
	
	<resultMap type="com.csa.po.User" id="UserMap">
		<!-- user信息 -->
		<id column="user_id" property="userId"/>
		<result column="name" property="name"/>
		<result column="age" property="age"/>
		<!-- 一对一 -->
		<association property="address" javaType="com.csa.po.Address">
			<id column="address_id" property="addressId"/>
			<result column="province" property="province"/>
			<result column="city" property="city"/>
		</association>
	</resultMap>
	
	<!-- 使用到继承 -->
	<resultMap type="com.csa.po.User" id="User" extends="UserMap">
		<!-- 一对多 -->
		<collection property="phoneList" ofType="com.csa.po.Phone">
			<id column="phone_id" property="phoneId"/>
			<result column="model" property="model"/>
			<result column="memory" property="memory"/>
		</collection>
	</resultMap>
	
	<!-- 查询用户,通过用户id -->
	<select id="selectUserById" parameterType="int" resultMap="User">
		select * from user,address,phone
		where user_id = #{id} 
		and address = address_id 
		and user = user_id
	</select>
	
</mapper>

测试

package com.csa.app;

import java.io.InputStream;
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 com.csa.dao.UserMapper;
import com.csa.po.User;

public class App {
	public static void main(String[] args) throws Exception {
		// 读取全局配置文件
		String resource = "SqlMapConfig.xml";
		InputStream input = Resources.getResourceAsStream(resource);
		// 创建SqlSessionFactory
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
		// 创建sqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 创建dao
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		User user = userMapper.selectUserById(3);
		System.out.println(user);
		// 关闭sqlSession
		sqlSession.close();
	}
	
}

测试结果

在这里插入图片描述

1.3、多对多

1.3.0、不变的东西

数据库信息

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

开发环境

在这里插入图片描述

Course类
package com.csa.po;
import java.util.List;
public class Course {
	private Integer courseId;
	private String courseName;
	private Integer credit;
	private List<Student> studentList;
	// get/set...方法
	// toString方法
}
Student类
package com.csa.po;
import java.util.List;
public class Student {
	private Integer studentId;
	private String studentName;
	private Integer age;
	private List<Course> courseList;
	// get/set...方法
	// toString方法
}
SqlMapConfig.xml的一些小改变
<!-- 加载UserMapper.xml文件 -->
<mappers>
	<mapper resource="StudentMapper.xml"/>
	<mapper resource="CourseMapper.xml"/>
	<mapper resource="StudentCourseMapper.xml"/>
</mappers>

1.3.1、查询学生所选课程的情况

StudentMapper.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.csa.dao.StudentMapper">
	<!-- CURD操作 -->
	<resultMap type="com.csa.po.Student" id="Student">
		<id column="student_id" property="studentId"/>
		<result column="student_name" property="studentName"/>
		<result column="age" property="age"/>
		<collection property="courseList" ofType="com.csa.po.Course">
			<id column="course_id" property="courseId"/>
			<result column="course_name" property="courseName"/>
			<result column="credit" property="credit"/>
		</collection>
	</resultMap>
	
	<!-- 通过id查找该学生选修的课程 -->
	<select id="selectStudentCoursesById" parameterType="int" resultMap="Student">
		select * from student natural join course natural join student_course 
		where student_id = #{studentId}
	</select>
</mapper>
StudentMapper接口
package com.csa.dao;
import com.csa.po.Student;
public interface StudentMapper {
	/**
	 * 通过学生id查找学生选修情况
	 * @param id
	 * @return
	 */
	public Student selectStudentCoursesById(Integer id);
}
测试
package com.csa.app;

import java.io.InputStream;
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 com.csa.dao.StudentMapper;
import com.csa.po.Student;

public class App {
	public static void main(String[] args) throws Exception {
		// 读取全局配置文件
		String resource = "SqlMapConfig.xml";
		InputStream input = Resources.getResourceAsStream(resource);
		// 创建SqlSessionFactory
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
		// 创建sqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 创建dao
		StudentMapper studentMapper = (StudentMapper) sqlSession.getMapper(StudentMapper.class);
		Student student = studentMapper.selectStudentCoursesById(2);
		System.out.println(student);
		// 关闭sqlSession
		sqlSession.close();
	}
	
}
测试结果

在这里插入图片描述

1.3.2、查询本门课程的所有学生

CourseMapper.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.csa.dao.CourseMapper">
	
	<!-- CRUD操作 -->
	<resultMap type="com.csa.po.Course" id="Course">
		<id column="course_id" property="courseId"/>
		<result column="course_name" property="courseName"/>
		<result column="credit" property="credit"/>
		<collection property="studentList" ofType="com.csa.po.Student">
			<id column="student_id" property="studentId"/>
			<result column="student_name" property="studentName"/>
			<result column="age" property="age"/>
		</collection>
	</resultMap>
	
	<!-- 通过课程id查询本课程的所有学生 -->
	<select id="selectCourseStudentsById" parameterType="int" resultMap="Course">
		select * from student natural join course natural join student_course
		where course_id = #{courseId}
	</select>
	
</mapper>
CourseMapper接口
package com.csa.dao;
import com.csa.po.Course;
public interface CourseMapper {
	/**
	 * 通过课程id查询本门课程的所有学生
	 * @param id
	 * @return
	 */
	public Course selectCourseStudentsById(Integer id);
}
测试
package com.csa.app;

import java.io.InputStream;
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 com.csa.dao.CourseMapper;
import com.csa.dao.StudentMapper;
import com.csa.po.Course;
import com.csa.po.Student;

public class App {
	public static void main(String[] args) throws Exception {
		// 读取全局配置文件
		String resource = "SqlMapConfig.xml";
		InputStream input = Resources.getResourceAsStream(resource);
		// 创建SqlSessionFactory
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
		// 创建sqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 创建dao
		CourseMapper courseMapper = sqlSession.getMapper(CourseMapper.class);
		Course course = courseMapper.selectCourseStudentsById(3);
		System.out.println(course);
		// 关闭sqlSession
		sqlSession.close();
	}
	
}
测试结果

在这里插入图片描述

1.3.3、增加一条选修记录

StudentCourseMapper.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.csa.dao.StudentCourseMapper">
	<!-- CURD操作 -->
	<insert id="addElective">
		<!-- 没有给定参数则是为param1、param2...paramn -->
		insert into student_course values(#{param1.studentId},#{param2.courseId},#{param3})
	</insert>
</mapper>
StudentCourse接口
package com.csa.dao;
import com.csa.po.Course;
import com.csa.po.Student;
public interface StudentCourseMapper {
	public void addElective(Student student,Course course,Integer score);
}
测试(记得提交事务)
package com.csa.app;

import java.io.InputStream;

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 com.csa.dao.StudentCourseMapper;
import com.csa.po.Course;
import com.csa.po.Student;

public class App {
	public static void main(String[] args) throws Exception {
		// 读取全局配置文件
		String resource = "SqlMapConfig.xml";
		InputStream input = Resources.getResourceAsStream(resource);
		// 创建SqlSessionFactory
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
		// 创建sqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 创建dao
		StudentCourseMapper studentCourseMapper = sqlSession.getMapper(StudentCourseMapper.class);
		Student student = new Student();
		student.setStudentId(2);
		Course course = new Course();
		course.setCourseId(2);
		studentCourseMapper.addElective(student, course, 99);
		// 提交事务
		sqlSession.commit();
		// 关闭sqlSession
		sqlSession.close();
	}
	
}
测试结果

在这里插入图片描述
在这里插入图片描述


2、延迟加载

2.1、什么是延迟加载

延迟加载又叫懒加载,也叫按需加载。也就是说先加载主信息,在需要的时候,再去加载从信息。

在mybatis中,resultMap标签 的association标签和collection标签具有延迟加载的功能。

2.2、在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">
<configuration>
	
	<!-- 引入外部文件 -->
	<properties resource="jdbc.properties"></properties>
	
	<settings>
		<!-- 开启延迟加载,默认为true -->
		<setting name="lazyLoadingEnabled" value="true"/>
		<!-- 将积极加载改为消极加载即按需要加载,默认为true -->
		<setting name="aggressiveLazyLoading" value="false"/>
	</settings>
	
	<!-- 环境 -->
	<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>
	
	<!-- 加载UserMapper.xml文件 -->
	<mappers>
		<mapper resource="StudentMapper.xml"/>
		<mapper resource="CourseMapper.xml"/>
	</mappers>
</configuration>

2.3、一对多的延迟加载案例

数据库信息

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

开发环境

在这里插入图片描述

两个实体类

Student
package com.csa.po;

import java.util.List;

public class Student {
	private Integer studentId;
	private String studentName;
	private Integer age;
	private List<Course> courseList;
	// get/set...方法
	// toString方法
}
Course
package com.csa.po;

import java.util.List;

public class Course {
	private Integer courseId;
	private String courseName;
	private Integer credit;
	private List<Student> studentList;
	// get/set...方法
	// toString方法
}

两个接口

StudentMapper
package com.csa.dao;
import com.csa.po.Student;
public interface StudentMapper {
	/**
	 * 通过学生id查找学生选修情况
	 * @param id
	 * @return
	 */
	public Student selectStudentCoursesById(Integer id);
}

CourseMapper
package com.csa.dao;
import com.csa.po.Course;
public interface CourseMapper {
	/**
	 * 通过课程id查询本门课程的所有学生
	 * @param id
	 * @return
	 */
	public Course selectCourseStudentsById(Integer id);
}

两个xml配置(重点)

StudentMapper.xml(注意sql语句和resultMap)
<?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.csa.dao.StudentMapper">
	<!-- CURD操作 -->
	<resultMap type="com.csa.po.Student" id="Student">
		<id column="student_id" property="studentId"/>
		<result column="student_name" property="studentName"/>
		<result column="age" property="age"/>
		<collection property="courseList" ofType="com.csa.po.Course"
		select="com.csa.dao.CourseMapper.selectCourseStudentsById" column="student_id"></collection>
	</resultMap>
	
	<!-- 通过id查找该学生选修的课程 -->
	<select id="selectStudentCoursesById" parameterType="int" resultMap="Student">
		select * from student 
		where student_id = #{studentId}
	</select>
</mapper>
CourseMapper.xml(注意sql语句)
<?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.csa.dao.CourseMapper">
	
	<!-- CRUD操作 -->
	<resultMap type="com.csa.po.Course" id="Course">
		<id column="course_id" property="courseId"/>
		<result column="course_name" property="courseName"/>
		<result column="credit" property="credit"/>
		<collection property="studentList" ofType="com.csa.po.Student">
			<id column="student_id" property="studentId"/>
			<result column="student_name" property="studentName"/>
			<result column="age" property="age"/>
		</collection>
	</resultMap>
	
	<!-- 通过课程id查询本课程的所有学生 -->
	<select id="selectCourseStudentsById" parameterType="int" resultMap="Course">
		select * from course natural join student_course
		where student_id = #{student_id}
	</select>
	
</mapper>

测试

不加载课程信息
package com.csa.app;
import java.io.InputStream;
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 com.csa.dao.StudentMapper;
import com.csa.po.Course;
import com.csa.po.Student;

public class App {
	public static void main(String[] args) throws Exception {
		// 读取全局配置文件
		String resource = "SqlMapConfig.xml";
		InputStream input = Resources.getResourceAsStream(resource);
		// 创建SqlSessionFactory
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
		// 创建sqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 创建dao
		StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
		Student student = studentMapper.selectStudentCoursesById(2);
		// 将下面这段放开,则是延迟加载了course!
		/*for (Course course : student.getCourseList()) {
			System.out.println(course);
		}*/
		// 关闭sqlSession
		sqlSession.close();
	}
	
}
加载课程信息
package com.csa.app;
import java.io.InputStream;
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 com.csa.dao.StudentMapper;
import com.csa.po.Course;
import com.csa.po.Student;

public class App {
	public static void main(String[] args) throws Exception {
		// 读取全局配置文件
		String resource = "SqlMapConfig.xml";
		InputStream input = Resources.getResourceAsStream(resource);
		// 创建SqlSessionFactory
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
		// 创建sqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 创建dao
		StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
		Student student = studentMapper.selectStudentCoursesById(2);
		
		for (Course course : student.getCourseList()) {
			System.out.println(course);
		}
		// 关闭sqlSession
		sqlSession.close();
	}
	
}

测试结果

不加载课程信息结果

在这里插入图片描述

加载课程信息结果(当属性被访问时,再去数据库查找,于是mapper需要这样的sql语句)
# 这里的查询条件是学号!
select * from course natural join student_course
		where student_id = #{student_id}

在这里插入图片描述


3、查询缓存

3.0、什么是缓存

Mybatis的缓存,包括一级缓存和二级缓存。

一级缓存指的就是sqlsession,在sqlsession中有一个数据区域,是map结构,这个区域就是一级缓存区域。一级缓存中的key是由sql语句、条件、statement等信息组成一个唯一值。一级缓存中的value,就是查询出的结果对象。

二级缓存指的就是同一个namespace下的mapper,二级缓存中,也有一个map结构,这个区域就是一级缓存区域。一级缓存中的key是由sql语句、条件、statement等信息组成一个唯一值。一级缓存中的value,就是查询出的结果对象。

3.1、一级缓存

一级缓存是默认使用的。同一个sqlsession中的缓存。

开发环境

在这里插入图片描述

实体类

package com.csa.po;
public class Student {
	private Integer studentId;
	private String studentName;
	private Integer age;
	// get/set...方法
	// toString方法
}

接口

package com.csa.dao;
import com.csa.po.Student;
public interface StudentMapper {
	/**
	 * 通过学生id查找学生
	 * @param id
	 * @return
	 */
	public Student selectStudentById(Integer 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.csa.dao.StudentMapper">
	<!-- CURD操作 -->
	<resultMap type="com.csa.po.Student" id="Student">
		<id column="student_id" property="studentId"/>
		<result column="student_name" property="studentName"/>
		<result column="age" property="age"/>
	</resultMap>
	
	<!-- 通过id查找该学生选修的课程 -->
	<select id="selectStudentById" parameterType="int" resultMap="Student">
		select * from student 
		where student_id = #{studentId}
	</select>
</mapper>

测试

package com.csa.app;

import java.io.InputStream;
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 com.csa.dao.StudentMapper;
import com.csa.po.Student;

public class App {
	public static void main(String[] args) throws Exception {
		// 读取全局配置文件
		String resource = "SqlMapConfig.xml";
		InputStream input = Resources.getResourceAsStream(resource);
		// 创建SqlSessionFactory
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
		// 创建sqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 创建dao
		StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
		Student student1 = studentMapper.selectStudentById(2);
		Student student2 = studentMapper.selectStudentById(2);
		System.out.println(student1);
		System.out.println(student2);
		// 关闭sqlSession
		sqlSession.close();
	}
	
}

测试结果(可以看出,只做了一次查询)

在这里插入图片描述

3.2、二级缓存

二级缓存需要手动开启。

二级缓存原理

在这里插入图片描述

开发环境

在这里插入图片描述

开启缓存

SqlMapConfig.xml配置
<!-- 开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
StudentMapper.xml配置
<!-- 开启二级缓存,默认使用了PerpettualCache -->
<cache/>

实体类

需要序列化!

package com.csa.po;
import java.io.Serializable;
public class Student implements Serializable{
	private Integer studentId;
	private String studentName;
	private Integer age;
	// get/set...方法
	// toString方法
}

接口

与上面一样!

测试

package com.csa.app;

import java.io.InputStream;
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 com.csa.dao.StudentMapper;
import com.csa.po.Student;

public class App {
	public static void main(String[] args) throws Exception {
		// 读取全局配置文件
		String resource = "SqlMapConfig.xml";
		InputStream input = Resources.getResourceAsStream(resource);
		// 创建SqlSessionFactory
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
		// 创建sqlSession
		SqlSession sqlSession1 = sqlSessionFactory.openSession();
		SqlSession sqlSession2 = sqlSessionFactory.openSession();
		SqlSession sqlSession3 = sqlSessionFactory.openSession();
		// 创建dao
		StudentMapper studentMapper1 = sqlSession1.getMapper(StudentMapper.class);
		StudentMapper studentMapper2 = sqlSession2.getMapper(StudentMapper.class);
		StudentMapper studentMapper3 = sqlSession3.getMapper(StudentMapper.class);
		Student student1 = studentMapper1.selectStudentById(2);
		// 关闭sqlSession
		sqlSession1.close();
		Student student2 = studentMapper2.selectStudentById(2);
		sqlSession2.close();
		Student student3 = studentMapper3.selectStudentById(2);
		Student student11 = studentMapper3.selectStudentById(4);
		sqlSession3.close();
		System.out.println(student1);
		System.out.println(student2);
		System.out.println(student3);
		System.out.println(student11);
	}
	
}

测试结果

在这里插入图片描述

禁用缓存与刷新缓存

<!-- 
	useCache:是否使用缓存
	flushCache:是否刷新缓存
 -->
<!-- 通过id查找该学生选修的课程 -->
<select id="selectStudentById" parameterType="int" resultMap="Student"
	useCache="false" flushCache="true">
	select * from student 
	where student_id = #{studentId}
</select>

3.3、整合ehcache

应用场景

使用场景:对于访问响应速度要求高,但是实时性不高的查询,可以采用二级缓存技术。

注意:在使用二级缓存的时候,要设置一下刷新间隔(cache标签中有一个flashInterval属性)来定时刷新二级缓存,这个刷新间隔根据具体需求来设置,比如设置30分钟、60分钟等,单位为毫秒。

导包

在这里插入图片描述

添加ehcache.xml文件(下面的diskStore是我们自己的缓存路径)

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">

    <!--
    The ehcache-failsafe.xml is a default configuration for ehcache, if an ehcache.xml is not configured.

    The diskStore element is optional. It must be configured if you have overflowToDisk or diskPersistent enabled
    for any cache. If it is not configured, a warning will be issues and java.io.tmpdir will be used.

    diskStore has only one attribute - "path". It is the path to the directory where .data and .index files will be created.

    If the path is a Java System Property it is replaced by its value in the
    running VM.

    The following properties are translated:
    * user.home - User's home directory
    * user.dir - User's current working directory
    * java.io.tmpdir - Default temp file path
    * ehcache.disk.store.dir - A system property you would normally specify on the command line
          e.g. java -Dehcache.disk.store.dir=/u01/myapp/diskdir ...

    Subdirectories can be specified below the property e.g. java.io.tmpdir/one

    -->
    <diskStore path="java.io.tmpdir"/>

    <!--
    Specifies a CacheManagerEventListenerFactory, be used to create a CacheManagerPeerProvider,
    which is notified when Caches are added or removed from the CacheManager.

    The attributes of CacheManagerEventListenerFactory are:
    * class - a fully qualified factory class name
    * properties - comma separated properties having meaning only to the factory.

    Sets the fully qualified class name to be registered as the CacheManager event listener.

    The events include:
    * adding a Cache
    * removing a Cache

    Callbacks to listener methods are synchronous and unsynchronized. It is the responsibility
    of the implementer to safely handle the potential performance and thread safety issues
    depending on what their listener is doing.

    If no class is specified, no listener is created. There is no default.

    <cacheManagerEventListenerFactory class="" properties=""/>
    -->

    <!--
    (Enable for distributed operation)

    Specifies a CacheManagerPeerProviderFactory which will be used to create a
    CacheManagerPeerProvider, which discovers other CacheManagers in the cluster.

    The attributes of cacheManagerPeerProviderFactory are:
    * class - a fully qualified factory class name
    * properties - comma separated properties having meaning only to the factory.

    Ehcache comes with a built-in RMI-based distribution system with two means of discovery of
    CacheManager peers participating in the cluster:
    * automatic, using a multicast group. This one automatically discovers peers and detects
      changes such as peers entering and leaving the group
    * manual, using manual rmiURL configuration. A hardcoded list of peers is provided at
      configuration time.

    Configuring Automatic Discovery:
    Automatic discovery is configured as per the following example:
    <cacheManagerPeerProviderFactory
                        class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
                        properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1,
                                    multicastGroupPort=4446, timeToLive=32"/>

    Valid properties are:
    * peerDiscovery (mandatory) - specify "automatic"
    * multicastGroupAddress (mandatory) - specify a valid multicast group address
    * multicastGroupPort (mandatory) - specify a dedicated port for the multicast heartbeat
      traffic
    * timeToLive - specify a value between 0 and 255 which determines how far the packets will propagate.
      By convention, the restrictions are:
      0   - the same host
      1   - the same subnet
      32  - the same site
      64  - the same region
      128 - the same continent
      255 - unrestricted


    Configuring Manual Discovery:
    Manual discovery is configured as per the following example:
    <cacheManagerPeerProviderFactory class=
                          "net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
                          properties="peerDiscovery=manual,
                          rmiUrls=//server1:40000/sampleCache1|//server2:40000/sampleCache1
                          | //server1:40000/sampleCache2|//server2:40000/sampleCache2"/>

    Valid properties are:
    * peerDiscovery (mandatory) - specify "manual"
    * rmiUrls (mandatory) - specify a pipe separated list of rmiUrls, in the form
                            //hostname:port

    The hostname is the hostname of the remote CacheManager peer. The port is the listening
    port of the RMICacheManagerPeerListener of the remote CacheManager peer.

    <cacheManagerPeerProviderFactory
            class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
            properties="peerDiscovery=automatic,
                        multicastGroupAddress=230.0.0.1,
                        multicastGroupPort=4446, timeToLive=1"/>
    -->

    <!--
    (Enable for distributed operation)

    Specifies a CacheManagerPeerListenerFactory which will be used to create a
    CacheManagerPeerListener, which
    listens for messages from cache replicators participating in the cluster.

    The attributes of cacheManagerPeerListenerFactory are:
    class - a fully qualified factory class name
    properties - comma separated properties having meaning only to the factory.

    Ehcache comes with a built-in RMI-based distribution system. The listener component is
    RMICacheManagerPeerListener which is configured using
    RMICacheManagerPeerListenerFactory. It is configured as per the following example:

    <cacheManagerPeerListenerFactory
        class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
        properties="hostName=fully_qualified_hostname_or_ip,
                    port=40001,
                    socketTimeoutMillis=120000"/>

    All properties are optional. They are:
    * hostName - the hostName of the host the listener is running on. Specify
      where the host is multihomed and you want to control the interface over which cluster
      messages are received. Defaults to the host name of the default interface if not
      specified.
    * port - the port the listener listens on. This defaults to a free port if not specified.
    * socketTimeoutMillis - the number of ms client sockets will stay open when sending
      messages to the listener. This should be long enough for the slowest message.
      If not specified it defaults 120000ms.

    <cacheManagerPeerListenerFactory
            class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"/>
    -->


    <!-- Cache configuration.

    The following attributes are required.

    name:
    Sets the name of the cache. This is used to identify the cache. It must be unique.

    maxElementsInMemory:
    Sets the maximum number of objects that will be created in memory (0 == no limit)

	maxElementsOnDisk:
    Sets the maximum number of objects that will be maintained in the DiskStore
	The default value is zero, meaning unlimited.

    eternal:
    Sets whether elements are eternal. If eternal,  timeouts are ignored and the
    element is never expired.

    overflowToDisk:
    Sets whether elements can overflow to disk when the in-memory cache
    has reached the maxInMemory limit.

    The following attributes are optional.

    timeToIdleSeconds:
    Sets the time to idle for an element before it expires.
    i.e. The maximum amount of time between accesses before an element expires
    Is only used if the element is not eternal.
    Optional attribute. A value of 0 means that an Element can idle for infinity.
    The default value is 0.

    timeToLiveSeconds:
    Sets the time to live for an element before it expires.
    i.e. The maximum time between creation time and when an element expires.
    Is only used if the element is not eternal.
    Optional attribute. A value of 0 means that and Element can live for infinity.
    The default value is 0.

    diskPersistent:
    Whether the disk store persists between restarts of the Virtual Machine.
    The default value is false.

    diskExpiryThreadIntervalSeconds:
    The number of seconds between runs of the disk expiry thread. The default value
    is 120 seconds.

    diskSpoolBufferSizeMB:
    This is the size to allocate the DiskStore for a spool buffer. Writes are made
    to this area and then asynchronously written to disk. The default size is 30MB.
    Each spool buffer is used only by its cache. If you get OutOfMemory errors consider
    lowering this value. To improve DiskStore performance consider increasing it. Trace level
    logging in the DiskStore will show if put back ups are occurring.

    memoryStoreEvictionPolicy:
    Policy would be enforced upon reaching the maxElementsInMemory limit. Default
    policy is Least Recently Used (specified as LRU). Other policies available -
    First In First Out (specified as FIFO) and Less Frequently Used
    (specified as LFU)

    Cache elements can also contain sub elements which take the same format of a factory class
    and properties. Defined sub-elements are:

    * cacheEventListenerFactory - Enables registration of listeners for cache events, such as
      put, remove, update, and expire.

    * bootstrapCacheLoaderFactory - Specifies a BootstrapCacheLoader, which is called by a
      cache on initialisation to prepopulate itself.

    Each cache that will be distributed needs to set a cache event listener which replicates
    messages to the other CacheManager peers. For the built-in RMI implementation this is done
    by adding a cacheEventListenerFactory element of type RMICacheReplicatorFactory to each
    distributed cache's configuration as per the following example:

    <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
         properties="replicateAsynchronously=true,
         replicatePuts=true,
         replicateUpdates=true,
         replicateUpdatesViaCopy=true,
         replicateRemovals=true "/>

    The RMICacheReplicatorFactory recognises the following properties:

    * replicatePuts=true|false - whether new elements placed in a cache are
      replicated to others. Defaults to true.

    * replicateUpdates=true|false - whether new elements which override an
      element already existing with the same key are replicated. Defaults to true.

    * replicateRemovals=true - whether element removals are replicated. Defaults to true.

    * replicateAsynchronously=true | false - whether replications are
      asynchronous (true) or synchronous (false). Defaults to true.

    * replicateUpdatesViaCopy=true | false - whether the new elements are
      copied to other caches (true), or whether a remove message is sent. Defaults to true.


    * asynchronousReplicationIntervalMillis=<number of milliseconds> - The asynchronous
      replicator runs at a set interval of milliseconds. The default is 1000. The minimum
      is 10. This property is only applicable if replicateAsynchronously=true

    * asynchronousReplicationMaximumBatchSize=<number of operations> - The maximum
      number of operations that will be batch within a single RMI message.  The default
      is 1000. This property is only applicable if replicateAsynchronously=true

    The RMIBootstrapCacheLoader bootstraps caches in clusters where RMICacheReplicators are
    used. It is configured as per the following example:

    <bootstrapCacheLoaderFactory
        class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
        properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>

    The RMIBootstrapCacheLoaderFactory recognises the following optional properties:

    * bootstrapAsynchronously=true|false - whether the bootstrap happens in the background
      after the cache has started. If false, bootstrapping must complete before the cache is
      made available. The default value is true.

    * maximumChunkSizeBytes=<integer> - Caches can potentially be very large, larger than the
      memory limits of the VM. This property allows the bootstraper to fetched elements in
      chunks. The default chunk size is 5000000 (5MB).

    -->


    <!--
    Mandatory Default Cache configuration. These settings will be applied to caches
    created programmtically using CacheManager.add(String cacheName)
    -->
    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            maxElementsOnDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
        <persistence strategy="localTempSwap"/>
    </defaultCache>
</ehcache>

修改StudentMapper.xml

<!-- 开启二级缓存,默认使用了org.mybatis.caches.ehcache.EncacheCache -->
<cache type="org.mybatis.caches.ehcache.EncacheCache"/>

4、逆向工程(发送一波黑马笔记)

4.1、下载逆向工程

逆向工程jar的下载地址

4.2、创建逆向工程

在这里插入图片描述

4.3、创建Generator.java

在这里插入图片描述

4.4、添加generatorConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
	<context id="testTables" targetRuntime="MyBatis3">
		<commentGenerator>
			<!-- 是否去除自动生成的注释 true:是 : false:否 -->
			<property name="suppressAllComments" value="true" />
		</commentGenerator>
		<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
		<jdbcConnection driverClass="com.mysql.jdbc.Driver"
			connectionURL="jdbc:mysql://localhost:3306/mybatis" userId="root"
			password="root">
		</jdbcConnection>
		<!-- <jdbcConnection driverClass="oracle.jdbc.OracleDriver" connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg" 
			userId="yycg" password="yycg"> </jdbcConnection> -->

		<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 
			和 NUMERIC 类型解析为java.math.BigDecimal -->
		<javaTypeResolver>
			<property name="forceBigDecimals" value="false" />
		</javaTypeResolver>

		<!-- targetProject:生成PO类的位置 -->
		<javaModelGenerator targetPackage="com.itheima.ms.po"
			targetProject=".\src">
			<!-- enableSubPackages:是否让schema作为包的后缀 -->
			<property name="enableSubPackages" value="false" />
			<!-- 从数据库返回的值被清理前后的空格 -->
			<property name="trimStrings" value="true" />
		</javaModelGenerator>
		<!-- targetProject:mapper映射文件生成的位置 -->
		<sqlMapGenerator targetPackage="com.itheima.ms.mapper"
			targetProject=".\src">
			<!-- enableSubPackages:是否让schema作为包的后缀 -->
			<property name="enableSubPackages" value="false" />
		</sqlMapGenerator>
		<!-- targetPackage:mapper接口生成的位置 -->
		<javaClientGenerator type="XMLMAPPER"
			targetPackage="com.itheima.ms.mapper" targetProject=".\src">
			<!-- enableSubPackages:是否让schema作为包的后缀 -->
			<property name="enableSubPackages" value="false" />
		</javaClientGenerator>
		<!-- 指定数据库表 -->
		<table tableName="items"></table>
		<table tableName="orders"></table>
		<table tableName="orderdetail"></table>
		<table tableName="user"></table>
	</context>
</generatorConfiguration>

4.5、注意事项

Mapper.xml文件已经存在时,如果进行重新生成则mapper.xml文件时,内容不被覆盖而是进行内容追加,结果导致mybatis解析失败。

解决方法:删除原来已经生成的mapper xml文件再进行生成。

Mybatis自动生成的po及mapper.java文件不是内容而是直接覆盖没有此问题。

参考

黑马笔记、黑马、黑马!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值