一、常用框架个功能结构图
二、Mybatis框架的概述
mybatis 是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql 语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。
mybatis 通过 xml 或注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。
采用 ORM 思想解决了实体和数据库映射的问题,对 jdbc 进行了封装,屏蔽了 jdbc api 底层访问细节,使我们不用与 jdbc api 打交道,就可以完成对数据库的持久化操作。
为了我们能够更好掌握框架运行的内部过程,并且有更好的体验,下面我们将从自定义 Mybatis 框架开始来学习框架。此时我们将会体验框架从无到有的过程体验,也能够很好的综合前面阶段所学的基础。
三、ORM(Object Relational Mappging 对象关系映射)
简单的说: 就是把数据库表和实体类及实体类的属性对应起来,让我们可以操作实体类就实现操作数据库表。
user表中的字段 | User实体中的属性 |
---|
id | userId | user_name | userName |
四、Mybatis入门案例
1. 数据库准备
DROP TABLE IF EXISTS user ; CREATE TABLE user ( ? id INT(11) NOT NULL AUTO_INCREMENT, ?username VARCHAR(32) NOT NULL COMMENT ‘用户名称’, ?birthday DATETIME DEFAULT NULL COMMENT ‘生日’, ? sex CHAR(1) DEFAULT NULL COMMENT ‘性别’, ?address VARCHAR(256) DEFAULT NULL COMMENT ‘地址’, ? PRIMARY KEY (id ) ) ENGINE=INNODB DEFAULT CHARSET=utf8; INSERT INTO user (id ,username ,birthday ,sex ,address ) VALUES (41,‘老王’,‘2018-02-27 17:47:08’,‘男’,‘北京’),(42,‘小二王’,‘2018-03-02 15:09:37’,‘女’,‘北京朝阳区’),(43,‘小二王’,‘2018-03-04 11:34:34’,‘女’,‘北京昌平区’),(45,‘柯基侦探’,‘2018-03-04 12:04:06’,‘男’,‘北京大兴区’),(46,‘老王’,‘2018-03-07 17:37:26’,‘男’,‘北京’),(48,‘小马宝莉’,‘2018-03-08 11:44:00’,‘女’,‘北京东城’);
2. Mybatis的入门案例
项目结构
⑴ 创建maven工程并导入坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kejizhentan</groupId>
<artifactId>mybatis-project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--Mybatis框架的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql数据库驱动的依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--生成日志文件的依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--junit单元测试的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
⑵ 创建实体类和dao的接口
User.java
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
IUserDao.java
public interface IUserDao {
List<User> findAll();
}
⑶ 创建Mybatis的主配置文件
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">
<!--Mybatis的主配置文件-->
<configuration>
<!--配置环境-->
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<dataSource type="POOLED">
<!--配置数据的四个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db4"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件-->
<mappers>
<mapper resource="com/kejizhentan/dao/IUserDao.xml"/>
</mappers>
</configuration>
⑷ 创建映射配置文件
IUserDao.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.kejizhentan.dao.IUserDao">
<!--配置查询所有-->
<select id = "findAll" resultType="com.kejizhentan.bean.User">
select * from user
</select>
</mapper>
⑸ 测试类:
MybatisTest.java
public class MybatisTest {
@Test
public void test1(){
InputStream is = null;
SqlSession sqlSession = null;
try {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
//3.使用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}catch (Exception e){
e.printStackTrace();
}finally {
//6.释放资源
if(sqlSession != null){
sqlSession.close();
}
try {
if(is != null){
is.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
执行结果如下:
注意事项: ⑴ 环境搭建的注意事项: ① 创建IUserDao.xml 和 IUserDao.java时名称是为了和我们之前的知识保持一致。 在Mybatis中它把持久层的操作接口名称和映射文件也叫做:Mapper 所以:IUserDao 和 IUserMapper是一样的 ② 在idea中创建目录的时候,它和包是不一样的 包在创建时:com.itheima.dao 它是三级结构 目录在创建时:com.itheima.dao 是一级目录 所以创建时要一步步分开创建
③ mybatis的映射配置文件位置必须和dao接口的包结构相同 ④ 映射配置文件的mapper标签namespace属性的取值必须是dao接口的全限定类名 ⑤ 映射配置文件的操作配置(select),id属性的取值必须是dao接口的方法名 当我们遵从了第③,④,⑤点之后,我们在开发中就无须再写dao的实现类。 ⑵ mybatis测试类中的注意事项: 不要忘记在映射配置中告知mybatis要封装到哪个实体类中 配置的方式:指定实体类的全限定类名
3. 使用注解来实现2中的入门案例
项目结构
⑴ 创建maven工程并导入坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kejizhentan</groupId>
<artifactId>mybatis-project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--Mybatis框架的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql数据库驱动的依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--生成日志文件的依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--junit单元测试的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
⑵ 创建实体类和dao的接口
User.java
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
IUserDao.java
public interface IUserDao {
@Select("select * from user")
List<User> findAll();
}
⑶ 创建Mybatis的主配置文件
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">
<!--Mybatis的主配置文件-->
<configuration>
<!--配置环境-->
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<dataSource type="POOLED">
<!--配置数据的四个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db4"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--
使用配置文件来实现mybatis的配置:
指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
使用注解来实现mybatis的配置:
如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
-->
<mappers>
<!--<mapper resource="com/kejizhentan/dao/IUserDao.xml"/>-->
<mapper class="com.kejizhentan.dao.IUserDao"/>
</mappers>
</configuration>
⑷ 测试类:
MybatisTest.java
public class MybatisTest {
@Test
public void test1(){
InputStream is = null;
SqlSession sqlSession = null;
try {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
//3.使用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}catch (Exception e){
e.printStackTrace();
}finally {
//6.释放资源
if(sqlSession != null){
sqlSession.close();
}
try {
if(is != null){
is.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
执行结果如下:
mybatis基于注解的入门案例的步骤: 把IUserDao.xml移除,在dao接口的方法上使用@Select注解,并且指定SQL语句 同时需要在SqlMapConfig.xml中的mapper配置时,使用class属性指定dao接口的全限定类名 注意: 我们在实际开发中,都是越简便越好,所以都是采用不写dao实现类的方式。 不管使用XML还是注解配置。但是Mybatis它是支持写dao实现类的。
五、 自定义Mybatis框架(底层原理)
自定Mybatis框架的分析: 自定义Mybatis框架流程
1. 自定义mybatis框架所涉及的主要几个类
自定义mybatis能通过入门案例看到类 class Resources class SqlSessionFactoryBuilder interface SqlSessionFactory interface SqlSession
2. 自定义Mybatis框架的项目结构
3. 自定义Mybatis框架详解
⑴ 实体类和dao的接口
User.java
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
IUserDao.java
public interface IUserDao {
@Select("select * from user")
List<User> findAll();
}
⑵ 测试类MybatisTest :
public class MybatisTest {
@Test
public void test1(){
InputStream is = null;
SqlSession sqlSession = null;
try {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
//3.使用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}catch (Exception e){
e.printStackTrace();
}finally {
//6.释放资源
if(sqlSession != null){
sqlSession.close();
}
try {
if(is != null){
is.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
⑶ 类加载器读取配置文件Resources类
public class Resources {
public static InputStream getResourceAsStream(String file){
return Resources.class.getClassLoader().getResourceAsStream(file);
}
}
⑷ 用于创建一个SqlSessionFactory对象的SqlSessionFactoryBuilder
public class SqlSessionFactoryBuilder {
public SqlSessionFactory build(InputStream is){
Configuration cfg = XMLConfigBuilder.loadConfiguration(is);
return new DefaultSqlSessionFactory(cfg);
}
}
⑸ 用于打开一个新的SqlSession对象的SqlSessionFactory 接口及其实现类DefaultSqlSessionFactory
SqlSessionFactory 接口
public interface SqlSessionFactory {
SqlSession openSession();
}
实现类DefaultSqlSessionFactory
public class DefaultSqlSessionFactory implements SqlSessionFactory {
private Configuration cfg;
public DefaultSqlSessionFactory(Configuration cfg) {
this.cfg = cfg;
}
public SqlSession openSession() {
return new DefaultSqlSession(cfg);
}
}
⑹ 自定义Mybatis中和数据库交互的核心接口SqlSession及其实现类DefaultSqlSession(这个最重要)
SqlSession接口:
public interface SqlSession {
<T> T getMapper(Class<T> daoInterfaceClass);
void close();
}
DefaultSqlSession实现类:
public class DefaultSqlSession implements SqlSession {
private Configuration cfg;
private Connection conn;
public DefaultSqlSession(Configuration cfg) {
this.cfg = cfg;
conn = DataSourceUtil.getConnection(cfg);
}
public <T> T getMapper(Class<T> daoInterfaceClass) {
return (T)Proxy.newProxyInstance(daoInterfaceClass.getClassLoader(),
new Class[]{daoInterfaceClass},
new MapperProxy(cfg.getMappers(), conn));
}
public void close() {
try {
if(conn != null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
⑺ 动态代理的功能核心类MapperProxy
public class MapperProxy implements InvocationHandler {
//map的key是全限定类名+方法名
private Map<String, Mapper> mappers;
private Connection conn;
public MapperProxy(Map<String, Mapper> mappers,Connection conn) {
this.mappers = mappers;
this.conn = conn;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//1. 获取方法名
String methodName = method.getName();
//2. 获取方法所在类的名称
String className = method.getDeclaringClass().getName();
//3.组合key
String key = className +"."+methodName;
//4.获取mappers中的mapper对象
Mapper mapper = mappers.get(key);
//5.判断是否有mapper
if(mapper == null){
throw new IllegalArgumentException("传入的参数有误");
}
//6.调用工具类执行查询所有
return new Executor().selectList(mapper,conn);
}
}
⑻ 自定义Mybatis的配置类Configuration
Configuration
public class Configuration {
private String driver;
private String url;
private String username;
private String password;
Map<String, Mapper> mappers = new HashMap<String, Mapper>();
public Map<String, Mapper> getMappers() {
return mappers;
}
public void setMappers(Map<String, Mapper> mappers) {
this.mappers.putAll(mappers);//此处需要使用追加的方式
}
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
⑼ 用于封装执行的SQL语句和结果类型的全限定类名的Mapper类
public class Mapper {
private String queryString;//执行的SQL语句
private String resultType;//实体类的全限定类名
public String getQueryString() {
return queryString;
}
public void setQueryString(String queryString) {
this.queryString = queryString;
}
public String getResultType() {
return resultType;
}
public void setResultType(String resultType) {
this.resultType = resultType;
}
}
⑽ 自定义Mybatis中使用到的工具类(这些工具类一般不属于核心代码部分)
用于创建数据源的工具类DataSourceUtil
public class DataSourceUtil {
public static Connection getConnection(Configuration cfg) {
try {
Class.forName(cfg.getDriver());
return DriverManager.getConnection(cfg.getUrl(), cfg.getUsername(), cfg.getPassword());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
负责执行SQL语句,并且封装结果集的工具类Executor
public class Executor {
public <E> List<E> selectList(Mapper mapper, Connection conn) {
PreparedStatement pstm = null;
ResultSet rs = null;
try {
//1.取出mapper中的数据
String queryString = mapper.getQueryString();//select * from user
String resultType = mapper.getResultType();//com.itheima.domain.User
Class domainClass = Class.forName(resultType);
//2.获取PreparedStatement对象
pstm = conn.prepareStatement(queryString);
//3.执行SQL语句,获取结果集
rs = pstm.executeQuery();
//4.封装结果集
List<E> list = new ArrayList<E>();//定义返回值
while(rs.next()) {
//实例化要封装的实体类对象
E obj = (E)domainClass.newInstance();
//取出结果集的元信息:ResultSetMetaData
ResultSetMetaData rsmd = rs.getMetaData();
//取出总列数
int columnCount = rsmd.getColumnCount();
//遍历总列数
for (int i = 1; i <= columnCount; i++) {
//获取每列的名称,列名的序号是从1开始的
String columnName = rsmd.getColumnName(i);
//根据得到列名,获取每列的值
Object columnValue = rs.getObject(columnName);
//给obj赋值:使用Java内省机制(借助PropertyDescriptor实现属性的封装)
PropertyDescriptor pd = new PropertyDescriptor(columnName,domainClass);//要求:实体类的属性和数据库表的列名保持一种
//获取它的写入方法
Method writeMethod = pd.getWriteMethod();
//把获取的列的值,给对象赋值
writeMethod.invoke(obj,columnValue);
}
//把赋好值的对象加入到集合中
list.add(obj);
}
return list;
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
release(pstm,rs);
}
}
private void release(PreparedStatement pstm,ResultSet rs){
if(rs != null){
try {
rs.close();
}catch(Exception e){
e.printStackTrace();
}
}
if(pstm != null){
try {
pstm.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
}
dom4j工具类XMLConfigBuilder,用于解析xml
public class XMLConfigBuilder {
public static Configuration loadConfiguration(InputStream config){
try{
//定义封装连接信息的配置对象(mybatis的配置对象)
Configuration cfg = new Configuration();
//1.获取SAXReader对象
SAXReader reader = new SAXReader();
//2.根据字节输入流获取Document对象
Document document = reader.read(config);
//3.获取根节点
Element root = document.getRootElement();
//4.使用xpath中选择指定节点的方式,获取所有property节点
List<Element> propertyElements = root.selectNodes("//property");
//5.遍历节点
for(Element propertyElement : propertyElements){
//判断节点是连接数据库的哪部分信息
//取出name属性的值
String name = propertyElement.attributeValue("name");
if("driver".equals(name)){
//表示驱动
//获取property标签value属性的值
String driver = propertyElement.attributeValue("value");
cfg.setDriver(driver);
}
if("url".equals(name)){
//表示连接字符串
//获取property标签value属性的值
String url = propertyElement.attributeValue("value");
cfg.setUrl(url);
}
if("username".equals(name)){
//表示用户名
//获取property标签value属性的值
String username = propertyElement.attributeValue("value");
cfg.setUsername(username);
}
if("password".equals(name)){
//表示密码
//获取property标签value属性的值
String password = propertyElement.attributeValue("value");
cfg.setPassword(password);
}
}
//取出mappers中的所有mapper标签,判断他们使用了resource还是class属性
List<Element> mapperElements = root.selectNodes("//mappers/mapper");
//遍历集合
for(Element mapperElement : mapperElements){
//判断mapperElement使用的是哪个属性
Attribute attribute = mapperElement.attribute("resource");
if(attribute != null){
System.out.println("使用的是XML");
//表示有resource属性,用的是XML
//取出属性的值
String mapperPath = attribute.getValue();//获取属性的值"com/itheima/dao/IUserDao.xml"
//把映射配置文件的内容获取出来,封装成一个map
Map<String, Mapper> mappers = loadMapperConfiguration(mapperPath);
//给configuration中的mappers赋值
cfg.setMappers(mappers);
}else{
System.out.println("使用的是注解");
//表示没有resource属性,用的是注解
//获取class属性的值
String daoClassPath = mapperElement.attributeValue("class");
//根据daoClassPath获取封装的必要信息
Map<String,Mapper> mappers = loadMapperAnnotation(daoClassPath);
//给configuration中的mappers赋值
cfg.setMappers(mappers);
}
}
//返回Configuration
return cfg;
}catch(Exception e){
throw new RuntimeException(e);
}finally{
try {
config.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
private static Map<String,Mapper> loadMapperConfiguration(String mapperPath)throws IOException {
InputStream in = null;
try{
//定义返回值对象
Map<String,Mapper> mappers = new HashMap<String,Mapper>();
//1.根据路径获取字节输入流
in = Resources.getResourceAsStream(mapperPath);
//2.根据字节输入流获取Document对象
SAXReader reader = new SAXReader();
Document document = reader.read(in);
//3.获取根节点
Element root = document.getRootElement();
//4.获取根节点的namespace属性取值
String namespace = root.attributeValue("namespace");//是组成map中key的部分
//5.获取所有的select节点
List<Element> selectElements = root.selectNodes("//select");
//6.遍历select节点集合
for(Element selectElement : selectElements){
//取出id属性的值 组成map中key的部分
String id = selectElement.attributeValue("id");
//取出resultType属性的值 组成map中value的部分
String resultType = selectElement.attributeValue("resultType");
//取出文本内容 组成map中value的部分
String queryString = selectElement.getText();
//创建Key
String key = namespace+"."+id;
//创建Value
Mapper mapper = new Mapper();
mapper.setQueryString(queryString);
mapper.setResultType(resultType);
//把key和value存入mappers中
mappers.put(key,mapper);
}
return mappers;
}catch(Exception e){
throw new RuntimeException(e);
}finally{
in.close();
}
}
private static Map<String,Mapper> loadMapperAnnotation(String daoClassPath)throws Exception{
//定义返回值对象
Map<String,Mapper> mappers = new HashMap<String, Mapper>();
//1.得到dao接口的字节码对象
Class daoClass = Class.forName(daoClassPath);
//2.得到dao接口中的方法数组
Method[] methods = daoClass.getMethods();
//3.遍历Method数组
for(Method method : methods){
//取出每一个方法,判断是否有select注解
boolean isAnnotated = method.isAnnotationPresent(Select.class);
if(isAnnotated){
//创建Mapper对象
Mapper mapper = new Mapper();
//取出注解的value属性值
Select selectAnno = method.getAnnotation(Select.class);
String queryString = selectAnno.value();
mapper.setQueryString(queryString);
//获取当前方法的返回值,还要求必须带有泛型信息
Type type = method.getGenericReturnType();//List<User>
//判断type是不是参数化的类型
if(type instanceof ParameterizedType){
//强转
ParameterizedType ptype = (ParameterizedType)type;
//得到参数化类型中的实际类型参数
Type[] types = ptype.getActualTypeArguments();
//取出第一个
Class domainClass = (Class)types[0];
//获取domainClass的类名
String resultType = domainClass.getName();
//给Mapper赋值
mapper.setResultType(resultType);
}
//组装key的信息
//获取方法的名称
String methodName = method.getName();
String className = method.getDeclaringClass().getName();
String key = className+"."+methodName;
//给map赋值
mappers.put(key,mapper);
}
}
return mappers;
}
}
⑾ 自定义的查询注解@Select
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Select {
String value();
}
⑿ 使用XML配置查询时用的IUserDao.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<mapper namespace="com.kejizhentan.dao.IUserDao">
<!--配置查询所有-->
<select id = "findAll" resultType="com.kejizhentan.bean.User">
select * from user
</select>
</mapper>
⒀ 主配置文件SqlMapConfig.xml
<!--Mybatis的主配置文件-->
<configuration>
<!--配置环境-->
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<dataSource type="POOLED">
<!--配置数据的四个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db4"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--
使用配置文件来实现mybatis的配置:
指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
使用注解来实现mybatis的配置:
如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
-->
<mappers>
<!--<mapper resource="com/kejizhentan/dao/IUserDao.xml"/>-->
<mapper class="com.kejizhentan.dao.IUserDao"/>
</mappers>
</configuration>
⒁ 执行结果如下:
六、 Mybatis的CRUD操作
项目结构:
⑴ 创建maven工程并导入坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kejizhentan</groupId>
<artifactId>mybatis-project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--Mybatis框架的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql数据库驱动的依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--生成日志文件的依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--junit单元测试的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
⑵ 创建实体类和dao的接口
User.java
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
IUserDao.java
public interface IUserDao {
List<User> findAll();
void saveUser(User user);
void updateUser(User user);
void deleteUser(Integer userId);
User findById(Integer userId);
List<User> findByName(String username);
int findTotal();
}
⑶ 创建Mybatis的主配置文件
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">
<!--Mybatis的主配置文件-->
<configuration>
<!--配置环境-->
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<dataSource type="POOLED">
<!--配置数据的四个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db4"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件-->
<mappers>
<mapper resource="com/kejizhentan/dao/IUserDao.xml"/>
</mappers>
</configuration>
⑷ 创建映射配置文件
IUserDao.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.kejizhentan.dao.IUserDao">
<!--配置查询所有-->
<select id = "findAll" resultType="com.kejizhentan.bean.User">
select * from user
</select>
<!-- 保存用户 -->
<insert id="saveUser" parameterType="com.kejizhentan.bean.User">
insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday});
</insert>
<!-- 更新用户 -->
<update id="updateUser" parameterType="com.kejizhentan.bean.User">
update user set username=#{username},address=#{address},sex=#{sex},birthday=#{birthday} where id=#{id}
</update>
<!-- 根据id删除用户-->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id = #{uid}
</delete>
<!-- 根据id查询用户 -->
<select id="findById" parameterType="int" resultType="com.kejizhentan.bean.User">
select * from user where id = #{uid}
</select>
<!-- 根据名称模糊查询 -->
<select id="findByName" parameterType="string" resultType="com.kejizhentan.bean.User">
<!--select * from user where username like #{name}-->
<!--select * from user where username like '%${value}%'-->
select * from user where username like concat('%',#{name},'%')
</select>
<!-- 获取用户的总记录条数 -->
<select id="findTotal" resultType="int">
select count(id) from user;
</select>
</mapper>
⑸ 测试类:
MybatisTest.java
public class MybatisTest {
private InputStream is;
private SqlSession sqlSession;
private IUserDao userDao;
@Before//用于在执行方法执行之前执行
public void init(){
try {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
//3.使用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
userDao = sqlSession.getMapper(IUserDao.class);
}catch (Exception e){
e.printStackTrace();
}
}
@After//用于在测试方法执行之后执行
public void close(){
//提交事务
sqlSession.commit();
//6.释放资源
if(sqlSession != null){
sqlSession.close();
}
try {
if(is != null){
is.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
@Test
public void findAll(){
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}
@Test
public void saveUser(){
//实例化对象
User user = new User();
user.setUsername("李云迪");
user.setAddress("朝阳区");
user.setBirthday(new Date());
user.setSex("男");
//6.使用代理对象执行方法
userDao.saveUser(user);
}
@Test
public void updateUser(){
//实例化对象
User user = new User();
user.setId(52);
user.setUsername("朝阳群众");
user.setAddress("朝阳区");
user.setBirthday(new Date());
user.setSex("女");
//6.使用代理对象执行方法
userDao.updateUser(user);
}
@Test
public void deleteUser(){
userDao.deleteUser(52);
}
@Test
public void findById(){
User user = userDao.findById(45);
System.out.println(user);
}
@Test
public void findByName(){
//List<User> users = userDao.findByName("%王%");
List<User> users = userDao.findByName("王");
for (User user : users) {
System.out.println(user);
}
}
@Test
public void findTotal(){
int num = userDao.findTotal();
System.out.println("一共"+num+"条数据");
}
}
注意事项: Mybatis中#{}和${}的区别i:
七、 Mybatis中的细节
1. 获取新增数据的id
<!-- 保存用户 -->
<insert id="saveUser" parameterType="com.kejizhentan.bean.User">
<!--配置插入操作后,获取插入数据的id-->
<selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
select last_insert_id()
</selectKey>
insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday})
</insert>
结果如下:
2. Mybatis框架中OGNL表达式使用介绍
OGNL全称是Object Graphic Navigation Language ???????对象?? 图 ??导航 ?? 语言 它是通过对象的取值方法来获取数据。在写法上把get给省略了。 比如:我们获取用户的名称 类中的写法:user. getUsername(); OGNL表达式写法:user. username
mybatis中为什么能直接写username,而不用user. 呢? 因为在parameterType中已经提供了属性所属的类,所以此时不需要写对象名
例如:需求:根据用户名查询用户信息,查询条件放到 QueryVo 的 user 属性中。 QueryVo.java
public class QueryVo {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
User.java
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
3. Mybatis中对象中的属性和表中的字段对应不上的问题
⑴ 解决方式一:起别名的方式(这种方式执行效率最高)
⑵ 解决方式二:配置表的列名和实体的属性名的对应关系
4. Mybatis中的细节中的详细代码
项目结构:
⑴ 创建maven工程并导入坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kejizhentan</groupId>
<artifactId>mybatis-project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--Mybatis框架的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql数据库驱动的依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--生成日志文件的依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--junit单元测试的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
⑵ 创建实体类和dao的接口
User.java
public class User implements Serializable {
private Integer userId;
private String userName;
private Date userBirthday;
private String userSex;
private String userAddress;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Date getUserBirthday() {
return userBirthday;
}
public void setUserBirthday(Date userBirthday) {
this.userBirthday = userBirthday;
}
public String getUserSex() {
return userSex;
}
public void setUserSex(String userSex) {
this.userSex = userSex;
}
public String getUserAddress() {
return userAddress;
}
public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
}
@Override
public String toString() {
return "User{" +
"userId=" + userId +
", userName='" + userName + '\'' +
", userBirthday=" + userBirthday +
", userSex='" + userSex + '\'' +
", userAddress='" + userAddress + '\'' +
'}';
}
}
QueryVo.java
public class QueryVo {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
IUserDao.java
public interface IUserDao {
List<User> findAll();
void saveUser(User user);
User findUserByQueryVo(QueryVo queryVo);
}
⑶ 创建Mybatis的主配置文件
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">
<!--Mybatis的主配置文件-->
<configuration>
<!--配置环境-->
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<dataSource type="POOLED">
<!--配置数据的四个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db4"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件-->
<mappers>
<mapper resource="com/kejizhentan/dao/IUserDao.xml"/>
</mappers>
</configuration>
⑷ 创建映射配置文件
IUserDao.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.kejizhentan.dao.IUserDao">
<!--配置表的列名和实体的属性名的对应关系-->
<resultMap id="userMap" type="com.kejizhentan.bean.User">
<!--主键字段的对应-->
<id property="userId" column="id"></id>
<!--非主键字段的对应-->
<result property="userName" column="username"></result>
<result property="userAddress" column="address"></result>
<result property="userSex" column="sex"></result>
<result property="userBirthday" column="birthday"></result>
</resultMap>
<!--配置查询所有-->
<select id = "findAll" resultMap="userMap">
<!--select id as userId, username as userName, birthday as userBirthday, sex as userSex, address as userAddress from user-->
select * from user
</select>
<!-- 保存用户 -->
<insert id="saveUser" parameterType="com.kejizhentan.bean.User">
<!--配置插入操作后,获取插入数据的id-->
<selectKey keyProperty="userId" keyColumn="id" resultType="int" order="AFTER">
select last_insert_id()
</selectKey>
insert into user(username,address,sex,birthday)values(#{userName},#{userAddress},#{userSex},#{userBirthday})
<!--insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday})-->
</insert>
<!--OGNL的介绍通过QueryVo查询user-->
<select id="findUserByQueryVo" parameterType="com.kejizhentan.bean.QueryVo" resultMap="userMap">
select * from user where id = #{user.userId}
</select>
</mapper>
⑸ 测试类:
MybatisTest.java
public class MybatisTest {
private InputStream is;
private SqlSession sqlSession;
private IUserDao userDao;
@Before//用于在执行方法执行之前执行
public void init(){
try {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
//3.使用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
userDao = sqlSession.getMapper(IUserDao.class);
}catch (Exception e){
e.printStackTrace();
}
}
@After//用于在测试方法执行之后执行
public void close(){
//提交事务
sqlSession.commit();
//6.释放资源
if(sqlSession != null){
sqlSession.close();
}
try {
if(is != null){
is.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
@Test
public void findAll(){
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}
@Test
public void saveUser(){
//实例化对象
User user = new User();
user.setUserName("朝阳区人民");
user.setUserAddress("朝阳区");
user.setUserBirthday(new Date());
user.setUserSex("男");
System.out.println("保存之前的user"+user);
//6.使用代理对象执行方法
userDao.saveUser(user);
System.out.println("保存之后的user"+user);
}
@Test
public void findUserByQueryVo(){
QueryVo queryVo = new QueryVo();
User user = new User();
user.setUserId(41);
queryVo.setUser(user);
User u = userDao.findUserByQueryVo(queryVo);
System.out.println(u);
}
}
八、 Mybatis使用代理对象执行sq的底层流程
九、 properties标签的使用细节
可以在标签内部配置连接数据库的信息,也可以通过属性引用外部配置文件信息 resource属性:常用的方式 ??用于指定配置文件的位置,是按照类路径的写法来写的,并且必须存在于类路径下 url属性: ?它要求按照URL的写法来写地址 ?URL:Uniform?Resouece?Locator 统一资源定位符。它可以唯一标识一个资源的位置。 ????URI:Uniform?Resource?Identifier 统一资源标识符,它是应用中可以唯一定位一个资源的。
配置方式一:该方式太蠢,一般没人用,了解即可
配置方式二:通过resource属性配置(该方式比较常用) 配置方式三:通过url属性配置
注意: 文件使用URL定位的方式:
properties标签的使用细节详细代码: 项目结构:
⑴ 创建maven工程并导入坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kejizhentan</groupId>
<artifactId>mybatis-easy</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--Mybatis框架的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql数据库驱动的依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--生成日志文件的依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--junit单元测试的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
⑵ 创建实体类和dao的接口
User.java
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
IUserDao.java
public interface IUserDao {
List<User> findAll();
}
⑶ 创建Mybatis的主配置文件
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">
<!--Mybatis的主配置文件-->
<configuration>
<!-- 配置properties
可以在标签内部配置连接数据库的信息。也可以通过属性引用外部配置文件信息
resource属性: 常用的
用于指定配置文件的位置,是按照类路径的写法来写,并且必须存在于类路径下。
url属性:
是要求按照Url的写法来写地址
URL:Uniform Resource Locator 统一资源定位符。它是可以唯一标识一个资源的位置。
它的写法:
http://localhost:8080/mybatisserver/demo1Servlet
协议 主机 端口 URI
URI:Uniform Resource Identifier 统一资源标识符。它是在应用中可以唯一定位一个资源的。
-->
<!-- <properties resource="jdbcConfig.properties">-->
<properties url="file:///C:/Users/Administrator/Desktop/jdbcConfig.properties">
<!-- <property name="driver" value="com.mysql.jdbc.Driver"/>-->
<!-- <property name="url" value="jdbc:mysql://localhost:3306/db4"/>-->
<!-- <property name="username" value="root"/>-->
<!-- <property name="password" value="root"/>-->
</properties>
<!--配置环境-->
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<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>
<!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件-->
<mappers>
<mapper resource="com/kejizhentan/dao/IUserDao.xml"/>
</mappers>
</configuration>
jdbcConfig.properties配置文件:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db4
jdbc.username=root
jdbc.password=root
⑷ 创建映射配置文件
IUserDao.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.kejizhentan.dao.IUserDao">
<!--配置查询所有-->
<select id = "findAll" resultType="com.kejizhentan.bean.User">
select * from user
</select>
</mapper>
⑸ 测试类:
MybatisTest.java
public class MybatisTest {
@Test
public void test1(){
InputStream is = null;
SqlSession sqlSession = null;
try {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
//3.使用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}catch (Exception e){
e.printStackTrace();
}finally {
//6.释放资源
if(sqlSession != null){
sqlSession.close();
}
try {
if(is != null){
is.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
执行结果如下:
十、typeAliases标签和package标签
1. typeAliases标签和package标签配置别名
⑴ typeAliases标签配置别名
⑵ typeAliases标签+package标签配置别名
2. 使用package标签指定dao接口所在包
typeAliases标签和package标签使用详细代码
项目结构:
⑴ 创建maven工程并导入坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kejizhentan</groupId>
<artifactId>mybatis-easy</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--Mybatis框架的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql数据库驱动的依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--生成日志文件的依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--junit单元测试的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
⑵ 创建实体类和dao的接口
User.java
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
IUserDao.java
public interface IUserDao {
List<User> findAll();
}
⑶ 创建Mybatis的主配置文件
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">
<!--Mybatis的主配置文件-->
<configuration>
<!--使用typeAliases配置别名,它只能配置bean中实体类的别名-->
<typeAliases>
<!--typeAlias用于配置别名,type属性指定的是实体全限定类名,alias属性指定别名,当制定了别名就不再区分大小写了-->
<!--<typeAlias type="com.kejizhentan.bean.User" alias="user"></typeAlias>-->
<!--用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写-->
<package name="com.kejizhentan.bean"/>
</typeAliases>
<!--配置环境-->
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<dataSource type="POOLED">
<!--配置数据的四个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db4"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--
使用配置文件来实现mybatis的配置:
指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
使用注解来实现mybatis的配置:
如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
-->
<mappers>
<!--<mapper resource="com/kejizhentan/dao/IUserDao.xml"/>-->
<!--<mapper class="com.kejizhentan.dao.IUserDao"/>-->
<!--package标签是用于指定dao接口所在包,当指定之后就不需要再写mapper标签以及resource或者class了-->
<package name="com.kejizhentan.dao"/>
</mappers>
</configuration>
⑷ 创建映射配置文件
IUserDao.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.kejizhentan.dao.IUserDao">
<!--配置查询所有-->
<select id = "findAll" resultType="UseR">
select * from user
</select>
</mapper>
⑸ 测试类:
MybatisTest.java
public class MybatisTest {
@Test
public void test1(){
InputStream is = null;
SqlSession sqlSession = null;
try {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
//3.使用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}catch (Exception e){
e.printStackTrace();
}finally {
//6.释放资源
if(sqlSession != null){
sqlSession.close();
}
try {
if(is != null){
is.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
执行结果如下:
十一、Mybatis中的连接池
1. 连接池:
我们在实际开发中都会使用连接池。因为它可以减少我们获取连接所消耗的时间。
2. mybatis中的连接池
⑴ mybatis连接池提供了3种方式的配置:
- 配置的位置:
主配置文件SqlMapConfig.xml中的dataSource标签,type属性就是表示采用何种连接池方式。 - type属性的取值:
POOLED: 采用传统的javax.sql.DataSource 规范中的连接池,mybatis中有针对规范的实现 UNPOOLED: 采用传统的获取连接的方式,虽然也实现Javax.sql.DataSource 接口,但是并没有使用池的思想。 JNDI: 采用服务器提供的JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到DataSource是不一样。注意:如果不是web或者maven的war工程,是不能使用的。(用于了解,不做过多的解释)
⑵ POOLED和UNPOOLED的比较
十二、Mybatis中自动提交设置
十三、Mybatis中动态sql的使用
1. if 标签的使用
2. if和where标签组合使用(此时可以省略where1=1的条件)
3. foreach遍历查询条件
Mybatis中动态sql的使用详细代码
项目结构
⑴ 创建maven工程并导入坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kejizhentan</groupId>
<artifactId>mybatis-project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--Mybatis框架的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql数据库驱动的依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--生成日志文件的依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--junit单元测试的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
⑵ 创建实体类和dao的接口
User.java
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
IUserDao.java
public interface IUserDao {
List<User> findAll();
User findById(Integer userId);
List<User> findByName(String username);
User findUserByQueryVo(QueryVo queryVo);
List<User> findUserByCondition(User user);
List<User> findUserByIds(@Param("ids") List<Integer> ids);
}
⑶ 创建Mybatis的主配置文件
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">
<!--Mybatis的主配置文件-->
<configuration>
<!--配置环境-->
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<dataSource type="POOLED">
<!--配置数据的四个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db4"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--
使用配置文件来实现mybatis的配置:
指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
使用注解来实现mybatis的配置:
如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
-->
<mappers>
<mapper resource="com/kejizhentan/dao/IUserDao.xml"/>
<!--<mapper class="com.kejizhentan.dao.IUserDao"/>-->
</mappers>
</configuration>
⑷ 创建映射配置文件
IUserDao.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.kejizhentan.dao.IUserDao">
<!--配置查询所有-->
<select id = "findAll" resultType="com.kejizhentan.bean.User">
select * from user
</select>
<!-- 根据id查询用户 -->
<select id="findById" parameterType="int" resultType="com.kejizhentan.bean.User">
select * from user where id = #{uid}
</select>
<!-- 根据名称模糊查询 -->
<select id="findByName" parameterType="string" resultType="com.kejizhentan.bean.User">
select * from user where username like #{name}
<!--select * from user where username like '%${value}%'-->
<!--select * from user where username like concat('%',#{name},'%')-->
</select>
<!--OGNL的介绍通过QueryVo查询user-->
<select id="findUserByQueryVo" parameterType="com.kejizhentan.bean.QueryVo" resultType="com.kejizhentan.bean.User">
select * from user where id = #{user.userId}
</select>
<!-- 根据传入的参数条件来查询(查询条件不确定) -->
<select id="findUserByCondition" parameterType="com.kejizhentan.bean.User" resultType="com.kejizhentan.bean.User">
select * from user
<where>
<if test="username != null and username != '' ">
and username = #{username}
</if>
</where>
</select>
<!--根据id集合,查询用户信息-->
<select id="findUserByIds" parameterType="java.util.List" resultType="com.kejizhentan.bean.User">
select * from user
<where>
<if test="ids != null and ids.size() > 0">
<foreach collection="ids" open="and id in (" close=")" item="uid" separator=",">
#{uid}
</foreach>
</if>
</where>
</select>
</mapper>
⑸ 测试类:
MybatisTest.java
public class MybatisTest {
private InputStream is;
private SqlSession sqlSession;
private IUserDao userDao;
@Before//用于在执行方法执行之前执行
public void init(){
try {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
//3.使用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
userDao = sqlSession.getMapper(IUserDao.class);
}catch (Exception e){
e.printStackTrace();
}
}
@After//用于在测试方法执行之后执行
public void close(){
//提交事务
sqlSession.commit();
//6.释放资源
if(sqlSession != null){
sqlSession.close();
}
try {
if(is != null){
is.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
@Test
public void findAll(){
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}
@Test
public void findById(){
User user = userDao.findById(45);
System.out.println(user);
}
@Test
public void findByName(){
List<User> users = userDao.findByName("%王%");
//List<User> users = userDao.findByName("王");
for (User user : users) {
System.out.println(user);
}
}
@Test
public void findUserByCondition(){
User user = new User();
user.setUsername("老王");
List<User> users = userDao.findUserByCondition(user);
//List<User> users = userDao.findByName("王");
for (User u : users) {
System.out.println(u);
}
}
@Test
public void findUserByIds(){
List<Integer> ids = new ArrayList();
Collections.addAll(ids, 41, 42, 43);
List<User> users = userDao.findUserByIds(ids);
for (User u : users) {
System.out.println(u);
}
}
}
补充:重复的sql可以抽取出来
十四、多表查询的操作
增加一张账户表的sql DROP TABLE IF EXISTS account ; CREATE TABLE account ( ID int(11) NOT NULL COMMENT ‘编号’, UID int(11) default NULL COMMENT ‘用户编号’, MONEY double default NULL COMMENT ‘金额’, PRIMARY KEY (ID ), KEY FK_Reference_8 (UID ), CONSTRAINT FK_Reference_8 FOREIGN KEY (UID ) REFERENCES user (id ) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into account (ID ,UID ,MONEY ) values (1,46,1000),(2,45,1000),(3,46,2000);
1. 一对一的多表查询操作
⑴ 主要配置
<!--定义封装account和user的resultMap-->
<resultMap id="accountUserMap" type="com.kejizhentan.bean.Account">
<id property="id" column="aid"></id>
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
<!--一对一的关系映射,配置封装user的内容-->
<association property="user" column="uid" javaType="com.kejizhentan.bean.User">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="address" column="address"></result>
<result property="sex" column="sex"></result>
<result property="birthday" column="birthday"></result>
</association>
</resultMap>
<!--配置查询所有-->
<select id = "findAll" resultMap="accountUserMap">
SELECT
u.*,
a.id AS aid,
a.uid,
a.money
FROM account a LEFT JOIN USER u ON a.UID = u.id
</select>
public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
//从表实体应该包含一个主表实体的对象引用
private User user;
...
}
⑵ 详细代码
项目结构
⑴ 创建maven工程并导入坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kejizhentan</groupId>
<artifactId>mybatis-project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--Mybatis框架的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql数据库驱动的依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--生成日志文件的依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--junit单元测试的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
⑵ 创建实体类和dao的接口
User.java
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
Account.java
public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
//从表实体应该包含一个主表实体的对象引用
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", uid=" + uid +
", money=" + money +
'}';
}
}
IAccountDao.java
public interface IAccountDao {
List<Account> findAll();
⑶ 创建Mybatis的主配置文件
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">
<!--Mybatis的主配置文件-->
<configuration>
<!--配置环境-->
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<dataSource type="POOLED">
<!--配置数据的四个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db4"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--
使用配置文件来实现mybatis的配置:
指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
使用注解来实现mybatis的配置:
如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
-->
<mappers>
<mapper resource="com/kejizhentan/dao/IAccountDao.xml"/>
<!--<mapper class="com.kejizhentan.dao.IUserDao"/>-->
</mappers>
</configuration
⑷ 创建映射配置文件
IAccountDao.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.kejizhentan.dao.IAccountDao">
<!--定义封装account和user的resultMap-->
<resultMap id="accountUserMap" type="com.kejizhentan.bean.Account">
<id property="id" column="aid"></id>
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
<!--一对一的关系映射,配置封装user的内容-->
<association property="user" column="uid" javaType="com.kejizhentan.bean.User">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="address" column="address"></result>
<result property="sex" column="sex"></result>
<result property="birthday" column="birthday"></result>
</association>
</resultMap>
<!--配置查询所有-->
<select id = "findAll" resultMap="accountUserMap">
SELECT
u.*,
a.id AS aid,
a.uid,
a.money
FROM account a LEFT JOIN USER u ON a.UID = u.id
</select>
</mapper>
⑸ 测试类:
MybatisTest.java
public class MybatisTest {
private InputStream is;
private SqlSession sqlSession;
private IAccountDao accountDao;
@Before//用于在执行方法执行之前执行
public void init(){
try {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
//3.使用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
accountDao = sqlSession.getMapper(IAccountDao.class);
}catch (Exception e){
e.printStackTrace();
}
}
@After//用于在测试方法执行之后执行
public void close(){
//提交事务
sqlSession.commit();
//6.释放资源
if(sqlSession != null){
sqlSession.close();
}
try {
if(is != null){
is.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
@Test
public void findAll(){
//5.使用代理对象执行方法
List<Account> accounts = accountDao.findAll();
for (Account account : accounts) {
System.out.println("----------------打印account信息--------------");
System.out.println(account);
System.out.println(account.getUser());
}
}
}
⑹ 结果如下:
注意:
2. 一对多的多表查询操作
⑴ 主要配置
⑵ 详细代码
项目结构:
⑴ 创建maven工程并导入坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kejizhentan</groupId>
<artifactId>mybatis-project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--Mybatis框架的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql数据库驱动的依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--生成日志文件的依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--junit单元测试的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
⑵ 创建实体类和dao的接口
User.java
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
//一对多关系映射,主表实体应该包含从表实体的集合引用
private List<Account> accounts;
public List<Account> getAccounts() {
return accounts;
}
public void setAccounts(List<Account> accounts) {
this.accounts = accounts;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
Account.java
public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", uid=" + uid +
", money=" + money +
'}';
}
}
IUserDao.java
public interface IUserDao {
List<User> findAll();
}
⑶ 创建Mybatis的主配置文件
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">
<!--Mybatis的主配置文件-->
<configuration>
<!--配置环境-->
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<dataSource type="POOLED">
<!--配置数据的四个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db4"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--
使用配置文件来实现mybatis的配置:
指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
使用注解来实现mybatis的配置:
如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
-->
<mappers>
<!--<mapper resource="com/kejizhentan/dao/IAccountDao.xml"/>-->
<!--<mapper class="com.kejizhentan.dao.IUserDao"/>-->
<package name="com.kejizhentan.dao"/>
</mappers>
</configuration>
⑷ 创建映射配置文件
IUserDao.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.kejizhentan.dao.IUserDao">
<!-- 定义User的resultMap-->
<resultMap id="userAccountMap" type="com.kejizhentan.bean.User">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="address" column="address"></result>
<result property="sex" column="sex"></result>
<result property="birthday" column="birthday"></result>
<!-- 配置user对象中accounts集合的映射 -->
<collection property="accounts" ofType="com.kejizhentan.bean.Account">
<id column="aid" property="id"></id>
<result column="uid" property="uid"></result>
<result column="money" property="money"></result>
</collection>
</resultMap>
<!--配置查询所有-->
<select id = "findAll" resultMap="userAccountMap">
select * from user u left join account a on u.id = a.uid
</select>
</mapper>
⑸ 测试类:
MybatisTest.java
public class MybatisTest {
private InputStream is;
private SqlSession sqlSession;
private IUserDao userDao;
@Before//用于在执行方法执行之前执行
public void init(){
try {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
//3.使用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
userDao = sqlSession.getMapper(IUserDao.class);
}catch (Exception e){
e.printStackTrace();
}
}
@After//用于在测试方法执行之后执行
public void close(){
//提交事务
sqlSession.commit();
//6.释放资源
if(sqlSession != null){
sqlSession.close();
}
try {
if(is != null){
is.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
@Test
public void findAll(){
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println("----------------打印account信息--------------");
System.out.println(user);
System.out.println(user.getAccounts());
}
}
}
⑹ 结果如下:
3. 多对多的多表查询操作
增加两张表 DROP TABLE IF EXISTS role ;
CREATE TABLE role ( ID int(11) NOT NULL COMMENT ‘编号’, ROLE_NAME varchar(30) default NULL COMMENT ‘角色名称’, ROLE_DESC varchar(60) default NULL COMMENT ‘角色描述’, PRIMARY KEY (ID ) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into role (ID ,ROLE_NAME ,ROLE_DESC ) values (1,‘院长’,‘管理整个学院’),(2,‘总裁’,‘管理整个公司’),(3,‘校长’,‘管理整个学校’); DROP TABLE IF EXISTS user_role ; CREATE TABLE user_role ( UID int(11) NOT NULL COMMENT ‘用户编号’, RID int(11) NOT NULL COMMENT ‘角色编号’, PRIMARY KEY (UID ,RID ), KEY FK_Reference_10 (RID ), CONSTRAINT FK_Reference_10 FOREIGN KEY (RID ) REFERENCES role (ID ), CONSTRAINT FK_Reference_9 FOREIGN KEY (UID ) REFERENCES user (id ) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into user_role (UID ,RID ) values (41,1),(45,1),(41,2);
⑴ 主要配置
public class Role implements Serializable {
private Integer roleId;
private String roleName;
private String roleDesc;
//多对多的关系映射:一个角色可以赋予多个用户
private List<User> users;
. . .
}
<?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.kejizhentan.dao.IRoleDao">
<!--定义role表的ResultMap-->
<resultMap id="roleMap" type="com.kejizhentan.bean.Role">
<id property="roleId" column="rid"></id>
<result property="roleName" column="role_name"></result>
<result property="roleDesc" column="role_desc"></result>
<collection property="users" ofType="com.kejizhentan.bean.User">
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="address" property="address"></result>
<result column="sex" property="sex"></result>
<result column="birthday" property="birthday"></result>
</collection>
</resultMap>
<!--查询所有-->
<select id="findAll" resultMap="roleMap">
select u.*,r.id as rid,r.role_name,r.role_desc from role r
left outer join user_role ur on r.id = ur.rid
left outer join user u on u.id = ur.uid
</select>
</mapper>
⑵ 详细代码
项目结构:
⑴ 创建maven工程并导入坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kejizhentan</groupId>
<artifactId>mybatis-project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--Mybatis框架的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql数据库驱动的依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--生成日志文件的依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--junit单元测试的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
⑵ 创建实体类和dao的接口
User.java
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
Role.java
public class Role implements Serializable {
private Integer roleId;
private String roleName;
private String roleDesc;
//多对多的关系映射:一个角色可以赋予多个用户
private List<User> users;
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
public Integer getRoleId() {
return roleId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getRoleDesc() {
return roleDesc;
}
public void setRoleDesc(String roleDesc) {
this.roleDesc = roleDesc;
}
@Override
public String toString() {
return "Role{" +
"roleId=" + roleId +
", roleName='" + roleName + '\'' +
", roleDesc='" + roleDesc + '\'' +
'}';
}
}
IRoleDao.java
public interface IRoleDao {
List<Role> findAll();
}
⑶ 创建Mybatis的主配置文件
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">
<!--Mybatis的主配置文件-->
<configuration>
<!--配置环境-->
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<dataSource type="POOLED">
<!--配置数据的四个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db4"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--
使用配置文件来实现mybatis的配置:
指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
使用注解来实现mybatis的配置:
如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
-->
<mappers>
<!--<mapper resource="com/kejizhentan/dao/IAccountDao.xml"/>-->
<!--<mapper class="com.kejizhentan.dao.IUserDao"/>-->
<package name="com.kejizhentan.dao"/>
</mappers>
</configuration>
⑷ 创建映射配置文件
IRoleDao.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.kejizhentan.dao.IRoleDao">
<!--定义role表的ResultMap-->
<resultMap id="roleMap" type="com.kejizhentan.bean.Role">
<id property="roleId" column="rid"></id>
<result property="roleName" column="role_name"></result>
<result property="roleDesc" column="role_desc"></result>
<collection property="users" ofType="com.kejizhentan.bean.User">
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="address" property="address"></result>
<result column="sex" property="sex"></result>
<result column="birthday" property="birthday"></result>
</collection>
</resultMap>
<!--查询所有-->
<select id="findAll" resultMap="roleMap">
select u.*,r.id as rid,r.role_name,r.role_desc from role r
left outer join user_role ur on r.id = ur.rid
left outer join user u on u.id = ur.uid
</select>
</mapper>
⑸ 测试类:
MybatisTest.java
public class MybatisTest {
private InputStream is;
private SqlSession sqlSession;
private IRoleDao roleDao;
@Before//用于在执行方法执行之前执行
public void init(){
try {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
//3.使用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
roleDao = sqlSession.getMapper(IRoleDao.class);
}catch (Exception e){
e.printStackTrace();
}
}
@After//用于在测试方法执行之后执行
public void close(){
//提交事务
sqlSession.commit();
//6.释放资源
if(sqlSession != null){
sqlSession.close();
}
try {
if(is != null){
is.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
@Test
public void findAll(){
//5.使用代理对象执行方法
List<Role> roles = roleDao.findAll();
for (Role role : roles) {
System.out.println("----------------打印role信息--------------");
System.out.println(role);
System.out.println(role.getUsers());
}
}
}
⑹ 结果如下:
十五、 Mybatis中的延迟加载
1. 什么是延迟加载
在真正使用数据时才发起查询,不用的时候不查询。按需加载(懒加载)
2. 什么是立即加载
不管用不用,只要一调用方法,马上发起查询。
3. 在对应的四种表关系中:
一对多,多对多:通常情况下我们都是采用延迟加载。 多对一,一对一:通常情况下我们都是采用立即加载。
4.延迟加载场景演示
⑴ 一对一多表查询懒加载演示
① 主要配置
-
IAccountDao.xml中的配置 <resultMap id="accountUserMap" type="com.kejizhentan.bean.Account">
. . .
<association property="user" column="uid" javaType="com.kejizhentan.bean.User" select="com.kejizhentan.dao.IUserDao.findById"></association>
</resultMap>
-
SqlMapConfig.xml中的配置 <!--配置参数-->
<settings>
<!--开启Mybatis支持延迟加载的开关-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--将积极加载改为按需加载 mybatis3.4.1以后默认是false的,可以不用设置-->
<setting name="aggressiveLazyLoading" value="false"></setting>
</settings>
② 详细代码
-
项目结构 -
创建maven工程并导入坐标 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kejizhentan</groupId>
<artifactId>mybatis-project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--Mybatis框架的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql数据库驱动的依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--生成日志文件的依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--junit单元测试的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
-
创建实体类和dao的接口 User.java public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
Account.java public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
public Integer getId() {
return id;
}
//一对多关系映射,主表实体应该包含子表实体的集合
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", uid=" + uid +
", money=" + money +
'}';
}
}
IUserDao.java public interface IUserDao {
User findById(Integer id);
}
IAccountDao.java public interface IAccountDao {
List<Account> findAll();
}
-
创建Mybatis的主配置文件 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">
<!--Mybatis的主配置文件-->
<configuration>
<!--延迟加载参数配置-->
<!--配置参数-->
<settings>
<!--开启Mybatis支持延迟加载的开关-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--将积极加载改为按需加载 mybatis3.4.1以后默认是开启的,可以不用设置-->
<setting name="aggressiveLazyLoading" value="false"></setting>
</settings>
<!--配置环境-->
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<dataSource type="POOLED">
<!--配置数据的四个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db4"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--
使用配置文件来实现mybatis的配置:
指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
使用注解来实现mybatis的配置:
如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
-->
<mappers>
<!--<mapper resource="com/kejizhentan/dao/IAccountDao.xml"/>-->
<!--<mapper class="com.kejizhentan.dao.IUserDao"/>-->
<package name="com.kejizhentan.dao"/>
</mappers>
</configuration>
-
创建映射配置文件 IUserDao.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.kejizhentan.dao.IUserDao">
<select id = "findById" parameterType="java.lang.Integer" resultType="com.kejizhentan.bean.User">
select * from user u where id = #{id}
</select>
</mapper>
IAccountDao.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.kejizhentan.dao.IAccountDao">
<!--定义封装account和user的resultMap-->
<resultMap id="accountUserMap" type="com.kejizhentan.bean.Account">
<id property="id" column="aid"></id>
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
<!--一对一的关系映射,配置封装user的内容
select属性指定的内容,查询用户的唯一标识
column属性指定的内容:用户根据id查询时,所需要的参数值
-->
<association property="user" column="uid" javaType="com.kejizhentan.bean.User" select="com.kejizhentan.dao.IUserDao.findById"></association>
</resultMap>
<!--配置查询所有-->
<select id = "findAll" resultMap="accountUserMap">
SELECT
*
FROM account a
</select>
</mapper>
-
测试类: MybatisTest.java public class MybatisTest {
private InputStream is;
private SqlSession sqlSession;
private IAccountDao accountDao;
@Before//用于在执行方法执行之前执行
public void init() {
try {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
//3.使用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
accountDao = sqlSession.getMapper(IAccountDao.class);
} catch (Exception e) {
e.printStackTrace();
}
}
@After//用于在测试方法执行之后执行
public void close() {
//提交事务
sqlSession.commit();
//6.释放资源
if (sqlSession != null) {
sqlSession.close();
}
try {
if (is != null) {
is.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void findAll() {
//5.使用代理对象执行方法
List<Account> accounts = accountDao.findAll();
for (Account account : accounts) {
System.out.println("----------------打印account信息--------------");
System.out.println(account);
System.out.println(account.getUser());
}
}
}
-
结果如下:
注意:一对一普通查询和懒加载查询sql对比 普通查询 懒加载
⑵ 一对多查询懒加载演示
① 主要配置
-
IUserDao.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.kejizhentan.dao.IUserDao">
<!-- 定义User的resultMap-->
<resultMap id="userAccountMap" type="com.kejizhentan.bean.User">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="address" column="address"></result>
<result property="sex" column="sex"></result>
<result property="birthday" column="birthday"></result>
<!-- 配置user对象中accounts集合的映射,注意,这地方的column应该是id,应为使用的是用户的id -->
<collection property="accounts" ofType="com.kejizhentan.bean.Account" select="com.kejizhentan.dao.IUserDao.findByUId" column="id"></collection>
</resultMap>
<select id = "findAll" resultMap="userAccountMap">
select * from user u
</select>
<!--根据用户id查询账户信息-->
<select id = "findByUId" resultType="com.kejizhentan.bean.Account">
select * from account a where a.uid = #{uid}
</select>
</mapper>
-
SqlMapConfig.xml中的配置 <!--配置参数-->
<settings>
<!--开启Mybatis支持延迟加载的开关-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--将积极加载改为按需加载 mybatis3.4.1以后默认是false的,可以不用设置-->
<setting name="aggressiveLazyLoading" value="false"></setting>
</settings>
② 详细代码
-
项目结构 -
创建maven工程并导入坐标 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kejizhentan</groupId>
<artifactId>mybatis-project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--Mybatis框架的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql数据库驱动的依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--生成日志文件的依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--junit单元测试的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
-
创建实体类和dao的接口 User.java public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
//一对多关系映射,主表实体应该包含从表实体的集合引用
private List<Account> accounts;
public List<Account> getAccounts() {
return accounts;
}
public void setAccounts(List<Account> accounts) {
this.accounts = accounts;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
Account.java public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", uid=" + uid +
", money=" + money +
'}';
}
}
IUserDao.java public interface IUserDao {
List<User> findAll();
List<Account> findByUId(Integer uid);
}
-
创建Mybatis的主配置文件 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">
<!--Mybatis的主配置文件-->
<configuration>
<!--延迟加载参数配置-->
<!--配置参数-->
<settings>
<!--开启Mybatis支持延迟加载的开关-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--将积极加载改为按需加载 mybatis3.4.1以后默认是开启的,可以不用设置-->
<setting name="aggressiveLazyLoading" value="false"></setting>
</settings>
<!--配置环境-->
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<dataSource type="POOLED">
<!--配置数据的四个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db4"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--
使用配置文件来实现mybatis的配置:
指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
使用注解来实现mybatis的配置:
如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
-->
<mappers>
<!--<mapper resource="com/kejizhentan/dao/IAccountDao.xml"/>-->
<!--<mapper class="com.kejizhentan.dao.IUserDao"/>-->
<package name="com.kejizhentan.dao"/>
</mappers>
</configuration>
-
创建映射配置文件 IUserDao.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.kejizhentan.dao.IUserDao">
<!-- 定义User的resultMap-->
<resultMap id="userAccountMap" type="com.kejizhentan.bean.User">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="address" column="address"></result>
<result property="sex" column="sex"></result>
<result property="birthday" column="birthday"></result>
<!-- 配置user对象中accounts集合的映射,注意,这地方的column应该是id,应为使用的是用户的id -->
<collection property="accounts" ofType="com.kejizhentan.bean.Account" select="com.kejizhentan.dao.IUserDao.findByUId" column="id"></collection>
</resultMap>
<select id = "findAll" resultMap="userAccountMap">
select * from user u
</select>
<!--根据用户id查询账户信息-->
<select id = "findByUId" resultType="com.kejizhentan.bean.Account">
select * from account a where a.uid = #{uid}
</select>
</mapper>
-
测试类: MybatisTest.java public class MybatisTest {
private InputStream is;
private SqlSession sqlSession;
private IUserDao userDao;
@Before//用于在执行方法执行之前执行
public void init() {
try {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
//3.使用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
userDao = sqlSession.getMapper(IUserDao.class);
} catch (Exception e) {
e.printStackTrace();
}
}
@After//用于在测试方法执行之后执行
public void close() {
//提交事务
sqlSession.commit();
//6.释放资源
if (sqlSession != null) {
sqlSession.close();
}
try {
if (is != null) {
is.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void findAll() {
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
System.out.println(user.getAccounts());
}
}
}
-
结果如下:
十六、Mybatis中的缓存
1. 什么是缓存
存在于内存中的临时数据。
2. 为什么使用缓存
减少和数据库的交互次数,提高执行效率。
3. 什么样的数据能使用缓存,什么样的数据不能使用
- 适用于缓存:
经常查询并且不经常改变的。 数据的正确与否对最终结果影响不大的。 - 不适用于缓存:
经常改变的数据 数据的正确与否对最终结果影响很大的。 例如:商品的库存,银行的汇率,股市的牌价。
4. Mybatis中的一级缓存和二级缓存
⑴ 一级缓存:
它指的是Mybatis中SqlSession对象的缓存。当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供一块区域中。该区域的结构是一个Map。当我们再次查询同样的数据,mybatis会先去sqlsession中查询是否有,有的话直接拿出来用。当SqlSession对象消失时,mybatis的一级缓存也就消失了。
① 一级缓存的使用
- mybatis一级缓存默认是开启的。
- mybatis一级缓存失效的方式有两种
方式一:关闭sqlSession 方式二:使用clearCache方法清理缓存
详细代码
-
项目结构 -
创建maven工程并导入坐标 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kejizhentan</groupId>
<artifactId>mybatis-project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--Mybatis框架的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql数据库驱动的依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--生成日志文件的依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--junit单元测试的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
-
创建实体类和dao的接口 User.java public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
IUserDao.java public interface IUserDao {
User findById(Integer id);
}
-
创建Mybatis的主配置文件 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">
<!--Mybatis的主配置文件-->
<configuration>
<!--配置环境-->
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<dataSource type="POOLED">
<!--配置数据的四个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db4"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--
使用配置文件来实现mybatis的配置:
指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
使用注解来实现mybatis的配置:
如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
-->
<mappers>
<!--<mapper resource="com/kejizhentan/dao/IAccountDao.xml"/>-->
<!--<mapper class="com.kejizhentan.dao.IUserDao"/>-->
<package name="com.kejizhentan.dao"/>
</mappers>
</configuration>
-
创建映射配置文件 IUserDao.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.kejizhentan.dao.IUserDao">
<select id = "findById" resultType="com.kejizhentan.bean.User">
select * from user u where u.id = #{id}
</select>
</mapper>
-
测试类: MybatisTest.java public class MybatisTest {
private InputStream is;
private SqlSession sqlSession;
private IUserDao userDao;
private SqlSessionFactory factory;
@Before//用于在执行方法执行之前执行
public void init() {
try {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
factory = builder.build(is);
//3.使用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
userDao = sqlSession.getMapper(IUserDao.class);
} catch (Exception e) {
e.printStackTrace();
}
}
@After//用于在测试方法执行之后执行
public void close() {
//提交事务
sqlSession.commit();
//6.释放资源
if (sqlSession != null) {
sqlSession.close();
}
try {
if (is != null) {
is.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void findAll() {
System.out.println("演示一级缓存");
User user1 = userDao.findById(41);
System.out.println(user1);
User user2 = userDao.findById(41);
System.out.println(user2);
System.out.println(user1 == user2);
//演示一级缓存失效的情况
System.out.println("演示一级缓存失效的情况");
User user3 = userDao.findById(42);
System.out.println(user3);
//使mybatis的一级缓存失效的两种方式:
//方式二:使用clearCache方法清理缓存
sqlSession.clearCache();
User user4 = userDao.findById(42);
System.out.println(user4);
System.out.println(user3 == user4);
}
}
-
结果如下:
我们可以发现,虽然在上面的代码中我们查询了两次,但最后只执行了一次数据库操作,这就是 Mybatis提供给我们的一级缓存在起作用了。因为一级缓存的存在,导致第二次查询 id 为 41 的记录时,并没有发出 sql语句从数据库中查询数据,而是从一级缓存中查询。
② 触发清空一级缓存的情况
一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存。
详细代码
-
项目结构 -
创建maven工程并导入坐标 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kejizhentan</groupId>
<artifactId>mybatis-project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--Mybatis框架的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql数据库驱动的依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--生成日志文件的依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--junit单元测试的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
-
创建实体类和dao的接口 User.java public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
IUserDao.java public interface IUserDao {
User findById(Integer id);
}
void updateUser(User user);
-
创建Mybatis的主配置文件 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">
<!--Mybatis的主配置文件-->
<configuration>
<!--配置环境-->
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<dataSource type="POOLED">
<!--配置数据的四个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db4"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--
使用配置文件来实现mybatis的配置:
指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
使用注解来实现mybatis的配置:
如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
-->
<mappers>
<!--<mapper resource="com/kejizhentan/dao/IAccountDao.xml"/>-->
<!--<mapper class="com.kejizhentan.dao.IUserDao"/>-->
<package name="com.kejizhentan.dao"/>
</mappers>
</configuration>
-
创建映射配置文件 IUserDao.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.kejizhentan.dao.IUserDao">
<select id = "findById" resultType="com.kejizhentan.bean.User">
select * from user u where u.id = #{id}
</select>
<!--更新用户信息-->
<update id="updateUser" parameterType="com.kejizhentan.bean.User">
update user set username = #{username},address = #{address} where id = #{id}
</update>
</mapper>
-
测试类: MybatisTest.java public class MybatisTest {
private InputStream is;
private SqlSession sqlSession;
private IUserDao userDao;
private SqlSessionFactory factory;
@Before//用于在执行方法执行之前执行
public void init() {
try {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
factory = builder.build(is);
//3.使用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
userDao = sqlSession.getMapper(IUserDao.class);
} catch (Exception e) {
e.printStackTrace();
}
}
@After//用于在测试方法执行之后执行
public void close() {
//提交事务
sqlSession.commit();
//6.释放资源
if (sqlSession != null) {
sqlSession.close();
}
try {
if (is != null) {
is.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void findAll() {
System.out.println("演示一级缓存");
User user1 = userDao.findById(41);
System.out.println(user1);
user1.setUsername("触发清空一级缓存");
user1.setAddress("北京市海淀区");
//更新用户信息
userDao.updateUser(user1);
//再次查询41的用户信息
User user2 = userDao.findById(41);
System.out.println(user2);
System.out.println(user1 == user2);
}
}
-
结果如下:
⑵ 二级缓存:
它指的是Mybatis中SqlSessionFactory对象的缓存。由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。
二级缓存的使用步骤: 第一步:让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置) 第二步:让当前的映射文件支持二级缓存(在IUserDao.xml中配置) 第三步:让当前的操作支持二级缓存(在select标签中配置)
详细代码
-
项目结构 -
创建maven工程并导入坐标 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kejizhentan</groupId>
<artifactId>mybatis-project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--Mybatis框架的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql数据库驱动的依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--生成日志文件的依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--junit单元测试的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
-
创建实体类和dao的接口 User.java public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
IUserDao.java public interface IUserDao {
User findById(Integer id);
}
-
创建Mybatis的主配置文件 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">
<!--Mybatis的主配置文件-->
<configuration>
<!--让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)-->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
<!--配置环境-->
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<dataSource type="POOLED">
<!--配置数据的四个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db4"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--
使用配置文件来实现mybatis的配置:
指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
使用注解来实现mybatis的配置:
如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
-->
<mappers>
<!--<mapper resource="com/kejizhentan/dao/IAccountDao.xml"/>-->
<!--<mapper class="com.kejizhentan.dao.IUserDao"/>-->
<package name="com.kejizhentan.dao"/>
</mappers>
</configuration>
-
创建映射配置文件 IUserDao.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.kejizhentan.dao.IUserDao">
<!--让当前的映射文件支持二级缓存(在IUserDao.xml中配置)-->
<cache/>
<!--让当前的操作支持二级缓存(在select标签中配置)-->
<select id = "findById" parameterType="int" resultType="com.kejizhentan.bean.User" useCache="true">
select * from user u where u.id = #{id}
</select>
</mapper>
-
测试类: MybatisTest.java public class MybatisTest {
private InputStream is;
private SqlSessionFactory factory;
@Before//用于在执行方法执行之前执行
public void init() {
try {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
factory = builder.build(is);
} catch (Exception e) {
e.printStackTrace();
}
}
@After//用于在测试方法执行之后执行
public void close() {
try {
if (is != null) {
is.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void findAll() {
System.out.println("演示二级缓存");
SqlSession sqlSession1= factory.openSession();
IUserDao userDao1 = sqlSession1.getMapper(IUserDao.class);
User user1 = userDao1.findById(41);
System.out.println(user1);
sqlSession1.close();//一级缓存消失
SqlSession sqlSession2= factory.openSession();
IUserDao userDao2 = sqlSession2.getMapper(IUserDao.class);
User user2 = userDao2.findById(41);
sqlSession2.close();//一级缓存消失
System.out.println(user2);
System.out.println(user1 == user2);
}
}
-
结果如下:
注意: 二级缓存中存储的是数据不是对象,当使用二级缓存中的数据时会创建一个新对象,将缓存中的数据填充到这个新对象中。所以上面两个对象的值不相等。
十七、综合练习(使用注解的方式完成基本的CRUD操作、多表查询和缓存的使用)
1. 使用注解的方式完成基本的CRUD操作
详细代码:
-
项目结构 -
创建maven工程并导入坐标 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kejizhentan</groupId>
<artifactId>mybatis-annotation</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--导入mybatis依赖包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--导入mysql的连接依赖包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--导入日志文件logo4j的依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--导入单元测试的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>
</project>
-
创建实体类和dao的接口 User.java public class User implements Serializable {
private Integer id;
private String username;
private String address;
private String sex;
private Date birthday;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", address='" + address + '\'' +
", sex='" + sex + '\'' +
", birthday=" + birthday +
'}';
}
}
IUserDao.java public interface IUserDao {
//查询所有的用户信息
@Select("select * from user")
List<User> findAll();
@Insert("insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday})")
void saveUser(User user);
@Update("update user set username=#{username},sex=#{sex},birthday=#{birthday},address=#{address} where id=#{id}")
void updateUser(User user);
@Delete("delete from user where id=#{id} ")
void deleteUser(Integer userId);
@Select("select * from user where id=#{id} ")
User findById(Integer userId);
//@Select("select * from user where username like #{username} ")
@Select("select * from user where username like CONCAT('%',#{username},'%') ")
List<User> findUserByName(String username);
@Select("select count(*) from user ")
int findTotalUser();
}
-
创建Mybatis的主配置文件 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-->
<properties resource="jdbcConfig.properties"></properties>
<!--配置别名-->
<typeAliases>
<package name="com.kejizhentan.bean"></package>
</typeAliases>
<!--配置环境-->
<environments default="mysql">
<!-- 配置mysql的环境-->
<environment id="mysql">
<!-- 配置事务 -->
<transactionManager type="JDBC"></transactionManager>
<!--配置连接池-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</dataSource>
</environment>
</environments>
<!-- 配置映射文件的位置 -->
<mappers>
<package name="com.kejizhentan.dao"></package>
</mappers>
</configuration>
-
jdbcConfig.properties jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/kjztdatabase
jdbc.username=root
jdbc.password=123456
-
测试类: MybatisTest.java public class MybatisTest {
private InputStream in;
private SqlSession sqlSession;
private IUserDao userDao;
@Before//用于在测试方法执行之前执行
public void init()throws Exception{
//1.读取配置文件,生成字节输入流
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.获取SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3.获取SqlSession对象
sqlSession = factory.openSession(true);
//4.获取dao的代理对象
userDao = sqlSession.getMapper(IUserDao.class);
}
@After//用于在测试方法执行之后执行
public void destroy()throws Exception{
//提交事务
// sqlSession.commit();
//6.释放资源
sqlSession.close();
in.close();
}
@Test
public void testFindAll(){
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}
@Test
public void testSave(){
User user = new User();
user.setUsername("mybatis annotation");
user.setAddress("北京市昌平区");
userDao.saveUser(user);
}
@Test
public void testUpdate(){
User user = new User();
user.setId(49);
user.setUsername("mybatis annotation update");
user.setAddress("北京市海淀区");
user.setSex("男");
user.setBirthday(new Date());
userDao.updateUser(user);
}
@Test
public void testDelete(){
userDao.deleteUser(49);
}
@Test
public void testFindOne(){
User user = userDao.findById(48);
System.out.println(user);
}
@Test
public void testFindByName(){
// List<User> users = userDao.findUserByName("%mybatis%");
List<User> users = userDao.findUserByName("小二王");
for(User user : users){
System.out.println(user);
}
}
@Test
public void testFindTotal(){
int total = userDao.findTotalUser();
System.out.println(total);
}
}
-
结果如下:
注意: 使用注解开发时,当实体类属性和数据库字段不匹配时,可以使用@Results和@Result注解解决实体字段和数据库的字段不对应的问题:
2. 使用注解的方式完成一对一多表操作
详细代码:
-
项目结构 -
创建maven工程并导入坐标 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kejizhentan</groupId>
<artifactId>mybatis-annotation</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--导入mybatis依赖包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--导入mysql的连接依赖包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--导入日志文件logo4j的依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--导入单元测试的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>
</project>
-
创建实体类和dao的接口 User.java public class User implements Serializable {
private Integer id;
private String username;
private String address;
private String sex;
private Date birthday;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", address='" + address + '\'' +
", sex='" + sex + '\'' +
", birthday=" + birthday +
'}';
}
}
IUserDao.java public interface IUserDao {
@Select("select * from user where id=#{id}")
User findById(Integer userId);
}
Account.java public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
//从表实体应该包含一个主表实体的对象引用
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", uid=" + uid +
", money=" + money +
", user=" + user +
'}';
}
}
IAccountdao.java public interface IAccountDao {
/**
* 查询所有账户,同时还要获取到当前账户的所属用户信息
* @return
*/
/**
* 查询所有账户,并且获取每个账户所属的用户信息
* @return
*/
@Select("select * from account")
@Results({
@Result(id=true,column = "id",property = "id"),
@Result(column = "uid",property = "uid"),
@Result(column = "money",property = "money"),
@Result(property = "user",column = "uid",one=@One(select="com.kejizhentan.dao.IUserDao.findById",fetchType= FetchType.EAGER))
})
List<Account> findAll();
}
-
创建Mybatis的主配置文件 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-->
<properties resource="jdbcConfig.properties"></properties>
<!--配置别名-->
<typeAliases>
<package name="com.kejizhentan.bean"></package>
</typeAliases>
<!--配置环境-->
<environments default="mysql">
<!-- 配置mysql的环境-->
<environment id="mysql">
<!-- 配置事务 -->
<transactionManager type="JDBC"></transactionManager>
<!--配置连接池-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</dataSource>
</environment>
</environments>
<!-- 配置映射文件的位置 -->
<mappers>
<package name="com.kejizhentan.dao"></package>
</mappers>
</configuration>
-
jdbcConfig.properties jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/kjztdatabase
jdbc.username=root
jdbc.password=123456
-
测试类: MybatisTest.java public class MybatisTest {
private InputStream in;
private SqlSession sqlSession;
private IAccountDao accountDao;
@Before//用于在测试方法执行之前执行
public void init()throws Exception{
//1.读取配置文件,生成字节输入流
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.获取SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3.获取SqlSession对象
sqlSession = factory.openSession(true);
//4.获取dao的代理对象
accountDao = sqlSession.getMapper(IAccountDao.class);
}
@After//用于在测试方法执行之后执行
public void destroy()throws Exception{
//提交事务
// sqlSession.commit();
//6.释放资源
sqlSession.close();
in.close();
}
@Test
public void testFindAll(){
List<Account> accounts = accountDao.findAll();
for (Account account : accounts) {
System.out.println(account);
}
}
}
-
结果如下:
3. 使用注解的方式完成一对多的多表操作
详细代码:
-
项目结构 -
创建maven工程并导入坐标 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kejizhentan</groupId>
<artifactId>mybatis-annotation</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--导入mybatis依赖包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--导入mysql的连接依赖包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--导入日志文件logo4j的依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--导入单元测试的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>
</project>
-
创建实体类和dao的接口 User.java public class User implements Serializable {
private Integer id;
private String username;
private String address;
private String sex;
private Date birthday;
private List<Account> accounts;
public List<Account> getAccounts() {
return accounts;
}
public void setAccounts(List<Account> accounts) {
this.accounts = accounts;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", address='" + address + '\'' +
", sex='" + sex + '\'' +
", birthday=" + birthday +
", accounts=" + accounts +
'}';
}
}
IUserDao.java public interface IUserDao {
@Select("select * from user")
@Results({
@Result(id=true,column = "id",property = "id"),
@Result(column = "username",property = "username"),
@Result(column = "address",property = "address"),
@Result(column = "sex",property = "sex"),
@Result(column = "birthday",property = "birthday"), @Result(property = "accounts",column = "id", many = @Many(select = "com.kejizhentan.dao.IAccountDao.findByUid", fetchType = FetchType.LAZY)) }) List<User> findAll();
}
Account.java public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", uid=" + uid +
", money=" + money +
'}';
}
}
IAccountdao.java public interface IAccountDao {
/**
* 根据uid查询账户信息
*/
@Select("select * from account where uid = #{uid}")
List<Account> findByUid(Integer uid);
}
-
创建Mybatis的主配置文件 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-->
<properties resource="jdbcConfig.properties"></properties>
<!--配置别名-->
<typeAliases>
<package name="com.kejizhentan.bean"></package>
</typeAliases>
<!--配置环境-->
<environments default="mysql">
<!-- 配置mysql的环境-->
<environment id="mysql">
<!-- 配置事务 -->
<transactionManager type="JDBC"></transactionManager>
<!--配置连接池-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</dataSource>
</environment>
</environments>
<!-- 配置映射文件的位置 -->
<mappers>
<package name="com.kejizhentan.dao"></package>
</mappers>
</configuration>
-
jdbcConfig.properties jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/kjztdatabase
jdbc.username=root
jdbc.password=123456
-
测试类: MybatisTest.java public class MybatisTest {
private InputStream in;
private SqlSession sqlSession;
private IUserDao userDao;
@Before//用于在测试方法执行之前执行
public void init()throws Exception{
//1.读取配置文件,生成字节输入流
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.获取SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3.获取SqlSession对象
sqlSession = factory.openSession(true);
//4.获取dao的代理对象
userDao = sqlSession.getMapper(IUserDao.class);
}
@After//用于在测试方法执行之后执行
public void destroy()throws Exception{
//提交事务
// sqlSession.commit();
//6.释放资源
sqlSession.close();
in.close();
}
@Test
public void testFindAll(){
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}
}
-
结果如下:
4. 使用mybatis注解开发时如何开启二级缓存
详细代码:
-
项目结构 -
创建maven工程并导入坐标 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kejizhentan</groupId>
<artifactId>mybatis-annotation</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--导入mybatis依赖包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--导入mysql的连接依赖包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--导入日志文件logo4j的依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--导入单元测试的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>
</project>
-
创建实体类和dao的接口 User.java public class User implements Serializable {
private Integer id;
private String username;
private String address;
private String sex;
private Date birthday;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", address='" + address + '\'' +
", sex='" + sex + '\'' +
", birthday=" + birthday +
'}';
}
}
IUserDao.java //配置二级缓存的注解
@CacheNamespace(blocking=true)
public interface IUserDao {
@Select("select * from user where id = #{id}")
User findById(Integer id);
}
-
创建Mybatis的主配置文件 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-->
<properties resource="jdbcConfig.properties"></properties>
<!--配置开启二级缓存-->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
<!--配置别名-->
<typeAliases>
<package name="com.kejizhentan.bean"></package>
</typeAliases>
<!--配置环境-->
<environments default="mysql">
<!-- 配置mysql的环境-->
<environment id="mysql">
<!-- 配置事务 -->
<transactionManager type="JDBC"></transactionManager>
<!--配置连接池-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</dataSource>
</environment>
</environments>
<!-- 配置映射文件的位置 -->
<mappers>
<package name="com.kejizhentan.dao"></package>
</mappers>
</configuration>
-
jdbcConfig.properties jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/kjztdatabase
jdbc.username=root
jdbc.password=123456
-
测试类: MybatisTest.java public class MybatisTest {
private InputStream in;
private SqlSessionFactory factory;
@Before//用于在测试方法执行之前执行
public void init()throws Exception{
//1.读取配置文件,生成字节输入流
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.获取SqlSessionFactory
factory = new SqlSessionFactoryBuilder().build(in);
}
@After//用于在测试方法执行之后执行
public void destroy()throws Exception{
//提交事务
// sqlSession.commit();
//6.释放资源
in.close();
}
@Test
public void testFindById(){
SqlSession sqlSession1 = factory.openSession();
IUserDao dao1 = sqlSession1.getMapper(IUserDao.class);
User user1 = dao1.findById(46);
System.out.println(user1);
sqlSession1.close();//一级缓存消失
SqlSession sqlSession2 = factory.openSession();
IUserDao dao2 = sqlSession2.getMapper(IUserDao.class);
User user2 = dao2.findById(46);
System.out.println(user2);
sqlSession2.close();
System.out.println(user1 == user2);
}
}
-
结果如下:
|