MyBatis
文章目录
1、MyBatis 框架概述
- mybatis 是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql 语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。
- mybatis 通过 xml 或注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。
- 采用 ORM 思想解决了实体和数据库映射的问题,对 jdbc 进行了封装,屏蔽了 jdbc api 底层访问细节,使我
们不用与 jdbc api 打交道,就可以完成对数据库的持久化操作。
2、Mybatis 框架入门案例
基于 xml 的 mybatis 使用 (六步)
-
第一步:在 pom.xml 文件中添加 Mybatis 所需要的 jar 包坐标
<dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.27</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.12</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies>
-
第二步:编写 User 实体类
public class User implements Serializable { private int id; private String username; private String password; public int getId() { return id; } public void setId(int id) { this.id = id; } 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; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + '}'; } }
-
第三步:编写持久层接口 IUserDao
public interface IUserDao { /** * 查询所有信息 */ List<User> findAll(); }
-
第四步:编写持久层接口的映射文件 IUserDao.xml
- 要求:
- 创建位置: 必须和持久层接口在相同的包中。
- 名称: 必须以持久层接口名称命名文件名,扩展名是.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.itfzk.mybatis01.dao.IUserDao"> <!--配置查询所有--> <select id="findAll" resultType="com.itfzk.mybatis01.domain.User"> <!--查询语句--> select * from user </select> </mapper>
- 要求:
-
第五步:编写 mybatis.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"> <!--配置连接数据库的 4 个基本信息--> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <!--指定映射配置文件的位置,映射配置文件指的是每个 dao 独立的配置文件--> <mappers> <mapper resource="com/itfzk/mybatis01/dao/IUserDao.xml"></mapper> </mappers> </configuration>
-
第六步:编写测试类
public class mybatisTest { public static void main(String[] args) throws IOException { //1、读取配置文件 InputStream in = Resources.getResourceAsStream("mybatis01.xml"); //2、创建 SqlSessionFactory 工厂 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory sqlSessionFactory = builder.build(in); //3、使用工厂生产 SqlSession 对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //4、使用 SqlSession 创建创建 Dao 接口的代理对象 IUserDao userDao = sqlSession.getMapper(IUserDao.class); //5、使用代理对象执行方法 List<User> users = userDao.findAll(); for(User user : users){ System.out.println(user); } //6、释放资源 sqlSession.close(); in.close(); } }
基于 注解 的 mybatis 使用 (六步)
-
第一步:在 pom.xml 文件中添加 Mybatis 所需要的 jar 包坐标
<dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.27</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.12</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies>
-
第二步:编写 User 实体类
public class User implements Serializable { private int id; private String username; private String password; public int getId() { return id; } public void setId(int id) { this.id = id; } 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; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + '}'; } }
-
第三步:编写持久层接口 IUserDao
public interface IUserDao { /** * 查询所有信息 */ List<User> findAll(); }
-
第四步:在持久层接口 IUserDao.java 的方法中添加注解 @Select
public interface IUserDao { /** * 查询所有信息 */ @Select("select * from user") List<User> findAll(); }
-
第五步:编写 mybatis.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"> <!--配置连接数据库的 4 个基本信息--> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <!--配置指定接口--> <mappers> <mapper resource="com.itfzk.mybatis01.dao.IUserDao.xml"></mapper> </mappers> </configuration>
-
第六步:编写测试类
public class mybatisTest { public static void main(String[] args) throws IOException { //1、读取配置文件 InputStream in = Resources.getResourceAsStream("mybatis01.xml"); //2、创建 SqlSessionFactory 工厂 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory sqlSessionFactory = builder.build(in); //3、使用工厂生产 SqlSession 对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //4、使用 SqlSession 创建创建 Dao 接口的代理对象 IUserDao userDao = sqlSession.getMapper(IUserDao.class); //5、使用代理对象执行方法 List<User> users = userDao.findAll(); for(User user : users){ System.out.println(user); } //6、释放资源 sqlSession.close(); in.close(); } }
3、CRUD 操作 (增删改查)
要求:
- 1、持久层接口和持久层接口的映射配置必须在相同的包下
- 2、持久层映射配置中 mapper 标签的 namespace 属性取值必须是持久层接口的全限定类名
- 3、SQL 语句的配置标签<select>,<insert>,<delete>,<update>的 id 属性必须和持久层接口的方法名相同。
第一步:编写主配置文件(mybatis.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">
<!--配置连接数据库的 4 个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--指定映射配置文件的位置,映射配置文件指的是每个 dao 独立的配置文件-->
<mappers>
<mapper resource="com/itfzk/mybatis03/dao/IUserDao.xml"></mapper>
</mappers>
</configuration>
第二步:编写持久层接口(IUserDao)
public interface IUserDao {
/**
* 查询所有信息
* @return
*/
List<User> findAll();
/**
* 根据 id查询信息
* @return
*/
User findById(int id);
/**
* 根据 name 模糊查询1
*/
List<User> findByName1(String name);
/**
* 根据 name 模糊查询1
*/
List<User> findByName2(String name);
/**
* 查询使用聚合函数
*/
int findCount();
/**
* 添加信息
* @param user
*/
void add(User user);
/**
* 修改信息
* @param user
*/
void updateUser(User user);
/**
* 根据 id来删除信息
* @param id
*/
void deleteUserById(int id);
}
第三步:编写映射配置文件(IUserDao.xml)
-
属性
-
namespace 属性:用于指定持久层接口的权限定接口名
- <mapper namespace=“com.itfzk.mybatis03.dao.IUserDao”>
-
resultType 属性:用于指定返回的结果集的类型
-
parameterType 属性: 用于指定传入参数的类型
-
sql 语句中使用**#{}**字符:
- 代表占位符, 相当于 jdbc 中的?,都是用于执行语句时替换实际的数据。
- 具体的数据是由#{}里面的内容决定的。
- #{}中内容的写法:
- 由于数据类型是基本类型,所以此处可以随意写
-
-
模糊查询的两种方法
- 方法一:#{},前提是数据传入是就已经做了模糊查询的处理,比如:name="%xxx%"
- select * from user where username like #{name}
- 方法二:%${value}%
- select * from user where username like ‘%${value}%’
- 方法一:#{},前提是数据传入是就已经做了模糊查询的处理,比如:name="%xxx%"
<?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.itfzk.mybatis03.dao.IUserDao">
<!--配置查询所有-->
<select id="findAll" resultType="com.itfzk.mybatis03.domain.User">
<!--查询语句-->
select * from user
</select>
<!--配置按照 id查询信息-->
<select id="findById" parameterType="int" resultType="com.itfzk.mybatis03.domain.User">
select * from user where id=#{id}
</select>
<!-- 配置根据 name 模糊查询1 -->
<select id="findByName1" parameterType="String" resultType="com.itfzk.mybatis03.domain.User">
select * from user where username like #{name}
</select>
<!-- 配置根据 name 模糊查询2 -->
<select id="findByName2" parameterType="String" resultType="com.itfzk.mybatis03.domain.User">
select * from user where username like '%${value}%'
</select>
<!-- 查询使用聚合函数 -->
<select id="findCount" resultType="int">
select count(*) from user
</select>
<!--配置添加信息-->
<insert id="add" parameterType="com.itfzk.mybatis03.domain.User">
insert into user(username, password) values(#{username}, #{password})
</insert>
<!--配置修改信息-->
<update id="updateUser" parameterType="com.itfzk.mybatis03.domain.User">
update user set username=#{username},password=#{password} where id=#{id}
</update>
<!--配置删除信息-->
<delete id="deleteUserById" parameterType="java.lang.Integer">
delete from user where id=#{id}
</delete>
</mapper>
第四步:编写测试类
- SqlSession.commit()
- 提交事务,增删改语句必须要这一句,否则执行默认的回滚事务(sqlSession.rollback())
方法一(不推荐)
public class mybatisTest {
/**
* 查找所有信息的测试方法
*/
@Test
public void findAllTest() throws IOException {
//1、读取配置文件
InputStream in = Resources.getResourceAsStream("mybatis03.xml");
//2、创建 SqlSessionFactory 工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(in);
//3、使用工厂生产生产 SqlSession 对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4、使用 SqlSession 创建创建 Dao 接口的代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
//5、使用代理对象执行方法
List<User> users = userDao.findAll();
for(User user : users){
System.out.println(user);
}
//6、释放资源
sqlSession.close();
in.close();
}
/**
* 根据 id查询信息
*/
@Test
public void findById() throws IOException{
//1、读取配置文件
InputStream in = Resources.getResourceAsStream("mybatis03.xml");
//2、创建 SqlSessionFactory 工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(in);
//3、使用工厂生产生产 SqlSession 对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4、使用 SqlSession 创建创建 Dao 接口的代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
//5、使用代理对象执行方法
User user = userDao.findById(1);
System.out.println(user);
//6、释放资源
sqlSession.close();
in.close();
}
/**
* 根据 name 模糊查询1
*/
@Test
public void findByName1Test() throws IOException {
//1、读取配置文件
InputStream in = Resources.getResourceAsStream("mybatis03.xml");
//2、创建 SqlSessionFactory 工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(in);
//3、使用工厂生产生产 SqlSession 对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4、使用 SqlSession 创建创建 Dao 接口的代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
//5、使用代理对象执行方法
List<User> users = userDao.findByName1("%fff%");
for(User user : users){
System.out.println(user);
}
//6、释放资源
sqlSession.close();
in.close();
}
/**
* 根据 name 模糊查询2
*/
@Test
public void findByName2Test() throws IOException {
//1、读取配置文件
InputStream in = Resources.getResourceAsStream("mybatis03.xml");
//2、创建 SqlSessionFactory 工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(in);
//3、使用工厂生产生产 SqlSession 对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4、使用 SqlSession 创建创建 Dao 接口的代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
//5、使用代理对象执行方法
List<User> users = userDao.findByName2("fff");
for(User user : users){
System.out.println(user);
}
//6、释放资源
sqlSession.close();
in.close();
}
/**
* 查询使用聚合函数
*/
@Test
public void findCountTest() throws IOException {
//1、读取配置文件
InputStream in = Resources.getResourceAsStream("mybatis03.xml");
//2、创建 SqlSessionFactory 工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(in);
//3、使用工厂生产生产 SqlSession 对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4、使用 SqlSession 创建创建 Dao 接口的代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
//5、使用代理对象执行方法
int count = userDao.findCount();
System.out.println(count);
//6、释放资源
sqlSession.close();
in.close();
}
/**
* 添加信息的测试方法
*/
@Test
public void addTest() throws IOException {
User user = new User();
user.setUsername("789");
user.setPassword("789789");
//1、读取配置文件
InputStream in = Resources.getResourceAsStream("mybatis03.xml");
//2、创建 SqlSessionFactory 工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(in);
//3、使用工厂生产生产 SqlSession 对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4、使用 SqlSession 创建创建 Dao 接口的代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
//5、使用代理对象执行方法
userDao.add(user);
sqlSession.commit(); //提交事务,增删改语句必须要这一句,否则执行默认的回滚事务(sqlSession.rollback())
//6、释放资源
sqlSession.close();
in.close();
}
/**
* 修改信息的测试方法
*/
@Test
public void updateUserTest() throws IOException {
User user = new User();
user.setId(9);
user.setUsername("kkk789");
user.setPassword("789789");
//1、读取配置文件
InputStream in = Resources.getResourceAsStream("mybatis03.xml");
//2、创建 SqlSessionFactory 工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(in);
//3、使用工厂生产生产 SqlSession 对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4、使用 SqlSession 创建创建 Dao 接口的代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
//5、使用代理对象执行方法
userDao.updateUser(user);
sqlSession.commit();
//6、释放资源
sqlSession.close();
in.close();
}
/**
* 按 id删除信息
*/
@Test
public void deleteByIdTest() throws IOException {
//1、读取配置文件
InputStream in = Resources.getResourceAsStream("mybatis03.xml");
//2、创建 SqlSessionFactory 工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(in);
//3、使用工厂生产生产 SqlSession 对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4、使用 SqlSession 创建创建 Dao 接口的代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
//5、使用代理对象执行方法
userDao.deleteUserById(10);
sqlSession.commit();
//6、释放资源
sqlSession.close();
in.close();
}
}
方法二(推荐)
public class mybatisTestPlus {
private InputStream in;
private SqlSession sqlSession;
private IUserDao userDao;
@Before //用于测试方法前执行
public void init() throws IOException {
//1、读取配置文件
in = Resources.getResourceAsStream("mybatis03.xml");
//2、创建 SqlSessionFactory 工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(in);
//3、使用工厂生产生产 SqlSession 对象
sqlSession = sqlSessionFactory.openSession();
//4、使用 SqlSession 创建创建 Dao 接口的代理对象
userDao = sqlSession.getMapper(IUserDao.class);
}
@After //用于测试后执行
public void destory() throws IOException {
sqlSession.commit(); //提交事务,这句必须写,否则执行默认的回滚事务(sqlSession.rollback())
//6、释放资源
sqlSession.close();
in.close();
}
/**
* 查找所有信息的测试方法
*/
@Test
public void findAllTest() {
//5、使用代理对象执行方法
List<User> users = userDao.findAll();
for(User user : users){
System.out.println(user);
}
}
/**
* 根据 id查询信息
*/
@Test
public void findById(){
//5、使用代理对象执行方法
User user = userDao.findById(1);
System.out.println(user);
}
/**
* 根据 name 模糊查询1
*/
@Test
public void findByName1Test(){
List<User> users = userDao.findByName1("%fff%");
for(User user : users){
System.out.println(user);
}
}
/**
* 根据 name 模糊查询2
*/
@Test
public void findByName2Test(){
List<User> users = userDao.findByName2("fff");
for(User user : users){
System.out.println(user);
}
}
/**
* 查询使用聚合函数
*/
@Test
public void findCountTest(){
int count = userDao.findCount();
System.out.println(count);
}
/**
* 添加信息的测试方法
*/
@Test
public void addTest() {
User user = new User();
user.setUsername("789");
user.setPassword("789789");
//5、使用代理对象执行方法
userDao.add(user);
}
/**
* 修改信息的测试方法
*/
@Test
public void updateUserTest() {
User user = new User();
user.setId(11);
user.setUsername("kkk789");
user.setPassword("789789");
//5、使用代理对象执行方法
userDao.updateUser(user);
}
/**
* 按 id删除信息
*/
@Test
public void deleteByIdTest() {
//5、使用代理对象执行方法
userDao.deleteUserById(11);
}
}
4、Mybatis 的参数传入
parameterType 配置参数
- 基本类型和 String 类型,我们可以直接写类型名称,也可以使用 包名.类名 的方式
- 例如:String == java.lang.String
- 实体类类型,目前我们只能使用全限定类名
- 原因:
- mybaits 在加载时已经把常用的数据类型注册了别名,从而我们在使用时可以不写包名,而我们的是实体类并没有注册别名,所以必须写全限定类名
5、Mybatis 的输出结果封装
resultType 配置结果类型
- resultType 属性可以指定结果集的类型,它支持基本类型和实体类类型。
- 如果注册过类型别名的,可以直接使用别名。没有注册过的必须使用全限定类名。
- 实体类中的属性名称必须和查询语句中的列名保持一致,否则无法实现封装。
resultMap 结果类型
-
resultMap 标签可以建立查询的列名和实体类的属性名称不一致时建立对应关系。从而实现封装。
-
在 select 标签中使用 resultMap 属性指定引用即可。同时 resultMap 可以实现将查询结果映射为复杂类型的 pojo,比如在查询结果映射对象中包括 pojo 和 list 实现一对一查询和一对多查询
-
**<resultMap>**标签属性
- id:给定唯一标识,给查询 <select> 标签引用用的
- type:实体类全限定类名
- 标签
- <id> 标签:用于指定主键字段
- property 属性:用于指定实体类属性名称
- column 属性:用于指定数据库列名
- <result> 标签:用于指定非主键字段
- property 属性:用于指定实体类属性名称
- column 属性:用于指定数据库列名
- <id> 标签:用于指定主键字段
映射配置
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.itfzk.dao.IUserDao"> <resultMap id="userMap" type="com.itfzk.bean.User"> <id property="id" column="id"></id> <result property="name" column="username"></result> <result property="password" column="password"></result> </resultMap> <!-- 查询所有,使用 resultMap--> <select id="findAll" resultMap="userMap"> select * from user </select> </mapper>
6、主配置文件(mybatis.xml)
配置的内容和顺序
- properties(属性)
- property
- settings(全局配置参数)
- setting
- typeAliases(类型别名)
- typeAliase
- package
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境集合属性对象)
- environment(环境子属性对象)
- transactionManager(事务管理)
- dataSource(数据源)
- environment(环境子属性对象)
- mappers(映射器)
- mapper
- package
<?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>
<!-- 全局配置参数 -->
<settings>
<setting name="" value=""/>
</settings>
<!-- 类型别名 -->
<typeAliases>
<typeAlias type="" />
<package name=""/>
</typeAliases>
<!-- 类型处理器 -->
<typeHandlers></typeHandlers>
<!-- 对象工厂 -->
<objectFactory type=""></objectFactory>
<!-- 插件 -->
<plugins>
<plugin interceptor=""></plugin>
</plugins>
<!-- 环境集合属性对象 -->
<environments default="">
<!-- 环境子属性对象 -->
<environment id="">
<!-- 事务管理 -->
<transactionManager type=""></transactionManager>
<!-- 数据源 -->
<dataSource type="">
</dataSource>
</environment>
</environments>
<!-- 映射器 -->
<mappers>
<mapper></mapper>
<package name=""/>
</mappers>
</configuration>
properties(属性)
方法一:在 properties 中配置数据源
<!-- 配置数据源 -->
<properties>
<property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="jdbc.url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="jdbc.username" value="root"/>
<property name="jdbc.password" value="123456"/>
</properties>
<environments default="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>
方法一:在 properties 中引用 properties配置文件中的数据源
jdbc.properties配置文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=123456
mybatis.xml中的配置
<!-- 引用 jdbc.properties 文件中数据源的配置 -->
<properties resource="jdbc.properties">
</properties>
<environments default="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>
typeAliases(类型别名)
方法一: 单个别名定义
mybatis.xml 配置
<!-- 单个别名定义 -->
<typeAliases>
<typeAlias alias="user" type="com.itfzk.bean.User"/>
</typeAliases>
映射文件的配置
<!-- 没使用 <typeAliases>标签中的 <typeAlias>标签 -->
<select id="findAll" resultType="com.itfzk.bean.User">
select * from user
</select>
<!-- 使用了 <typeAliases>标签中的 <typeAlias>标签 -->
<select id="findAll" resultType="user">
select * from user
</select>
方法二:批量别名定义
-
扫描整个包下的类,别名为类名(首字母大写或小写都可以)
mybatis.xml 配置
<typeAliases> <package name="com.itfzk.bean"/> </typeAliases>
映射文件的配置
<!-- 没使用 <typeAliases>标签中的 <package>标签 --> <select id="findAll" resultType="com.itfzk.bean.User"> select * from user </select> <!-- 使用了 <typeAliases>标签中的 <package>标签 --> <select id="findAll" resultType="user"> select * from user </select>
mappers(映射器)
<package name="">
-
注册指定包下的所有 mapper 接口
-
注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中
<mappers> <package name="com.itfzk.dao"/> </mappers>
<mapper resource="">
-
使用相对于类路径的资源
-
路径为xml映射文件的:路径包名+文件名
<mappers> <mapper resource="com/itfzk/dao/IUserDao.xml"></mapper> </mappers>
<mapper url="">
-
使用相对于类路径的资源
-
路径对应的是网络上了某个文件,注意file:// 前缀 +路径+文件名
<mappers>
<mapper url="file:///com/itfzk/dao/IUserDao.xml"/>
</mappers>
<mapper class="">
-
使用 mapper 接口类路径
-
注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中
<mappers> <mapper class="com.itfzk.dao.IUserDao"></mapper> </mappers>
7、Mybatis 连接池
-
Mybatis 将数据源分为三类
属性 说明 UNPOOLED 不使用连接池的数据源 POOLED 使用连接池的数据源 JNDI 使用 JNDI 实现的数据源 -
Mybatis 中数据源的配置
在主配置文件配置 <dataSource>
- 属性
- type
- type=”POOLED”: MyBatis 会创建 PooledDataSource 实例
- type=”UNPOOLED” : MyBatis 会创建 UnpooledDataSource 实例(不使用连接池的数据源)
- type=”JNDI”: MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用
- type
<environments default="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/mybatis"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments>
- 属性
8、Mybatis 的动态 SQL 语句
<if>标签
-
根据实体类的不同取值,使用不同的 SQL 语句来进行查询。
- 比如:username 如果不为空时可以根据 username查询,如果 password 不为空时 password 也作为查询条件
-
注意: <if>标签的 test 属性中写的是对象的属性名,如果是包装类的对象要使用 OGNL 表达式的写法
映射配置文件
<select id="findTest" resultType="User" parameterType="User"> select * from user where 1=1 <if test="username != null and username != ''"> and username like #{username} </if> <if test="password != null and password != ''"> and password like #{password} </if> </select>
测试类
public class IUserDaoTest { @Test public void findTest() throws Exception { //1.读取配置文件 InputStream in = Resources.getResourceAsStream("mybatis.xml"); //2.创建 SqlSessinFactory 工厂 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory sqlSessionFactory = builder.build(in); //3.使用工厂生产 SqlSession 对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //4.使用 SqlSession 创建 Dao 接口的代理对象 IUserDao userDao = sqlSession.getMapper(IUserDao.class); //5.使用代理对象执行方法 List<User> users = userDao.findTest(new User(0, "%fff%", null)); for(User user : users){ System.out.println(user); } //6.释放对象 sqlSession.close(); in.close(); } }
<where>标签
-
简化上面 where 1=1 的条件拼装,我们可以采用<where>标签来简化开发。
<select id="findTest" resultType="User" parameterType="User"> select * from user <where> <if test="username != null and username != ''"> and username like #{username} </if> <if test="password != null and password != ''"> and password like #{password} </if> </where> </select>
<foreach>标签
-
SQL 语句:
- select * from user where id in (?)
-
<foreach>标签用于遍历集合,它的属性:
- collection:代表要遍历的集合元素,注意编写时不要写#{}
- open:代表语句的开始部分
- close:代表结束部分
- item:代表遍历集合的每个元素,生成的变量名
- sperator:代表分隔符
-
需求:传入多个 id 查询用户信息查询
映射配置文件
<select id="findTest" resultType="User" parameterType="arraylist"> select * from user <where> <if test="list != null and list.size() > 0"> <foreach collection="list" open="and id in (" close=")" item="id" separator=","> #{id} </foreach> </if> </where> </select>
测试类
public class IUserDaoTest { @Test public void findTest() throws Exception { //1.读取配置文件 InputStream in = Resources.getResourceAsStream("mybatis.xml"); //2.创建 SqlSessinFactory 工厂 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory sqlSessionFactory = builder.build(in); //3.使用工厂生产 SqlSession 对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //4.使用 SqlSession 创建 Dao 接口的代理对象 IUserDao userDao = sqlSession.getMapper(IUserDao.class); //5.使用代理对象执行方法 List<Integer> list = new ArrayList<Integer>(); list.add(1); list.add(2); list.add(3); List<User> users = userDao.findTest(list); for(User user : users){ System.out.println(user); } //6.释放对象 sqlSession.close(); in.close(); } }
Mybatis 中简化编写的 SQL 片段
-
Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的
<!-- 将重复的 sql 提取出来 --> <sql id="defaultSql"> select * from user </sql> <!-- 使用 include 引用 --> <select id="findTest" resultType="User" parameterType="arraylist"> <include refid="defaultSql"></include> <where> and id=1 </where> </select>
9、Mybatis 多表查询
一对一查询
方法一:定义账户信息的实体类
实体类:Account.java
public class Account {
private int aid;
private int uid;
private int age;
public Account() {
}
public int getId() {
return aid;
}
public void setId(int aid) {
this.aid = aid;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Account{" +
"aid=" + aid +
", uid=" + uid +
", age=" + age +
'}';
}
}
实体类:UserAccount.java
public class UserAccount extends Account implements Serializable {
private int id;
private String username;
private String password;
public UserAccount() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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;
}
@Override
public String toString() {
return "UserAccount{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", account=" + super.toString() +
'}';
}
}
映射配置文件
<select id="findAllUserAccount" resultType="UserAccount">
select u.*, a.id as aid, a.uid, a.age from user u, account a where u.id=a.uid
</select>
方法二:修改实体类并使用 <resultMap> 建立对应关系
实体类User.java
public class User implements Serializable {
private int id;
private String username;
private String password;
public User() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
实体类:Account.java
public class Account implements Serializable {
private int aid;
private int uid;
private int age;
private User user;
public int getAid() {
return aid;
}
public void setAid(int aid) {
this.aid = aid;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Account{" +
"aid=" + aid +
", uid=" + uid +
", age=" + age +
", user=" + user +
'}';
}
}
映射配置文件
<!-- 建立对应关系,定义封装 account 和 user 的 resultMap -->
<resultMap id="accountUserMap" type="Account">
<id property="aid" column="aid"></id>
<result property="uid" column="uid"></result>
<result property="age" column="age"></result>
<!-- 一对一的关系映射:配置封装 User 的内容 -->
<association property="user" javaType="User">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="password" column="password"></result>
</association>
</resultMap>
<!-- 查询所有 -->
<select id="findAllUserAccount" resultMap="accountUserMap">
select * from user u, account a where u.id=a.uid
</select>
一对多查询
实体类:Account.java
public class Account implements Serializable {
private int aid;
private int uid;
private int age;
public int getAid() {
return aid;
}
public void setAid(int aid) {
this.aid = aid;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Account{" +
"aid=" + aid +
", uid=" + uid +
", age=" + age +
'}';
}
}
实体类:User.java
public class User {
private int id;
private String username;
private String password;
private List<Account> accounts;
public List<Account> getAccounts() {
return accounts;
}
public void setAccounts(List<Account> accounts) {
this.accounts = accounts;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", accounts=" + accounts +
'}';
}
}
映射配置文件
<!-- 建立对应关系,定义封装 user 和 account 的 resultMap -->
<resultMap id="userAccountMap" type="User">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="password" column="password"></result>
<!-- 一对一的关系映射:配置封装 Account 的内容 -->
<collection property="accounts" ofType="Account">
<id property="aid" column="aid"></id>
<result property="uid" column="uid"></result>
<result property="age" column="age"></result>
</collection>
</resultMap>
<!-- 查询语句 -->
<select id="findAllUserAccount" resultMap="userAccountMap">
select * from user u, account a where u.id=a.uid
</select>
多对多查询
- 与 一对多查询操作 一样
10、Mybatis 延迟加载
概述
- 在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载.
- 好处:
- 先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为单表查询比多张查询速度要快
- 坏处:
- 因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降
使用 <assocation> 实现延迟加载
在主配置文件(mybatis.xml)中开启延迟加载的支持
<settings>
<!--延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。-->
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
映射配置文件
<!--定义封装 account 和 user 的 resultMap-->
<resultMap id="accountUserMap" type="Account">
<id property="id" column="id"></id>
<result property="uid" column="uid"></result>
<result property="age" column="age"></result>
<!-- 一对一的关系映射
select属性 :要调用的 select 方法的 全限定类名.方法
column属性 :用户根据 所需的参数 查询所需的数据
-->
<association property="user" select="com.itfzk.mybatis07.dao.IUserDao.findById" column="uid"></association>
</resultMap>
使用 <Collection> 实现延迟加载
在主配置文件(mybatis.xml)中开启延迟加载的支持
<settings>
<!--延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。-->
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
映射配置文件
<!--配置一对多-->
<resultMap id="userAccountMap" type="User">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="password" column="password"></result>
<!-- 一对多的关系映射
select属性 :要调用的 select 方法的 全限定类名.方法
column属性 :用户根据 所需的参数 查询所需的数据
-->
<collection property="accounts" select="com.itfzk.mybatis07.dao.IAccountDao.findAccountById" column="id"></collection>
</resultMap>
11、Mybatis 缓存
一级缓存
- 一级缓存是 SqlSession 级别的缓存,只要 SqlSession 没有 flush 或 close,它就存在
- 一级缓存的清空
- 一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除, commit(), close()等方法时,就会清空一级缓存
- 缓存过程
- 第一次发起查询用户 id 的用户信息,先找缓存中是否有该 id 的用户信息,如果没有,从数据库查询用户信息
- 得到用户信息,将用户信息存储到一级缓存中
- 如果 sqlSession 去执行 commit 操作(执行插入、更新、删除),清空 SqlSession 中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读
- 第二次发起查询用户 id 的用户信息,先去找缓存中是否有该 id 的用户信息,缓存中有,从缓存中获取用户信息
二级缓存
概述
- 二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mapper 映射的 sql 语句,多个 SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的
- 缓存过程
- 首先开启 mybatis 的二级缓存
- sqlSession 去查询用户信息,查询到用户信息会将查询数据存储到二级缓存中
- 如果 SqlSession 去执行相同 mapper 映射下 sql,执行 commit 提交, 将会清空该 mapper 映射下的二级缓存区域的数据
- sqlSession 去查询与 sqlSession1 相同的用户信息, 首先会去缓存中找是否存在数据,如果存在直接从缓存中取出数据,没有就查询数据库然后存储到缓存中
步骤
-
第一步:在主配置文件开启二级缓存 cacheEnabled
-
cacheEnabled 的取值默认为 true,这一步可以不配置。true :开启二级缓存;false :不开启二级缓存
<?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> <settings> <!-- 开启二级缓存 --> <setting name="cacheEnabled" value="true"/> </settings> </configuration>
-
第二步:配置相关的 Mapper 映射配置文件 <cache>
-
**<cache>**标签表示当前这个 mapper 映射将使用二级缓存,区分的标准就看 mapper 的 namespace 值。
<?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.itfzk.dao.IUserDao"> <!-- 开启二级缓存的支持 --> <cache></cache> </mapper>
-
第三步: 配置 **<select>**上面的 useCache 属性
-
将映射配置文件中的**<select>**标签中设置 **useCache=”true”**代表当前使用二级缓存,不使用二级缓存设置为 false
-
注意: 针对每次查询都需要最新的数据 sql,要设置成 useCache=false,禁用二级缓存
<select id="findById" resultType="com.itfzk.bean.User" parameterType="int" useCache="true"> select * from user where id=#{id} </select>
12、Mybatis 注解开发
常用注解
- @Insert :实现新增
- @Update :实现更新
- @Delete :实现删除
- @Select :实现查询
- @Result :实现结果集封装
- @Results :可以与@Result 一起使用,封装多个结果集
- @ResultMap :实现引用@Results 定义的封装
- @One :实现一对一结果集封装
- @Many :实现一对多结果集封装
- @SelectProvider :实现动态 SQL 映射
- @CacheNamespace :实现注解二级缓存的使用
使用 Mybatis 注解实现基本 CRUD (四步)
-
第一步:编写实体类
public class User { private int id; private String username; private String password; public int getId() { return id; } public void setId(int id) { this.id = id; } 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; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + '}'; } }
-
第二步:使用注解方式编写持久层接口
public interface IUserDao { //查询所有 @Select("select * from user") public List<User> findAll(); //根据 id 查询所有 @Select("select * from user where id = #{id}") public User findById(int id); //保存信息 @Insert("insert into user(username, password) values(#{username}, #{password})") public void save(User user); //修改信息 @Update("update user set username = #{username}, password = #{password} where id = #{id}") public void update(User user); //删除信息 @Delete("delete from user where id = #{id}") public void delete(int id); }
-
第三步:编写主配置文件
<?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> <environments default="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/mybatis"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <package name="cn.itfzk.dao"/> </mappers> </configuration>
-
第四步:编写测试类
public class IUserDaoTest { private InputStream in; private SqlSession sqlSession; private IUserDao userDao; @Before public void init() throws IOException { //1、获取配置文件 in = Resources.getResourceAsStream("mybatis.xml"); //2、获取 SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); //3、获取 SqlSession sqlSession = sqlSessionFactory.openSession(); //4、使用工厂创建Dao接口 userDao = sqlSession.getMapper(IUserDao.class); } @After public void destory() throws IOException { //6、提交并释放对象 sqlSession.commit(); sqlSession.close(); in.close(); } //查询所有 @Test public void findAllTest(){ //5、使用代理对象执行方法 List<User> users = userDao.findAll(); for(User user : users){ System.out.println(user); } } //根据 id 查询 @Test public void findByIdTest(){ //5、使用代理对象执行方法 System.out.println(userDao.findById(1)); } //保存信息 @Test public void saveTest(){ //5、使用代理对象执行方法 User user = new User(); user.setUsername("123"); user.setPassword("123"); userDao.save(user); } //修改信息 @Test public void updateTest(){ //5、使用代理对象执行方法 User user = new User(); user.setId(13); user.setUsername("psq"); user.setPassword("123"); userDao.update(user); } //删除信息 @Test public void deleteTest(){ //5、使用代理对象执行方法 userDao.delete(13); } }
使用注解实现复杂关系映射
@Results 注解
-
代替的是标签 <resultMap>
-
该注解中可以使用单个@Result 注解,也可以使用@Result 集合
- 集合:@Results({@Result(), @Result() })
- 单个:@Results(@Result())
@Results(id = "userAccountMap", value = { @Result(id = true, property = "id", column = "id"), @Result(property = "username", column = "username"), @Result(property = "password", column = "password") })
@Result 注解
-
代替了**<id>标签和<result>**标签
-
属性
- id :是否是主键字段
- column :数据库的列名
- property :实体类的属性名
- one :需要使用的@One 注解(@Result(one=@One)()))
- many :需要使用的@Many 注解(@Result(many=@many)()))
@Result(id = true, property = "id", column = "id") @Result(property = "username", column = "username")
@One 注解(一对一)
-
代替了**<assocation>**标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。
-
属性
- select :指定用来多表查询的 sqlmapper
fetchType :会覆盖全局的配置参数 lazyLoadingEnabled
- select :指定用来多表查询的 sqlmapper
-
使用格式:
- @Result(column=" “,property=”",one=@One(select=""))
@Results(id = "accountUserMap", value = { @Result(id = true, property = "id", column = "id"), @Result(property = "uid", column = "uid"), @Result(property = "age", column = "age"), @Result(property = "user", column = "uid", one = @One(select = "com.itfzk.mybatis08.dao.IUserDao.findById")) })
@Many 注解(一对多)
-
代替了**<Collection>**标签,是是多表查询的关键,在注解中用来指定子查询返回对象集合
-
使用格式:
- @Result(property="",column="",many=@Many(select=""))
@Results(id = "userAccountMap", value = { @Result(id = true, property = "id", column = "id"), @Result(property = "username", column = "username"), @Result(property = "password", column = "password"), @Result(property = "accounts", column = "id", many = @Many(select = "com.itfzk.mybatis08.dao.IAccountDao.findAccountById")) })
使用注解实现 一对一,一对多 复杂关系映射及延迟加载
-
第一步:添加 User 实体类及 Account 实体类
//Account.java实体类 public class Account implements Serializable { private int id; private int uid; private int age; //一对一 private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getUid() { return uid; } public void setUid(int uid) { this.uid = uid; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Account{" + "id=" + id + ", uid=" + uid + ", age=" + age + '}'; } } //User.java实体类 public class User implements Serializable { private int id; private String username; private String password; //一对多 private List<Account> accounts; public List<Account> getAccounts() { return accounts; } public void setAccounts(List<Account> accounts) { this.accounts = accounts; } public int getId() { return id; } public void setId(int id) { this.id = id; } 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; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + '}'; } }
-
第二步:编写配置文件
<?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设置--> <settings> <!--延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。--> <setting name="lazyLoadingEnabled" value="true"/> </settings> <!--配置环境--> <environments default="mysql"> <!--配置MySQL的配置环境--> <environment id="mysql"> <!--配置事务类型--> <transactionManager type="JDBC"></transactionManager> <!--配置数据源(连接池)--> <dataSource type="POOLED"> <!--配置连接数据库的 4 个基本信息--> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <!--指定映射配置文件的位置,映射配置文件指的是每个 dao 独立的配置文件--> <mappers> <package name="com.itfzk.mybatis08.dao"/> </mappers> </configuration>
-
第三步:编写持久层接口 IAccountDao(一对一),IUserDao(一对多) 并使用注解配置
/** * IAccountDao(一对一)接口 */ public interface IAccountDao { /** * 一对一查询所有信息 * @return */ @Select("select * from account a left join user u on a.uid = u.id") @Results(id = "accountUserMap", value = { @Result(id = true, property = "id", column = "id"), @Result(property = "uid", column = "uid"), @Result(property = "age", column = "age"), @Result(property = "user", column = "uid", one = @One(select = "com.itfzk.mybatis08.dao.IUserDao.findById")) }) List<Account> findAllOneByOne(); /** * 根据 id查询信息 * @param uid * @return */ @Select("select * from account where uid = #{uid}") List<Account> findAccountById(int uid); } /** * IUserDao(一对多)接口 */ public interface IUserDao { /** * 一对多查询所有 * @return */ @Select("select * from user u left join account a on u.id = a.uid") @Results(id = "userAccountMap", value = { @Result(id = true, property = "id", column = "id"), @Result(property = "username", column = "username"), @Result(property = "password", column = "password"), @Result(property = "accounts", column = "id", many = @Many(select = "com.itfzk.mybatis08.dao.IAccountDao.findAccountById")) }) List<User> findAllOneByN(); /** * 查询所有信息 * @return */ @Select("select * from user") List<User> findAll(); /** * 根据 id查询信息 * @return */ @Select("select * from user where id = #{id}") User findById(int id); /** * 添加信息 * @param user */ @Insert("insert into user(username, password) values(#{username}, #{password})") void add(User user); /** * 修改信息 * @param user */ @Update("update user set username=#{username}, password=#{password} where id=#{id}") void updateUser(User user); /** * 根据 id来删除信息 * @param id */ @Delete("delete from user where id=#{id}") void deleteUserById(int id); }
基于注解的二级缓存
-
在主配置文件开启二级缓存支持
<!-- 配置二级缓存 --> <settings> <!-- 开启二级缓存的支持 --> <setting name="cacheEnabled" value="true"/> </settings>
-
在持久层接口中使用注解配置二级缓存
//mybatis 基于注解方式实现配置二级缓存 @CacheNamespace(blocking=true) public interface IUserDao {}