Java框架-Mybatis
框架概述
框架简介
- 框架指定是一系列工具类,它是个半成品,基于框架开发,可以提高效率
- 框架是我们软件开发中的一套解决方案,不同的框架解决的是不同的问题
- 使用框架的好处:
- 框架封装了很多的细节,使开发者可以使用极简的方式实现功能,大大提高开发效率
三层架构
架构 | 类名 | 作用 |
---|---|---|
表现层 | controller | 用于展示数据 |
业务层 | service | 处理业务逻辑 |
持久层 | dao | 和数据库交互 |
回顾JDBC操作数据库
- 步骤
- 加载驱动
- 获取连接
- 定义要执行的语句
- 创建要执行sql语句的预编译处理对象并设置参数
- 执行sql语句
- 处理结果集
- 关闭连接,释放资源
- 问题
- 频繁的创建连接关闭连接,耗费资源
- 连接池可以解决这个问题
- 将sql语句硬编码到项目中,每次修改sql语句都会导致重新编译
- 将sql语句配置到xml文件中
- 传递sql语句的参数,也会出现硬编码
- 将参数传递到xml文件中
- 频繁的创建连接关闭连接,耗费资源
持久层技术解决方案
- JDBC技术
- Connection
- PreparedStatement
- ResultSet
- Spring的JdbcTemplate
- Spring中对Jdbc的简单封装
- Apache的DBUtils
- 它和Spring的JdbcTemp很像,也是对Jdbc的简单封装
- 以上这些都不是框架
- JDBC是规范
- Spring的JdbcTemplate和Apache的DbUtils都只是工具类
Mybatis上
Mybatis概述
- mybatis是一个持久层的框架,用java编写的
- 它封装了jdbc操作的很多细节,使开发者只需要关注sql语句本身,而无需关注注册驱动,创建连接等繁杂过程
- mybatis是一个支持自定义sql语句的半自动框架
- 它使用了ORM思想实现了结果集的封装
- ORM
- Object Relational Mapping 对象关系映射
- 简单的说
- 就是把关系型数据库表和实体类及实体类的属性一一对应起来
- 让我们可以操作实体类就行实现操作数据库表
- 实体类中的属性和数据库表的字段名称保持一致
- 官方文档定义
- MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
- 官方文档: https://mybatis.org/mybatis-3/zh/index.html
Mybatis入门
-
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.danny</groupId> <artifactId>mybatisDemo1_annotation</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> <scope>test</scope> </dependency> </dependencies> </project>
-
-
创建实体类和
dao
的接口 -
创建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> <!-- 配置环境 --> <environments default="mysql"> <!-- 配置mysql的环境 --> <environment id="mysql"> <!-- 配置事务类型 --> <transactionManager type="JDBC"></transactionManager> <!-- 配置数据源(连接池) --> <dataSource type="POOLED"> <!-- 配置连接数据库的4个基本信息 --> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/db_mybatis?serverTimezone=GMT%2B8&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 如果是用注解来配置的话,此处一个使用class属性指定被注解的dao全限定类名 --> <mappers> <mapper class="com.danny.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.danny.dao.IUserDao"> <!--配置查询所有--> <select id="findAll" resultType="user"> select * from user </select> </mapper>
-
-
-
环境搭建的注意事项
- 创建
IUserDao.xml
和IUserDao.java
时名称是为了我们之前的知识保持一致- 在Mybatis中它把持久层的操作接口名称和映射文件也叫做:
Mapper
- 所以:
IUserdao
和IUserMapper
是一样的
- 在Mybatis中它把持久层的操作接口名称和映射文件也叫做:
- 在idea创建目录的时候,它和包是不一样的
- 包在创建是:
com.danny.dao
它是三级结构 - 目录创建时:
com.danny.dao
是一级目录
- 包在创建是:
- 根据数据库列名创建实体类可以实现序列化接口用来提高传输速度
- Mybatis的映射配置文件位置必须和
dao
接口包结构相同 - 映射配置文件的
mapper
标签,namespace
属性的取值必须是dao
接口的全限定类名 - 映射配置文件的操作配置(
select
), id属性的取值必须是dao
接口的方法名
- 当我们遵从了第4,5,6点后,我们在开发中就无需再写
dao
的实现类
- 创建
-
Mybatis入门案例
-
//1.读取配置文件 InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml"); //2.创建SqlSessionFactory工厂 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); //3.使用工厂生产SqlSession对象 SqlSession session = factory.openSession(); //4.使用SqlSession创建Dao接口的代理对象 IUserDao userDao = session.getMapper(IUserDao.class); //5.使用代理对象执行方法 List<User> users = userDao.findAll(); for (User user : users){ System.out.println(user); } //6.释放资源 session.close(); in.close();
- 注意事项
- 不要忘记在映射配置中告知mybatis要封装到哪个实体类中
- 配置方式: 指定实体类的全限定类名
- mybatis基于注解的入门案例:
- 把
IUserDao.xml
移除,在dao
接口的方法上使用@Select
注解,并指定SQL语句 - 同时需要在
SqlMapConfig.xml
中的mapper配置时,使用class属性指定dao
接口的全限定类名
- 把
- 明确:
- 我们在实际开发中,越简便越好,所以都是采用不写
dao
实现类的方式 - 不管使用xml还是注解配置
- 但是Mybatis是支持写dao实现类的
- 我们在实际开发中,越简便越好,所以都是采用不写
- 自定义Mybatis的分析:
- mybatis在使用代理dao的方式实现增删改查时只做两件事
- 创建代理对象
- 在代理对象中调用selectList
- mybatis在使用代理dao的方式实现增删改查时只做两件事
- 注意事项
-
Mybatis框架主配置文件
-
<properties>
属性标签- 首先读取在 properties 元素体内指定的属性。
- 然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
- 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。
-
优先级3>2>1
-
<!--定义属性变量,通过${变量名}来获取变量--> <properties> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&characterEncoding=utf-8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </properties> <!--引入外部属性文件,通过${变量名}来获取变量值--> <properties resource="db.properties"></properties>
-
<settings>
设置标签-
表示mybatis框架的配置特性标签,可以做各种特殊配置
-
<settings> <setting name="cacheEnabled" value="true"/> </settings>
-
更多配置查看 https://mybatis.org/mybatis-3/zh/configuration.html#settings
-
-
<typeAliases>
类别名标签-
该标签用于为数据类型取别名的标签
-
<!-- 单个与批量取别名只能二选一 --> <typeAliases> <!-- 单个取别名 --> <typeAlias type="com.danny.dao.IUserDao" alias="dao"/> <!-- 批量取别名 --> <package name="com.danny.dao"/> </typeAliases>
-
-
<typeHandlers>
类型处理器标签(了解)- 作用将数据库字段数据类型转换java对象中的属性的数据类型, 或者反之
- 用于注册自定义类型处理器,而mybatis已经提供了大量的类型处理器供我们使用,无需自定义
-
<objectFactory>
对象工厂标签(了解)- 该标签用于注册自定义的工厂对象,而mybatis已经提供了工厂对象,不需要自己创建工厂对象
- 创建数据库记录封装的对象实例
-
<plugins>
插件标签-
该标签叫做插件标签,用于扩展其他功能,如扩展分页插件
-
步骤
-
引入分页插件的jar包
pom.xml
中-
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.3</version> </dependency>
-
-
注册分页插件
-
<plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"/> </plugins>
-
-
实现分页查询
-
@Test public void myTest2() throws IOException { String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = sqlSessionFactory.openSession(); PageHelper.startPage(2,3); List<User> users = session.selectList("org.mybatis.example.BlogMapper.selectBlog"); for (User user : users){ System.out.println(user); } session.close(); inputStream.close(); }
-
-
-
-
<environments>
环境标签-
该标签用于配置数据源
-
<!-- 配置环境 --> <!-- 指定数据源配置, 通过default属性指定要使用的具体的数据源 --> <environments default="mysql"> <!-- 配置mysql的环境 --> <!-- 每一个environment就是一个数据源的配置, 属性id表示当前数据源的唯一标识 --> <environment id="mysql"> <!-- 配置事务类型 --> <!-- transactionManager标签用于指定事务类型, 属性type取值有两个: JDBC: 通过连接connection来实现事务管理; MANAGED: 指定是容器类型的事务, 比如spring提供的事务; --> <transactionManager type="JDBC"/> <!-- 配置数据源(连接池) --> <!-- dataSource用于配置数据源的具体标签, 属性type表示获取连接的方式,取值有三个: POOLED: 指的mybatis操作数据库时通过连接池的方式获取连接; UNPOOLED: 指的是每次操作数据库都通过新建连接的方式获取链接; JNDI: java命名注册接口, 指的是将数据源配置从项目中提取出来配置到TomCat服务器上通过远程固定api获取数据 作用将数据源和项目实现彻底解耦合 --> <dataSource type="POOLED"> <!-- 配置连接数据库的4个基本信息 --> <property name="driver" value="${db.driver}"/> <property name="url" value="${db.url}"/> <property name="username" value="${db.username}"/> <property name="password" value="${db.password}"/> </dataSource> </environment> </environments>
-
-
<databaseldProvider>
数据库厂商标识标签(了解)-
MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的
databaseId
属性。 -
MyBatis 会加载带有匹配当前数据库
databaseId
属性和所有不带databaseId
属性的语句 -
<databaseIdProvider type="DB_VENDOR"> <property name="SQL Server" value="sqlserver"/> <property name="DB2" value="db2"/> <property name="Oracle" value="oracle" /> </databaseIdProvider>
-
-
<mappers>
映射器标签-
该标签用于引入配置映射文件,从而引入配置映射文件中的sql语句
-
使用相对于类路径的资源引用
-
<mappers> <mapper resource="org/mybatis/builder/AuthorMapper.xml"/> <mapper resource="org/mybatis/builder/BlogMapper.xml"/> <mapper resource="org/mybatis/builder/PostMapper.xml"/> </mappers>
-
-
使用完全限定资源定位符(URL)
-
<mappers> <mapper url="file:///var/mappers/AuthorMapper.xml"/> <mapper url="file:///var/mappers/BlogMapper.xml"/> <mapper url="file:///var/mappers/PostMapper.xml"/> </mappers>
-
-
使用映射器接口实现类的完全限定类名
-
必须保证接口和映射配置文件同名且同包
-
<mappers> <mapper class="org.mybatis.builder.AuthorMapper"/> <mapper class="org.mybatis.builder.BlogMapper"/> <mapper class="org.mybatis.builder.PostMapper"/> </mappers>
-
-
将包内的映射器接口实现全部注册为映射器
-
必须保证接口和映射配置文件同名且同包
-
<mappers> <package name="org.mybatis.builder"/> </mappers>
-
-
-
Mybatis映射配置文件
-
<cache>
标签- 该标签的作用是开启mybatis框架的二级缓存
-
<cache-ref>
标签- 该标签的作用引入其他映射配置文件的缓存设置
-
<resultMap>
标签-
该标签专门用于做高级映射,有两个使用场景:
- 当数据库表字段名称和javaBean对象属性名称不一致时,使用映射
- 当多表查询是,做高级映射使用
<resultMap id="userMap" type="com.danny.entity.User"> <id property="id" column="id" javaType="_int"/> <result column="username" property="username"/> <result column="birthday" property="birthday"/> <result column="sex" property="sex"/> <result column="address" property="address"/> </resultMap>
- id:结果映射的唯一表示
-
type:指定查询结果返回的数据类型
-
<id>
:映射主键字段 -
<result>
:用于映射普通字段- 属性:
- property指的是返回数据类型的属性名称; JavaType表示属性类型,可省略
- column指定是查询数据库字段名称jdbcType表示字段标签,可以省略
- 属性:
-
-
-
<sql>
标签-
<!-- sql变量的定义 --> <sql id="selectUser">select id,username,birthday,sex,address from user</sql> <select id="selectAll" resultType="com.danny.entity.User"> <!--include 表示sql语句变量的引用--> <include refid="selectUser"></include> </select>
-
所有查询语句都必须指定返回类型: 指定方式有两种:
- resultType属性指定:默认将数据库中的字段名称和java对象中属性名称相同的属性做映射
- resultMap: 自定义结果映射, 一般用于查询字段名称和返回数据类型字段名称不一致时
-
-
<insert><update><delete><select>
标签- 用于在映射配置文件中定义增删改查sql语句;
- 属性:
- id表示定义的sql语句的唯一标识;
<select>
标签必须指定返回类型- resultType属性指定:默认将数据库中的字段名称和java对象中属性名称相同的属性做映射;
- resultMap: 自定义结果映射, 一般用于查询字段名称和返回数据类型字段名称不一致时;
Mybatis执行原理
-
//定义mybatis主配置文件 String resource = "SqlMapConfig.xml"; //读取mybatis主配置文件,将其读取到输入流中 InputStream inputStream = Resources.getResourceAsStream(resource); //通过配置文件信息构建sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //获取sqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //执行sql语句操作数据库 User user = sqlSession.selectOne("org.mybatis.example.BlogMapper.selectOne"); System.out.println(user); //持久化数据到数据库(提交事务,mybatis默认开启事务) sqlSession.commit(); //关闭sqlSession释放资源 sqlSession.close(); inputStream.close();
基于接口代理的方式操作数据库
-
步骤
-
引入mybatis的jar包
-
创建mybatis的两个配置文件,并配置好主配置文件
-
定义dao层接口
-
package com.danny.dao; import com.danny.entity.User; import org.apache.ibatis.annotations.Select; import java.util.List; /** * 用户的持久层接口 */ public interface IUserDao { /** * 查询所有操作 * @return */ @Select("Select * from user") List<User> findAll(); /** * 新增 * @param user */ void insert(User user); /** * 修改 * @param user */ void update(User user); /** * 删除 * @param id */ void delete(int id); /** * 查询单个 * @param id */ User findUserById(int id); }
-
-
找到对应的映射配置文件,定义接口方法对应的接口语句
- 要保证映射配置文件中namespace属性值和接口的全限定类名一致
-
要保证sql语句的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.danny.dao.IUserDao"> <!-- 基于接口代理方式操作数据库,要保证映射配置文件中namespace属性值和接口的全限定类名一致; 要保证sql语句的id值和接口方法名称一致--> <select id="findUserById" resultType="user"> select id,username,birthday,sex,address from user where id = #{id} </select> <insert id="insert" parameterType="user"> insert into user (id,username,birthday,sex,address) values(default,#{username},#{birthday},#{sex},#{address}) </insert> <update id="update" parameterType="user"> update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id = #{id} </update> <delete id="delete" parameterType="user"> delete from user where id=#{id} </delete> </mapper>
-
使用接口代理对象操作数据库
-
将新增的接口
-
提取工具类操作数据库
-
工具类
-
public class MySqlSessionFactory { private static SqlSessionFactory sqlSessionFactory; private static InputStream in; static { //1.读取配置文件 try { in = Resources.getResourceAsStream("SqlMapConfig.xml"); } catch (IOException e) { e.printStackTrace(); } //2.创建SqlSessionFactory工厂 sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); } public static SqlSessionFactory getSqlSessionFactory(){ return sqlSessionFactory; } }
-
-
测试类
-
public class MybatisTest02 { private IUserDao userDao; private SqlSession session; private InputStream in; @Before public void before() throws IOException { //3.使用工厂生产SqlSession对象 session = MySqlSessionFactory.getSqlSessionFactory().openSession(); //4.使用SqlSession创建Dao接口的代理对象 userDao = session.getMapper(IUserDao.class); } @After public void after() throws IOException { session.commit(); //6.释放资源 session.close(); } @Test public void testFindUserById() throws Exception { //5.使用代理对象执行方法 User user = userDao.findUserById(48); System.out.println(user); } }
-
-
映射文件
-
<?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.danny.dao.IUserDao"> <!-- 基于接口代理方式操作数据库,要保证映射配置文件中namespace属性值和接口的全限定类名一致; 要保证sql语句的id值和接口方法名称一致--> <select id="findUserById" resultType="user"> select id,username,birthday,sex,address from user where id = #{id} </select> </mapper>
-
Mybatis的参数传递
-
单参数传递
- mybatis在传递单个参数时, 映射配置文件中的sql语句占位符中参数名称可以随便写,因为它是根据类型来传递参数的
-
多参数传递
-
最常用的: 多参数传递时, 将多个参数封装到对象中进行传递,mybatis会根据对象属性名来设置占位符中的参数
-
直接传递多个参数, mybatis通过索引来设置sql语句中占位符的参数
-
接口中的方法使用多个参数代替javaBean实体对象
-
sql语句中使用索引
#{arg0}
,#{arg1}
…
-
-
直接传递多个参数, 在每个参数前加上注解
@param
,mybatis可以通过注解名称获取参数名来设置sql语句中占位符的参数 -
将多个参数封装到map集合中进行传递,mybatis会根据map集合中的key值类设置占位符中的参数
-
-
mybatis传参中的
#{}
和${}
-
#{}
, 相当于占位符, 可以防止sql注入 -
${}
, 仅仅相当于字符串, 不能防止sql注入 -
模糊搜索案例:
List<Car> findCarsByCname(String cname); List<Car> findCarsByCname2(@Param("cname") String cname);
<select id="findCarsByCname" resultType="car"> select cid,car_name as carName,car_price as carPrice from car where car_name like concat('%',#{cname},'%') </select> <select id="findCarsByCname2" resultType="car"> select cid,car_name as carName,car_price as carPrice from car where car_name like '%${cname}%' </select>
-
Mybatis中
一对一关系多表查询
-
嵌套结果集方式
-
定义dao层接口
-
public interface IUserOrderDao { /** * * @param uid * @return */ User findUserOrderByUid(int uid); }
-
-
创建对应的映射文件,定义接口方法对应执行的sql语句
-
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.danny.dao.IUserOrderDao"> <!-- 一对一关系多表查询 --> <resultMap id="userOrderResult" type="User"> <id property="id" column="id" javaType="_int"/> <result column="username" property="username"/> <result column="birthday" property="birthday"/> <result column="sex" property="sex"/> <result column="address" property="address"/> <!-- 该标签表示一对一关系表映射 --> <association property="order" javaType="Order"> <id column="id" property="oid"/> <result column="user_id" property="userId"/> <result column="sum_price" property="sumPrice"/> <result column="created_time" property="createdTime"/> <result column="info" property="info"/> </association> </resultMap> <select id="findUserOrderByUid" resultMap="userOrderResult"> SELECT u.id,u.username,u.birthday,u.sex,u.address,o.id,o.user_id,o.sum_price,o.created_time,o.info FROM USER u LEFT JOIN `order` o ON u.id=o.user_id WHERE u.id=1 </select> </mapper>
-
-
使用MybatisAPI操作数据库
-
public class myTest { private SqlSession session; private IUserOrderDao userOrderDao; @Before public void before() throws IOException { //3.使用工厂生产SqlSession对象 session = MySqlSessionFactory.getSqlSessionFactory().openSession(); //4.使用SqlSession创建Dao接口的代理对象 userOrderDao = session.getMapper(IUserOrderDao.class); } @After public void after() throws IOException { //6.释放资源 session.close(); } /** * 一对一关系多表查询 * 嵌套结果集方式 */ @Test public void test1(){ User uu = userOrderDao.findUserOrderByUid(1); System.out.println(uu); } }
-
-
-
嵌套查询方式操作数据库
-
定义dao层接口
-
/** * 嵌套查询方式 * @param uid * @return */ User findUserOrderByUid(long uid);
-
-
找到对应的映射文件,定义接口方法对应执行的sql语句
-
第一步sql语句
-
<!-- 一对一嵌套查询 --> <resultMap id="userOrderResult2" type="user"> <id property="id" column="id" javaType="_int"/> <result column="username" property="username"/> <result column="birthday" property="birthday"/> <result column="sex" property="sex"/> <result column="address" property="address"/> <!--association表示一对一映射表关系 column属性表示传入嵌套查询sql语句的入参; select属性表示下一步嵌套查询的sql语句--> <association property="order" column="id" select="com.danny.dao.OrderDao.findOrderByUid"> </association> </resultMap> <!-- 定义第一步sql语句 --> <select id="findUserOrderByUid2" resultMap="userOrderResult2"> select id,username,birthday,sex,address from user where id = #{id} </select>
-
-
第二步sql语句
-
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.danny.dao.OrderDao"> <resultMap id="orderMap" type="order"> <id column="id" property="oid"/> <result column="user_id" property="userId"/> <result column="sum_price" property="sumPrice"/> <result column="created_time" property="createdTime"/> <result column="info" property="info"/> </resultMap> <select id="findOrderByUid" resultMap="orderMap"> SELECT id,user_id,sum_price,created_time,info FROM `ORDER` WHERE user_id = #{id}; </select> </mapper>
-
-
-
使用MybatisAPI操作数据库
-
/** * 一对一关系多表查询 * 嵌套查询方式 */ @Test public void test2(){ User uu = userOrderDao.findUserOrderByUid2(1); System.out.println(uu); }
-
-
一对多关系多表操作
-
嵌套结果集方式
-
定义dao层接口
-
/** * 嵌套结果集 * @param uid * @return */ List<User> findUserOrdersByUid(int uid);
-
-
使用dao层接口代理处理数据库
-
<!-- 一对多关系多表查询 --> <resultMap id="userOrdersResult" type="User"> <id property="id" column="id" javaType="_int"/> <result column="username" property="username"/> <result column="birthday" property="birthday"/> <result column="sex" property="sex"/> <result column="address" property="address"/> <!-- 该标签表示一对多关系表映射 --> <collection property="orderList" ofType="Order"> <id column="oid" property="oid"/> <result column="user_id" property="userId"/> <result column="sum_price" property="sumPrice"/> <result column="created_time" property="createdTime"/> <result column="info" property="info"/> </collection> </resultMap> <select id="findUserOrdersByUid" resultMap="userOrdersResult"> SELECT u.id,u.username,u.birthday,u.sex,u.address,o.id as oid,o.user_id,o.sum_price,o.created_time,o.info FROM USER u LEFT JOIN `order` o ON u.id=o.user_id WHERE u.id=#{id} </select>
-
-
使用MybatisAPI操作数据库
-
/** * 一对多关系多表查询 * 嵌套结果集方式 */ @Test public void test3(){ List<User> uu = userOrderDao.findUserOrdersByUid(2); System.out.println(uu); }
-
-
-
嵌套查询方式操作数据库
-
定义dao层接口
-
/** * 嵌套查询方式 * @param uid * @return */ List<User> findUserOrdersByUid2(int uid);
-
-
使用dao层接口代理处理数据库
-
第一步sql语句
-
<!-- 一对多嵌套查询 --> <resultMap id="userOrdersResult2" type="user"> <id property="id" column="id" javaType="_int"/> <result column="username" property="username"/> <result column="birthday" property="birthday"/> <result column="sex" property="sex"/> <result column="address" property="address"/> <collection property="orderList" column="id" select="com.danny.dao.OrderDao.findOrdersByUid"> </collection> </resultMap> <!-- 定义第一步sql语句 --> <select id="findUserOrdersByUid2" resultMap="userOrdersResult2"> select id,username,birthday,sex,address from user where id = #{id} </select> </mapper>
-
-
第二步sql语句
-
<select id="findOrdersByUid" resultMap="orderMap"> SELECT id,user_id,sum_price,created_time,info FROM `ORDER` WHERE user_id = #{id}; </select>
-
-
-
使用MybatisAPI操作数据库
-
/** * 一对多关系多表查询 * 嵌套查询方式 */ @Test public void test4(){ List<User> uu = userOrderDao.findUserOrdersByUid2(2); System.out.println(uu); }
-
-
多对多关系多表操作
-
嵌套结果集方式
-
定义dao层接口
-
public interface IUserOrderItemDao { /** * 根据用户id获取用户订单商品信息(嵌套结果集方式) * @param uid * @return */ List<User> findUserOrderItemByUid(int uid); }
-
-
使用dao层接口代理处理数据库
-
<!-- 多对多嵌套结果集方式 --> <resultMap id="userOrdersItemsResult" type="User"> <id property="id" column="id" javaType="_int"/> <result column="username" property="username"/> <result column="birthday" property="birthday"/> <result column="sex" property="sex"/> <result column="address" property="address"/> <collection property="orderList" ofType="Order"> <id column="oid" property="oid"/> <result column="user_id" property="userId"/> <result column="sum_price" property="sumPrice"/> <result column="created_time" property="createdTime"/> <result column="info" property="info"/> <association property="item" javaType="item"> <result column="order_id" property="orderId"/> <result column="product_id" property="productId"/> <result column="purchase_num" property="purchaseNum"/> <collection property="productList" ofType="product"> <id column="pid" property="id"/> <result column="name" property="name"/> <result column="price" property="price"/> <result column="info" property="info"/> <result column="created_time" property="createTime"/> </collection> </association> </collection> </resultMap> <select id="findUserOrderItemByUid" resultMap="userOrdersItemsResult"> SELECT u.id,u.username,u.birthday,u.sex,u.address,o.id as oid,o.user_id,o.sum_price,o.created_time,o.info,i.order_id,i.product_id,i.purchase_num,p.id as pid,p.name,p.price,p.info,p.created_time FROM USER u LEFT JOIN `order` o ON u.id=o.user_id LEFT JOIN `order_item` i ON o.id=i.order_id LEFT JOIN `product` p ON i.product_id=p.id WHERE u.id=#{id} </select>
-
-
使用MybatisAPI操作数据库
-
/** * 多对多关系多表查询 * 嵌套结果集方式 */ @Test public void test5(){ List<User> uu = userOrderItemDao.findUserOrderItemByUid(2); System.out.println(uu); }
-
-
-
嵌套查询方式操作数据库
-
定义dao层接口
-
/** * 根据用户id获取用户订单商品信息(嵌套查询) * @param uid * @return */ List<User> findUserOrderItemByUid2(int uid);
-
-
使用dao层接口代理处理数据库
-
第一步sql语句
-
<!-- 多对多嵌套查询方式 --> <resultMap id="userOrdersItemsResult2" type="user"> <id property="id" column="id" javaType="_int"/> <result column="username" property="username"/> <result column="birthday" property="birthday"/> <result column="sex" property="sex"/> <result column="address" property="address"/> <collection property="orderList" column="id" select="com.danny.dao.OrderDao.findOrdersByUid2"> </collection> </resultMap> <!-- 定义第一步sql语句 --> <select id="findUserOrderItemByUid2" resultMap="userOrdersItemsResult2"> select id,username,birthday,sex,address from user where id = #{id} </select>
-
-
第二步sql语句
-
<!--多对多嵌套方法2--> <resultMap id="orderMaps" type="order"> <id column="id" property="oid"/> <result column="user_id" property="userId"/> <result column="sum_price" property="sumPrice"/> <result column="created_time" property="createdTime"/> <result column="info" property="info"/> <association property="item" column="id" select="com.danny.dao.ItemDao.findItemByOid"></association> </resultMap> <select id="findOrdersByUid2" resultMap="orderMaps"> SELECT id,user_id,sum_price,created_time,info FROM `ORDER` WHERE user_id = #{id}; </select>
-
-
第三步sql语句
-
<mapper namespace="com.danny.dao.ItemDao"> <resultMap id="itemResult" type="item"> <result column="order_id" property="orderId"/> <result column="product_id" property="productId"/> <result column="purchase_num" property="purchaseNum"/> <collection property="productList" column="product_id" select="com.danny.dao.ProductDao.findProductsByPid"> </collection> </resultMap> <select id="findItemByOid" resultMap="itemResult"> SELECT order_id,product_id,purchase_num FROM order_item WHERE order_id= #{id} </select> </mapper>
-
-
第四步sql语句
-
<mapper namespace="com.danny.dao.ProductDao"> <resultMap id="productResult" type="product"> <id column="id" property="id"/> <result column="name" property="name"/> <result column="price" property="price"/> <result column="info" property="info"/> <result column="created_time" property="createTime"/> </resultMap> <select id="findProductsByPid" resultMap="productResult"> SELECT id,NAME,price,info,created_time FROM product WHERE id = #{id} </select> </mapper>
-
-
-
使用MybatisAPI操作数据库
-
/** * 多对多关系多表查询 * 嵌套结果集方式 */ @Test public void test6(){ List<User> uu = userOrderItemDao.findUserOrderItemByUid2(2); System.out.println(uu); }
-
-
新增返回主键值
-
通过设置属性
useGeneratedKeys
返回主键-
<!--新增返回主键值: useGeneratedKeys表示是否设置新增返回主键id; keyproperty属性表示新增返回的主键值的具体位置--> <insert id="insertOrders" useGeneratedKeys="true" keyProperty="oid"> insert into orders (pid,order_name) values(#{pid},#{orderName}) </insert>
-
-
通过
selectKey
标签返回主键-
<insert id="insertOrders" > <selectKey resultType="_long" keyProperty="oid"> SELECT LAST_INSERT_ID() </selectKey> insert into orders (pid,order_name) values(#{pid},#{orderName}) </insert>
-
Mybatis下
Mybatis的动态sql
- Mybatis中的动态sql语句用于在xml文件中动态的拼接sql语句,可以自动的删除多余的前缀或者后缀,如逗号后缀and符号等,作用降低拼接sql语句的复杂程度,提高开发效率
<if>
动态sql标签
-
if动态标签就相当于java中的if关键字,作用用于在sql语句中做条件判断
-
示例
-
<select id="findProductsByOrderConditionWithIf" resultMap="productResult"> <include refid="selectProduct"></include> <if test="'price'.equals(orderCondition)"> order by price </if> <if test="'id'.equals(orderCondition)"> order by id </if> <if test="'name'.equals(orderCondition)"> order by name </if> </select>
-
<where>
动态sql标签
-
where动态标签相当于sql语句中的where关键字,除了可以添加限制条件以外,还可以自动删除多余的前缀and符号; 通常搭配if动态标签使用,当if条件不成立时,自动删除多余前缀and符号
-
示例
-
<select id="findProductsByConditionWithWhere" resultMap="productResult"> <include refid="selectProduct"></include> <where> <if test="name!=null"> name like concat('%',#{name},'%') </if> <if test="price>0"> and price <![CDATA[<]]>#{price} </if> </where> </select>
-
<choose>
<when>
<otherwise>
动态标签
-
该标签相当于java中的switch case default 用于条件判断,可以用该动态标签替换上面的if+where动态标签
-
示例
-
<select id="findProductsByOrderCondition" resultMap="productResult"> <include refid="selectProduct"></include> <choose> <when test="'price'.equals(orderCondition)"> order by price </when> <when test="'name'.equals(orderCondition)"> order by name </when> <otherwise> order by id </otherwise> </choose> </select>
-
<set>
动态标签
-
set动态标签相当于sql语句中的set关键字,用于修改sql语句,除了修改以外,还可以自己删除多余的逗号,通常搭配id动态标签使用,当if条件成立时,删除多余逗号
-
示例
-
<update id="updateProduct"> update product <set> <if test="name!=null"> name=#{name}, </if> <if test="price>0"> price=#{price}, </if> </set> where id=#{id} </update>
-
<trim>
动态标签
- trim动态标签可以替换where动态标签和set动态标签,作用可以自动的添加前缀或者后缀,可以自动删除前缀后缀后缀
- trim动态标签提供了四个属性
-
prefix
- 用于指定自动增加的前缀
-
prefixOverrides
- 用于指定自动删除的前缀
-
suffix
- 用于指定自动增加的后缀
-
suffixOverrides
- 用于指定自动删除的前缀
-
示例
-
<update id="updateProduct2"> update product <trim prefix="set" suffixOverrides=","> <if test="name!=null"> name=#{name}, </if> <if test="price>0"> price=#{price}, </if> </trim> where id=#{id} </update>
-
-
<foreach>
动态标签
-
相当于java中的for循环,用于sql语句中的迭代集合或者数组
-
foreach标签迭代集合或者数组,拼接批量操作sql语句
- collection:
- 表示要迭代的集合或者数组
- 如果传入参数是单个参数,那么根据类型来取参数
- 如果传入多个参数,那么根据多个参数传递规则获取参数
- 表示要迭代的集合或者数组
- open:
- 表示要迭代sql语句的前面部分
- close:
- 表示要迭代sql语句的后面部分
- item:
- 表示要迭代的集合或者数组中每一个元素为其定义的变量名
- separator:
- 表示要迭代的元素之间的分隔符
- collection:
-
示例
-
<select id="findProductsByPid" resultMap="productResult"> SELECT id,NAME,price,info,created_time FROM product where id in <foreach collection="array" open="(" close=")" item="pid" separator=","> #{pid} </foreach> </select>
-
具体案例
- https://mybatis.org/mybatis-3/zh/dynamic-sql.html
Mybatis懒加载
-
mybatis的懒加载又叫做按需加载或者延迟加载,根据需要去加载,需要就加载,不需要就不加载
- 需要: 指的是用户的需求
- 加载: 指的是加载要执行的sql语句
注意: mybatis懒加载使用的前提,必须要有嵌套查询sql语句
-
好处:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。
-
坏处: 因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗 时间,所以可能造成用户等待时间变长,造成用户体验下降。
-
懒加载的使用(主配置文件)
-
全局懒加载设置
-
放
<properties>
标签后面 -
<settings> <setting name="lazyLoadingEnabled" value="true"/> </settings>
-
-
局部懒加载设置
- mybatis提供了两个标签
<association>
和<collection>
里面有个属性fetchType可以设置局部懒加载fetchType=lazy
开启懒加载fetchType=eager
关闭懒加载
- 注意局部懒加载优先级高于全局懒加载
- mybatis提供了两个标签
-
Mybatis的缓存机制
- 缓存:指的是一块内存空间用于存储大量频繁访问的数据,当用户第一次读取数据库中的数据库时,会将这些数据查询出来存放到该内存空间中(缓存中),当用户再次获取同样的数据时,可以直接从内存中返回,而不用再去数据库中读取,从而提高查询效率;
- 注意:每一次的新增,修改,删除数据库数据后悔导致缓存清空,除此之外mybatis提供了手动清空缓存的方法
clearCache()
- mybatis提供了两种缓存机制一级缓存和二级缓存机制
一级缓存
- mybatis默认支持一级缓存
- 一级缓存是 SqlSession 级别的缓存,只要 SqlSession 没有 flush 或 close,它就存在。
- 一级缓存的作用范围(生命周期)
- 随着sqlSession的创建而创建
- 随着sqlSession的销毁而销毁
二级缓存
- mybatis二级缓存的使用需要自己设置
- 二级缓存的作用范围在一个mapper映射配置文件中
- 二级缓存的生命周期
- 随着sqlSessionFactory的创建而创建
- 随着sqlSessionFactory的销毁而销毁
- 多个用户共享这个缓存(跨sqlSession的缓存)
- 二级缓存设置
- 开启缓存,默认就是开启的
- 在要开启二级缓存的mapper文件中加二级缓存设置
<cache>
- 具体配置了解:详见官方文档
逆向工程
-
步骤
-
引入mybatis逆向工程jar包
-
<dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.5</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency>
-
-
配置逆向工程的配置文件
-
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <!-- context 是逆向工程的主要配置信息 --> <!-- id:起个名字 --> <!-- targetRuntime:设置生成的文件适用于那个 mybatis 版本 --> <context id="default" targetRuntime="MyBatis3"> <!--optional,指在创建class时,对注释进行控制--> <commentGenerator> <property name="suppressDate" value="true"/> <!-- 是否去除自动生成的注释 true:是 : false:否 --> <property name="suppressAllComments" value="true"/> </commentGenerator> <!--jdbc的数据库连接 wg_insert 为数据库名字--> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/db_mybatis_orders?useUnicode=true&characeterEncoding=utf-8&serverTimezone=UTC" userId="root" password="root"/> <!--非必须,类型处理器,在数据库类型和java类型之间的转换控制--> <javaTypeResolver> <!-- 默认情况下数据库中的 decimal,bigInt 在 Java 对应是 sql 下的 BigDecimal 类 --> <!-- 不是 double 和 long 类型 --> <!-- 使用常用的基本类型代替 sql 包下的引用类型 --> <property name="forceBigDecimals" value="false"/> </javaTypeResolver> <!-- targetPackage:生成的实体类所在的包 --> <!-- targetProject:生成的实体类所在的硬盘位置 --> <javaModelGenerator targetPackage="com.danny.bean" targetProject="src/main/java"> <!-- 是否允许子包 --> <property name="enableSubPackages" value="true"/> <!-- 是否对modal添加构造函数 --> <property name="constructorBased" value="true"/> <!-- 是否清理从数据库中查询出的字符串左右两边的空白字符 --> <property name="trimStrings" value="true"/> <!-- 建立modal对象是否不可改变 即生成的modal对象不会有setter方法,只有构造方法 --> <property name="immutable" value="false"/> </javaModelGenerator> <!-- targetPackage 和 targetProject:生成的 mapper 文件的包和位置 --> <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"> <!-- 针对数据库的一个配置,是否把 schema 作为字包名 --> <property name="enableSubPackages" value="true"/> </sqlMapGenerator> <!-- targetPackage 和 targetProject:生成的 interface 文件的包和位置 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.danny.dao" targetProject="src/main/java"> <!-- 针对 oracle 数据库的一个配置,是否把 schema 作为字包名 --> <property name="enableSubPackages" value="true"/> </javaClientGenerator> <!-- tableName是数据库中的表名,domainObjectName是生成的JAVA模型名,后面的参数不用改,要生成更多的表就在下面继续加table标签 --> <!-- <table tableName="student" domainObjectName="Student"--> <!-- enableCountByExample="false" enableUpdateByExample="false"--> <!-- enableDeleteByExample="false" enableSelectByExample="false"--> <!-- selectByExampleQueryId="false"></table>--> <table tableName="user"/> <table tableName="order"/> <table tableName="order_item"/> <table tableName="item"/> </context> </generatorConfiguration>
-
-
使用逆向工程API运行
-
import org.junit.Test; import org.mybatis.generator.api.MyBatisGenerator; import org.mybatis.generator.config.Configuration; import org.mybatis.generator.config.xml.ConfigurationParser; import org.mybatis.generator.internal.DefaultShellCallback; import java.io.File; import java.util.ArrayList; import java.util.List; public class testGenerator { @Test public void testBuild() throws Exception { List<String> warnings = new ArrayList<String>(); boolean overwrite = true; File configFile = new File("src/mybatisGenerator.xml"); ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = cp.parseConfiguration(configFile); DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(null); } }
-
-
逆向工程方法总结
- mapper接口中的方法解析
- mapper接口中的部分常用方法及功能如下:
方法 | 功能说明 |
---|---|
int countByExample(UserExample example) thorws SQLException | 按条件计数 |
int deleteByPrimaryKey(Integer id) thorws SQLException | 按主键删除 |
int deleteByExample(UserExample example) thorws SQLException | 按条件删除 |
String/Integer insert(User record) thorws SQLException | 插入数据(返回值为ID) |
User selectByPrimaryKey(Integer id) thorws SQLException | 按主键查询 |
ListselectByExample(UserExample example) thorws SQLException | 按条件查询 |
ListselectByExampleWithBLOGs(UserExample example) thorws SQLException | 按条件查询(包括BLOB字段)。只有当数据表中的字段类型有为二进制的才会产生 |
int updateByPrimaryKey(User record) thorws SQLException | 按主键更新 |
int updateByPrimaryKeySelective(User record) thorws SQLException | 按主键更新值不为null的字段 |
int updateByExample(User record, UserExample example) thorws SQLException | 按条件更新 |
int updateByExampleSelective(User record, UserExample example) thorws SQLException | 按条件更新值不为null的字段 |
- Example类解析
- mybatis的逆向工程中会生成实体类及实体类对应的example类,example类用于添加条件,相当where后面的部分。
- xxxExample example = new xxxExample();
- Criteria criteria = new Example().createCriteria();
- example类中的部分常用方法及功能如下:
方法 | 功能说明 |
---|---|
example.setOrderByClause(“字段名 ASC”); | 添加升序排列条件,DESC为降序 |
example.setDistinct(false) | 去除重复,boolean型,true为选择不重复的记录 |
criteria.andXxxIsNull | 添加字段xxx为null的条件 |
criteria.andXxxIsNotNull | 添加字段xxx不为null的条件 |
criteria.andXxxEqualTo(value) | 添加xxx字段等于value条件 |
criteria.andXxxNotEqualTo(value) | 添加xxx字段不等于value条件 |
criteria.andXxxGreaterThan(value) | 添加xxx字段大于value条件 |
criteria.andXxxGreaterThanOrEqualTo(value) | 添加xxx字段大于等于value条件 |
criteria.andXxxLessThan(value) | 添加xxx字段小于value条件 |
criteria.andXxxLessThanOrEqualTo(value) | 添加xxx字段小于等于value条件 |
criteria.andXxxIn(List<?>) | 添加xxx字段值在List<?>条件 |
criteria.andXxxNotIn(List<?>) | 添加xxx字段值不在List<?>条件 |
criteria.andXxxLike(“%”+value+”%”) | 添加xxx字段值为value的模糊查询条件 |
criteria.andXxxNotLike(“%”+value+”%”) | 添加xxx字段值不为value的模糊查询条件 |
criteria.andXxxBetween(value1,value2) | 添加xxx字段值在value1和value2之间条件 |
criteria.andXxxNotBetween(value1,value2) | 添加xxx字段值不在value1和value2之间条件 |
- 注:在mybatis逆向工程生成的文件XxxExample.java中包含一个static的内部类Criteria,Criteria中的方法是定义SQL 语句where后的查询条件。
- 总结
- XxxExample.java只能实现简单条件增删改查,复杂的功能还需要自己编写sql代码来实现。
Mybatis注解配置
-
以下注解都是在接口方法上配置
- @Insert : 插入sql , 和xml insert sql语法完全一样
- @Select : 查询sql, 和xml select sql语法完全一样
- @Update : 更新sql, 和xml update sql语法完全一样
- @Delete : 删除sql, 和xml delete sql语法完全一样
- @Param : 入参
- @Results:该注解相当于xml中的
<resultMap>
标签,用于自定义结果映射; - @Result:该注解相当于xml中的
<result>
标签,用于字段映射; - @One:该注解相当于xml中的
<association>
标签,用于一对一表映射; - @Many:该注解相当于xml中的
<collection>
标签,用于一对多表映射;
-
@SelectProvider: 实现动态 SQL 映射
- @CacheNamespace:实现注解二级缓存的使用
-
单表增删改查
-
定义dao层接口以及对应的sql语句
-
/** * 新增 * @param user */ @Insert("insert into user (id,username,birthday,sex,address) values(default,#{username},#{birthday},#{sex},#{address})") void insert2(User user); /** * 修改 * @param user */ @Update("update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}") void update2(User user); /** * 删除 * @param id */ @Delete("delete from user where id=#{id}") void delete2(int id); /** * 查询单个 * @param id */ @Select("select id,username,birthday,sex,address from user where id=#{id}") User findUserById2(int id); /** * 查询所有操作 * @return */ @Select("Select id,username,birthday,sex,address from user") List<User> findAll();
-
-
将接口注册到mybatis主配置文件中
-
<mappers> <mapper class="com.danny.dao.UserDao"/> </mappers>
-
-
-
多表操作
-
一对一查询
-
@Results({ @Result(column = "pid",property = "pid"), @Result(column = "pname",property = "pname"), @Result(column = "paddress",property = "paddress"), @Result(column = "hire_date",property = "hireDate"), @Result(property = "car",column = "pid", one=@One(select = "com.offcn.dao.CarDao.findCarByPid",fetchType = FetchType.LAZY)) }) @Select("select pid,pname,paddress,hire_date from person where pid=#{pid}") Person findPersonCarByPid(long pid);
-
-
一对多查询
-
@Results({ @Result(column = "pid",property = "pid"), @Result(column = "pname",property = "pname"), @Result(column = "paddress",property = "paddress"), @Result(column = "hire_date",property = "hireDate"), @Result(property = "ordersList",column = "pid", many=@Many(select = "com.offcn.dao.OrdersDao.findOrdersByPid")) }) @Select("select pid,pname,paddress,hire_date from person where pid=#{pid}") Person findPersonOrdersByPid(long pid);
-
-
复杂关系注解映射
-
@Results 注解
- 代替的是标签
<resultMap>
- 该注解中可以使用单个@Result 注解,也可以使用@Result 集合
- @Results({@Result(), @Result()}) 或 @Results(@Result())
- 代替的是标签
-
@Resutl 注解
- 代替了
<id>
标签和<result>
标签 - @Result 中 属性介绍:
- id 是否是主键字段
- column 数据库的列名
- property 需要装配的属性名
- one 需要使用的@One 注解(@Result(one=@One)()))
- many 需要使用的@Many 注解(@Result(many=@many)()))
- 代替了
-
@One 注解(一对一)
- 代替了
<assocation>
标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。 - @One 注解属性介绍:
- select 指定用来多表查询的 sqlmapper
- fetchType 会覆盖全局的配置参数 lazyLoadingEnabled。。
- 使用格式:
- @Result(column=" “,property=”",one=@One(select=""))
- 代替了
-
@Many 注解(多对一)
- 代替了
<Collection>
标签,是是多表查询的关键,在注解中用来指定子查询返回对象集合。 - 注意:
- 聚集元素用来处理“一对多”的关系。需要指定映射的 Java 实体类的属性,属性的 javaType
(一般为 ArrayList)但是注解中可以不定义;
- 聚集元素用来处理“一对多”的关系。需要指定映射的 Java 实体类的属性,属性的 javaType
- 使用格式:
- @Result(property="",column="",many=@Many(select=""))
- 代替了