[!note]
以下内容介绍Mybatis的XML映射文件的配置
顶级元素
SQL 映射文件只有很少的几个顶级元素(按照应被定义的顺序列出):
cache
– 该命名空间的缓存配置。cache-ref
– 引用其它命名空间的缓存配置。resultMap
– 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。parameterMap
– 老式风格的参数映射。此元素已被废弃,并可能在将来被移除!请使用行内参数映射。文档中不会介绍此元素。sql
– 可被其它语句引用的可重用语句块。insert
– 映射插入语句。update
– 映射更新语句。delete
– 映射删除语句。select
– 映射查询语句。
select
<select id="selectByUserId" parameterType="int" resultType="User"> select * from user where id = #{id} select>
id:用来标识根dao接口中匹配的方法,必须与方法的名字一一对应。
parameterType:表示执行该sql需要传入的参数#{id}的类型为int或者Integer
resultType:表示该sql语句执行后的返回值为User类型。该属性只能返回单一的对象,关联查询时需要自定义结果集。当返回的结果是一个集合时,并不需要使用属性resultMap,只需要使用resultType指定集合中的元素类型即可。例如:
<select id="selectAll" resultType="Emp"> select * from emp select>[Emp{empno=1111, ename='zhangsan', job='null', mgr=null, hiredate=null, sal=6666.67, comm=null, deptno=null}, Emp{empno=2222, ename='hhh', job='null', mgr=null, hiredate=null, sal=1500.0, comm=null, deptno=null}, Emp{empno=3333, ename='wangwu', job='null', mgr=null, hiredate=null, sal=4000.0, comm=null, deptno=null}]
select元素的所有属性
select除了以上常用的几个属性外,还有其他属性:
属性 | 描述 |
---|---|
id | 在命名空间中唯一的标识符,可以被用来引用这条语句。 |
parameterType | 将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。 |
parameterMap | 用于引用外部 parameterMap 的属性,目前已被废弃。请使用行内参数映射和 parameterType 属性。 |
resultType | 期望从这条语句中返回结果的类全限定名或别名。注意,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。resultType 和 resultMap 之间只能同时使用一个。 |
resultMap | 对外部 resultMap 的命名引用。结果映射是 MyBatis最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。resultType 和 resultMap 之间只能同时使用一个。 |
flushCache | 用来标识当前sql语句的结果是否进入二级缓存。将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false。 |
useCache | 将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true。 |
timeout | 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。 |
fetchSize | 这是一个给驱动的建议值,尝试让驱动程序每次批量返回的结果行数等于这个设置值。默认值为未设置(unset)(依赖驱动)。 |
statementType | 可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。 |
resultSetType | FORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等价于 unset) 中的一个,默认值为 unset (依赖数据库驱动)。 |
databaseId | 如果配置了数据库厂商标识(databaseIdProvider),MyBatis会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。 |
resultOrdered | 这个设置仅针对嵌套结果 select 语句:如果为true,将会假设包含了嵌套结果集或是分组,当返回一个主结果行时,就不会产生对前面结果集的引用。这就使得在获取嵌套结果集的时候不至于内存不够用。默认值:false 。 |
resultSets | 这个设置仅适用于多结果集的情况。它将列出语句执行后返回的结果集并赋予每个结果集一个名称,多个名称之间以逗号分隔。 |
例如:
<select id="selectPerson" parameterType="int" parameterMap="deprecated" resultType="hashmap" resultMap="personResultMap" flushCache="false" useCache="true" timeout="10" fetchSize="256" statementType="PREPARED" resultSetType="FORWARD_ONLY">
insert、update和delete
insert、update以及delete三个元素的基础用法:
<insert id="save" > insert into emp(empno,ename) values(#{empno},#{ename}) insert> <update id="update"> update emp set sal=#{sal} where empno = #{empno} update> <delete id="delete"> delete from emp where empno = #{empno} delete>
insert、update以及delete三个元素的属性如下:
属性 | 描述 |
---|---|
id | 在命名空间中唯一的标识符,可以被用来引用这条语句。 |
parameterType | 将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。 |
parameterMap | 用于引用外部 parameterMap 的属性,目前已被废弃。请使用行内参数映射和 parameterType 属性。 |
flushCache | 用来标识当前sql语句的结果是否进入二级缓存。将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:(对 insert、update 和 delete 语句)true。 |
timeout | 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。 |
statementType | 用来选择执行sql语句的方式。statement:基本的jdbc操作,用来表示一个sql语句,不能防止sql注入 PREPARED:采用预编译的方式,能够防止sql注入,设置参数的时候需要该对象来进行设置 CALLABLE:调用存储过程。可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。 |
useGeneratedKeys | (仅适用于 insert 和 update)完成插入或更新操作时,可以将自增生成的主键值返回到具体的对象属性中。需要配合属性keyProperty使用:指定返回的主键要赋值到哪个对象属性中。这会令 MyBatis 使用 JDBC 的getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false。 |
keyProperty | (仅适用于 insert 和 update)指定能够唯一识别对象的属性,MyBatis 会使用getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset )。如果生成列不止一个,可以用逗号分隔多个属性名称。 |
keyColumn | (仅适用于 insert 和 update)设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。 |
databaseId | 如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。 |
例如:
<insert id="insertAuthor" parameterType="domain.blog.Author" flushCache="true" statementType="PREPARED" keyProperty="" keyColumn="" useGeneratedKeys="" timeout="20"><update id="updateAuthor" parameterType="domain.blog.Author" flushCache="true" statementType="PREPARED" timeout="20"><delete id="deleteAuthor" parameterType="domain.blog.Author" flushCache="true" statementType="PREPARED" timeout="20">
以上useGeneratedKeys
属性的用法:插入数据后将生成的主键赋值给user对象的id字段,即 keyProperty="id"
<insert id="saveUser" useGeneratedKeys="true" keyProperty="id"> insert into user(user_name) values(#{userName})insert>
sql获取参数值
创建表:
CREATE TABLE `emp` (`empno` int(5) NOT NULL,`ename` varchar(20) DEFAULT NULL,`job` varchar(20) DEFAULT NULL,`mgr` int(20) DEFAULT NULL,`hiredate` datetime(6) DEFAULT NULL,`sal` double(20,2) DEFAULT NULL,`comm` double(20,0) DEFAULT NULL,`deptno` int(10) DEFAULT NULL,PRIMARY KEY (`empno`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;
mybatis-config.xml配置文件:
<?xml version="1.0" encoding="UTF-8" ?>/span> PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration> <properties resource="db.properties">properties> <settings> <setting name="mapUnderscoreToCamelCase" value="true"/> settings> <typeAliases> <package name="com.fan.bean"/> typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> dataSource> environment> environments> <mappers> <package name="com.fan.dao"/> mappers>configuration>
[!tip]
sql获取参数值的方式:#{}或者${}
使用#{}获取参数值时执行的sql:select * from emp where empno = ?
EmpDao.xml映射文件:
<?xml version="1.0" encoding="UTF-8" ?>/span> PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.fan.dao.EmpDao"><select id="selectEmpByEmpno" resultType="Emp"> select * from emp where empno = #{empno} select>mapper>
实体类:
package com.fan.bean;import java.util.Date;/*** @Description* @Author 1966659927@qq.com* @Date 2020-11-02 15:05* @Version 1.0* @Project mybatis_helloworld**/public class Emp { private Integer empno; private String ename; private String job; private Integer mgr; private Date hiredate; private Double sal; private Double comm; private Integer deptno; public Integer getEmpno() { return empno; } public void setEmpno(Integer empno) { this.empno = empno; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public String getJob() { return job; } public void setJob(String job) { this.job = job; } public Integer getMgr() { return mgr; } public void setMgr(Integer mgr) { this.mgr = mgr; } public Date getHiredate() { return hiredate; } public void setHiredate(Date hiredate) { this.hiredate = hiredate; } public Double getSal() { return sal; } public void setSal(Double sal) { this.sal = sal; } public Double getComm() { return comm; } public void setComm(Double comm) { this.comm = comm; } public Integer getDeptno() { return deptno; } public void setDeptno(Integer deptno) { this.deptno = deptno; } @Override public String toString() { return "Emp{" + "empno=" + empno + ", ename='" + ename + '\'' + ", job='" + job + '\'' + ", mgr=" + mgr + ", hiredate=" + hiredate + ", sal=" + sal + ", comm=" + comm + ", deptno=" + deptno + '}'; }}
DAO层接口:
package com.fan.dao;import com.fan.bean.Emp;/*** @Description* @Author 1966659927@qq.com* @Date 2020-11-02 15:12* @Version 1.0* @Project mybatis_helloworld**/public interface EmpDao { public Emp selectEmpByEmpno(Integer empno); }
测试类:
?> 为了不必要的内容冗余,后面不再给出整体类,只给出相关测试方法
import com.fan.bean.Emp;import com.fan.dao.EmpDao;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import org.junit.Before;import org.junit.FixMethodOrder;import org.junit.Test;import org.junit.runner.OrderWith;import org.junit.runners.MethodSorters;/*** @Description* @Author 1966659927@qq.com* @Date 2020-11-02 15:25* @Version 1.0* @Project mybatis_helloworld**/public class MyTest { SqlSessionFactory sqlSessionFactory = null; /* * 在测试方法之前执行 * */ @Before public void init() throws IOException { //通过xml创建一个SqlSessionFactory。SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,因此 SqlSessionFactory 的最佳作用域是应用作用域。 String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void testSelect() throws IOException { SqlSession sqlSession = sqlSessionFactory.openSession(); EmpDao mapper = sqlSession.getMapper(EmpDao.class); //执行具体的sql Emp emp = mapper.selectEmpByEmpno(1111); System.out.println(emp); //关闭数据库会话,保证每次请求都是创建了一个本次请求的新会话,避免造成数据混乱 sqlSession.close(); }}
测试结果:
DEBUG [main] - ==> Preparing: select * from emp where empno = ?DEBUG [main] - ==> Parameters: 1111(Integer)
使用?{}获取参数值时执行的sql:select * from emp where empno = 1111
<select id="selectEmpByEmpno" resultType="Emp"> select * from emp where empno = ${empno} select>
测试类:同上
DAO层接口:同上
测试结果:
DEBUG [main] - ==> Preparing: select * from emp where empno = 1111DEBUG [main] - ==> Parameters:
通过以上两个结果执行的sql语句可以看出:#{}的处理方式是使用了参数预编译的方式,不会引起sql注入的问题。
${}的处理方式是直接拼接sql语句,会有sql注入的风险。
当sql需要动态的获取表名、列名时就需要使用${}来拼接sql。
<select id="selectEmpByEmpno" resultType="Emp"> select * from ${arg0} where empno = #{arg1} select>
DAO层接口:
public Emp selectEmpByEmpno(String table, Integer empno);
测试方法中调用时传入相应的表名称即可:
Emp emp = mapper.selectEmpByEmpno("emp", 1111);
sql获取多参数值
?> 当查询语句包含多个参数时,如何获取需要的参数?
1、如果是单个参数: 基本数据类型:可以使用#{}随便获取,即#{}中的参数名可以不是对象属性名,可以随意指定
<select id="selectEmpByEmpno" resultType="Emp"> select * from emp where empno = #{aaa}select>
测试同上
引用数据类型:使用#{}获取值时必须使用对象的属性名
<select id="selectEmpByEmpnoAndSal" resultType="Emp"> select * from emp where empno = #{empno} and sal > #{sal} select>
DAO层接口:
public List<Emp> selectEmpByEmpnoAndSal(Emp emp);
测试方法:注意传给接口的是一个引用类型Emp对象,此时sql在获取该对象中属性值时就必须使用对象的属性名
@Test public void test_selectEmpByEmpnoAndSal(){ SqlSession sqlSession = sqlSessionFactory.openSession(); EmpDao mapper = sqlSession.getMapper(EmpDao.class); Emp emp = new Emp(); emp.setEmpno(2222); emp.setSal(500.0); List<Emp> emps = mapper.selectEmpByEmpnoAndSal(emp); System.out.println(emps); sqlSession.close(); }
2、如果是多个参数:此时需要使用、{arg1}、、{param1}...来获取参数 原因在于,mybatis在传入多个参数时,会将这些参数的结果封装到map中,在map中key值就是(arg0,arg1,...), (param1,param2,...),这种方式无法根据属性名来获取具体的参数值。
<select id="selectEmpByEmpnoAndSal2" resultType="Emp"> select * from emp where empno = ${arg0} and sal > ${arg1} select>
如果想要使用参数的方式获取值,可以在dao接口方法的参数加上注解@Param("参数名")。
<select id="selectEmpByEmpnoAndSal2" resultType="Emp"> select * from emp where empno = #{empno} and sal > #{sal} select>
DAO层接口:
public List<Emp> selectEmpByEmpnoAndSal2(@Param("empno") Integer empno, @Param("sal") Double sal);
测试方法:
@Test public void test_selectEmpByEmpnoAndSal2(){ SqlSession sqlSession = sqlSessionFactory.openSession(); EmpDao mapper = sqlSession.getMapper(EmpDao.class); List<Emp> emps = mapper.selectEmpByEmpnoAndSal2(2222,500.0); System.out.println(emps); sqlSession.close(); }
3、将参数包装成map传入sql,sql将自动解析map获取参数
<select id="selectEmpByEmpnoAndSal3" resultType="Emp"> select * from emp where empno = #{empno} and sal > #{sal}select>
DAO层接口:
public List<Emp> selectEmpByEmpnoAndSal3(Map<String, Object> map);
@Test public void test_selectEmpByEmpnoAndSal3(){ SqlSession sqlSession = sqlSessionFactory.openSession(); EmpDao mapper = sqlSession.getMapper(EmpDao.class); Map<String,Object> map = new HashMap<String, Object>(); map.put("empno", 2222); map.put("sal", 500.0); List<Emp> emps = mapper.selectEmpByEmpnoAndSal3(map); System.out.println(emps); sqlSession.close(); }
resultType与resultMap
resultType
resultType:表示返回的结果类型,一般使用的并不多,该属性只能返回单一的对象,关联查询时需要自定义结果集。 当返回的结果是一个集合时,并不需要使用属性resultMap,只需要使用resultType指定集合中的元素类型即可
<select id="selectAll" resultType="Emp"> select * from emp select> <select id="selectAll2" resultType="Emp"> select * from emp select> <select id="selectEmpByEmpno_1" resultType="map"> select * from emp where empno = #{empno} select>
DAO层接口:
public Map<Object, Object> selectEmpByEmpno_1(Integer empno); public List<Emp> selectAll(); @MapKey("ename")//代表该字段将作为结果的key,Emp将作为value public Map<String, Emp> selectAll2();
测试方法:
@Test public void testSelectAll(){ SqlSession sqlSession = sqlSessionFactory.openSession(true); EmpDao mapper = sqlSession.getMapper(EmpDao.class); List<Emp> emps = mapper.selectAll(); System.out.println(emps); sqlSession.close(); } @Test public void test_selectEmpByEmpno_1(){ SqlSession sqlSession = sqlSessionFactory.openSession(); EmpDao mapper = sqlSession.getMapper(EmpDao.class); Map<Object, Object> map = mapper.selectEmpByEmpno_1(2222); System.out.println(map); sqlSession.close(); } @Test public void test_selectAll2(){ SqlSession sqlSession = sqlSessionFactory.openSession(); EmpDao mapper = sqlSession.getMapper(EmpDao.class); Map<String, Emp> map = mapper.selectAll2(); System.out.println(map); sqlSession.close(); }
测试结果分别为:
testSelectAll
DEBUG [main] - ==> Preparing: select * from empDEBUG [main] - ==> Parameters:DEBUG [main] - <== Total: 5[Emp{empno=1111, ename='zhangsan', job='null', mgr=null, hiredate=null, sal=6666.67, comm=null, deptno=null}, Emp{empno=2222, ename='hhh', job='null', mgr=null, hiredate=null, sal=1500.0, comm=null, deptno=null}, Emp{empno=3333, ename='wangwu', job='null', mgr=null, hiredate=null, sal=4000.0, comm=null, deptno=null}, Emp{empno=4444, ename='maliu', job='null', mgr=null, hiredate=null, sal=8000.0, comm=null, deptno=null}, Emp{empno=5555, ename='lisi', job='null', mgr=null, hiredate=null, sal=null, comm=null, deptno=null}]
test_selectEmpByEmpno_1
DEBUG [main] - ==> Preparing: select * from emp where empno = ?DEBUG [main] - ==> Parameters: 2222(Integer)DEBUG [main] - <== Total: 1{ename=hhh, empno=2222, sal=1500.0}
test_selectAll2
DEBUG [main] - ==> Preparing: select * from empDEBUG [main] - ==> Parameters:DEBUG [main] - <== Total: 5{lisi=Emp{empno=5555, ename='lisi', job='null', mgr=null, hiredate=null, sal=null, comm=null, deptno=null}, zhangsan=Emp{empno=1111, ename='zhangsan', job='null', mgr=null, hiredate=null, sal=6666.67, comm=null, deptno=null}, hhh=Emp{empno=2222, ename='hhh', job='null', mgr=null, hiredate=null, sal=1500.0, comm=null, deptno=null}, maliu=Emp{empno=4444, ename='maliu', job='null', mgr=null, hiredate=null, sal=8000.0, comm=null, deptno=null}, wangwu=Emp{empno=3333, ename='wangwu', job='null', mgr=null, hiredate=null, sal=4000.0, comm=null, deptno=null}}
resultMap
resultMap:当进行关联查询时,在返回结果的对象中还包含另一个对象的引用时,此时需要自定义结果集合使用resultMap
一般情况下,mybatis会自动帮我们封装结果集(数据库字段名和类属性必须一一对应),但是当数据库中字段的值和类中的属性不匹配时,这时就需要我们自定义结果集。当然可以在sql中添加字段别名来保证查询结果赋值成功,但不可复用、比较繁琐。
<select id="selectDogById" resultType="Dog"> select id id, dname name, dage age, dgender gender from dog where id=#{id} select>
自定义结果集resultMap:
<resultMap id="myDog" type="Dog"> <id property="id" column="id">id> <result property="name" column="dname">result> <result property="age" column="dage">result> <result property="gender" column="dgender">result> resultMap> <select id="selectDogById_1" resultMap="myDog"> select * from dog where id=#{id} select>
创建表:
CREATE TABLE `dog` (`id` int(5) NOT NULL,`dname` varchar(5) DEFAULT NULL,`dage` int(2) DEFAULT '1',`dgender` char(1) DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
实体类:
package com.fan.bean;/*** @Description* @Author 1966659927@qq.com* @Date 2020-11-12 10:16* @Version 1.0* @Project mybatis_helloworld**/public class Dog { private Integer id; private String name; private Integer age; private String gender; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } @Override public String toString() { return "Dog{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", gender='" + gender + '\'' + '}'; }}
DAO层接口:
package com.fan.dao;import com.fan.bean.Dog;/*** @Description* @Author 1966659927@qq.com* @Date 2020-11-12 10:21* @Version 1.0* @Project mybatis_helloworld**/public interface DogDao { public Dog selectDogById(Integer id); public Dog selectDogById_1(Integer id);}
测试类:
import com.fan.bean.Dog;import com.fan.dao.DogDao;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import org.junit.Before;import org.junit.Test;import java.io.IOException;import java.io.InputStream;/*** @Description* @Author 1966659927@qq.com* @Date 2020-11-02 15:25* @Version 1.0* @Project mybatis_helloworld**/public class MyTest2 { SqlSessionFactory sqlSessionFactory = null; /* * 在测试方法之前执行 * */ @Before public void init() throws IOException { //通过xml创建一个SqlSessionFactory。SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,因此 SqlSessionFactory 的最佳作用域是应用作用域。 String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void test_selectDogById(){ SqlSession sqlSession = sqlSessionFactory.openSession(); DogDao mapper = sqlSession.getMapper(DogDao.class); Dog dog = mapper.selectDogById(1); System.out.println(dog); sqlSession.close(); } @Test public void test_selectDogById_1(){ SqlSession sqlSession = sqlSessionFactory.openSession(); DogDao mapper = sqlSession.getMapper(DogDao.class); Dog dog = mapper.selectDogById_1(1); System.out.println(dog); sqlSession.close(); }}
association属性
association属性是resultMap的子属性。当包含其他对象时,可以通过 对象.属性 来取到其他对象的值 或者使用association属性。
创建表:
create table `dept`(`deptno` int(4) not null,`dname` varchar(10) default null,`loc` varchar(10) default null)engine=innodb default charset=utf8
1、 对象.属性 的方式获取其他对象的值
<resultMap id="myEmp" type="Emp"> <id column="empno" property="empno">id> <result column="ename" property="ename">result> <result column="job" property="job">result> <result column="mgr" property="mgr">result> <result column="hiredate" property="hiredate">result> <result column="sal" property="sal">result> <result column="comm" property="comm">result> <result column="deptno" property="dept.deptno">result> <result column="dname" property="dept.dname">result> <result column="loc" property="dept.loc">result> resultMap> <select id="selectEmpByEmpno" resultMap="myEmp"> select * from emp left join dept on emp.deptno = dept.deptno where empno = #{empno} select>
实体类:
package com.fan.bean;import java.util.List;/*** @Description* @Author 1966659927@qq.com* @Date 2020-11-12 16:50* @Version 1.0* @Project mybatis_sqlMapping**/public class Dept { private Integer deptno; private String dname; private String loc; public Integer getDeptno() { return deptno; } public void setDeptno(Integer deptno) { this.deptno = deptno; } public String getDname() { return dname; } public void setDname(String dname) { this.dname = dname; } public String getLoc() { return loc; } public void setLoc(String loc) { this.loc = loc; } @Override public String toString() { return "Dept{" + "deptno=" + deptno + ", dname='" + dname + '\'' + ", loc='" + loc + '\''+ '}'; }}
DAO层接口:
public Emp selectEmpByEmpno(Integer empno);
测试方法:
@Test public void test_selectEmpByEmpno(){ SqlSession sqlSession = sqlSessionFactory.openSession(); EmpDao mapper = sqlSession.getMapper(EmpDao.class); Emp emp = mapper.selectEmpByEmpno(1111); System.out.println(emp); sqlSession.close(); }
测试结果:
DEBUG [main] - ==> Preparing: select * from emp left join dept on emp.deptno = dept.deptno where empno = ?DEBUG [main] - ==> Parameters: 1111(Integer)DEBUG [main] - <== Total: 1Emp{empno=1111, ename='zhangsan', job='null', mgr=null, hiredate=null, sal=6666.67, comm=null, dept=Dept{deptno=1, dname='软件', loc='null', emps=null}}
2、association属性 的方式获取其他对象的值
<resultMap id="myEmp_1" type="Emp"> <id column="empno" property="empno">id> <result column="ename" property="ename">result> <result column="job" property="job">result> <result column="mgr" property="mgr">result> <result column="hiredate" property="hiredate">result> <result column="sal" property="sal">result> <result column="comm" property="comm">result> <association property="dept" javaType="Dept"> <id column="deptno" property="deptno">id> <result column="dname" property="dname">result> <result column="loc" property="loc">result> association> resultMap> <select id="selectEmpByEmpno_1" resultMap="myEmp_1"> select * from emp left join dept on emp.deptno = dept.deptno where empno = #{empno} select>
实体类:同上
DAO层接口:
public Emp selectEmpByEmpno_1(Integer empno);
测试方法:
@Test public void test_selectEmpByEmpno_1(){ SqlSession sqlSession = sqlSessionFactory.openSession(); EmpDao mapper = sqlSession.getMapper(EmpDao.class); Emp emp = mapper.selectEmpByEmpno_1(1111); System.out.println(emp); sqlSession.close(); }
测试结果:
DEBUG [main] - ==> Preparing: select * from emp left join dept on emp.deptno = dept.deptno where empno = ?DEBUG [main] - ==> Parameters: 1111(Integer)DEBUG [main] - <== Total: 1Emp{empno=1111, ename='zhangsan', job='null', mgr=null, hiredate=null, sal=6666.67, comm=null, dept=Dept{deptno=1, dname='软件', loc='null', emps=null}}
collection属性
collection属性是resultMap的子属性,用于数据库中一对多的情形。
例如:一个部门对应多个员工,即一个部门dept中有多个员工emp。
<resultMap id="myDept" type="com.fan.bean.Dept"> <id column="deptno" property="deptno">id> <result column="dname" property="dname">result> <result column="loc" property="loc">result> <collection property="emps" ofType="com.fan.bean.Emp"> <id column="empno" property="empno">id> <result column="ename" property="ename">result> <result column="job" property="job">result> <result column="mgr" property="mgr">result> <result column="hiredate" property="hiredate">result> <result column="sal" property="sal">result> <result column="comm" property="comm">result> collection> resultMap> <select id="selectDeptByDeptno" resultMap="myDept"> select * from dept left join emp on dept.deptno = emp.deptno where dept.deptno = #{deptno} select>
实体类:添加一个emp的集合
package com.fan.bean;import java.util.List;/*** @Description* @Author 1966659927@qq.com* @Date 2020-11-12 16:50* @Version 1.0* @Project mybatis_sqlMapping**/public class Dept { private Integer deptno; private String dname; private String loc; private List<Emp> emps; public Integer getDeptno() { return deptno; } public void setDeptno(Integer deptno) { this.deptno = deptno; } public String getDname() { return dname; } public void setDname(String dname) { this.dname = dname; } public String getLoc() { return loc; } public void setLoc(String loc) { this.loc = loc; } public List<Emp> getEmps() { return emps; } public void setEmps(List<Emp> emps) { this.emps = emps; } @Override public String toString() { return "Dept{" + "deptno=" + deptno + ", dname='" + dname + '\'' + ", loc='" + loc + '\'' + ", emps=" + emps + '}'; }}
DAO层接口:
public Dept selectDeptByDeptno(Integer deptno);
测试类:
@Testpublic void test_selectDeptByDeptno(){ SqlSession sqlSession = sqlSessionFactory.openSession(); DeptDao mapper = sqlSession.getMapper(DeptDao.class); Dept dept = mapper.selectDeptByDeptno(1); System.out.println(dept); sqlSession.close();}
测试结果:可以看到一个dept对应了多个emp
DEBUG [main] - ==> Preparing: select * from dept left join emp on dept.deptno = emp.deptno where dept.deptno = ?DEBUG [main] - ==> Parameters: 1(Integer)DEBUG [main] - <== Total: 3Dept{deptno=1, dname='软件', loc='null', emps=[Emp{empno=1111, ename='zhangsan', job='null', mgr=null, hiredate=null, sal=6666.67, comm=null, dept=null}, Emp{empno=3333, ename='wangwu', job='null', mgr=null, hiredate=null, sal=4000.0, comm=null, dept=null}, Emp{empno=4444, ename='maliu', job='null', mgr=null, hiredate=null, sal=8000.0, comm=null, dept=null}]}
以上文章已同步到个人博客:https://bfanfanfan.gitee.io/fanfanfan
Ⓜ️ 我是一只小白猿,下期再见!