SpringBoot学习笔记(五)——Spring Boot中使用MyBatis进阶
目录
一、MyBatis 配置文件详解
1.1、settings 全局参数配置
mybatis 框架运行时可以调整一些运行参数。比如,开启二级缓存,开启延迟加载等等。全局参数会影响 mybatis 的运行行为。
mybatis-settings 的配置属性以及描述
setting(设置) | Description(描述) | valid Values(验证值组) | Default(默认值) |
cacheEnabled | 在全局范围内启用或禁用缓存配置 任何映射器在此配置下。 | true | false | TRUE |
lazyLoadingEnabled | 在全局范围内启用或禁用延迟加载。禁用时,所有相关联的将热加载。 | true | false | TRUE |
aggressiveLazyLoading | 启用时,有延迟加载属性的对象将被完全加载后调用懒惰的任何属性。否则,每一个属性是按需加载。 | true | false | TRUE |
multipleResultSetsEnabled | 允许或不允许从一个单独的语句(需要兼容的驱动程序)要返回多个结果集。 | true | false | TRUE |
useColumnLabel | 使用列标签,而不是列名。在这方面,不同的驱动有不同的行为。参考驱动文档或测试两种方法来决定你的驱动程序的行为如何。 | true | false | TRUE |
useGeneratedKeys | 允许 JDBC 支持生成的密钥。兼容的驱动程序是必需的。此设置强制生成的键被使用,如果设置为 true,一些驱动会不兼容性,但仍然可以工作。 | true | false | FALSE |
autoMappingBehavior | 指定 MyBatis 的应如何自动映射列到字段 / 属性。NONE 自动映射。 PARTIAL 只会自动映射结果没有嵌套结果映射定义里面。 FULL 会自动映射的结果映射任何复杂的(包含嵌套或其他)。 |
NONE,PARTIAL,FULL |
PARTIAL |
defaultExecutorType | 配置默认执行人。SIMPLE 执行人确实没有什么特别的。 REUSE 执行器重用准备好的语句。 BATCH 执行器重用语句和批处理更新。 |
SIMPLE,REUSE,BATCH |
SIMPLE |
safeRowBoundsEnabled | 允许使用嵌套的语句 RowBounds。 | true | false | FALSE |
mapUnderscoreToCamelCase | 从经典的数据库列名 A_COLUMN 启用自动映射到骆驼标识的经典的 Java 属性名 aColumn。 | true | false | FALSE |
localCacheScope | MyBatis 的使用本地缓存,以防止循环引用,并加快反复嵌套查询。默认情况下(SESSION)会话期间执行的所有查询缓存。如果 localCacheScope=STATMENT 本地会话将被用于语句的执行,只是没有将数据共享之间的两个不同的调用相同的 SqlSession。 |
SESSION STATEMENT |
SESSION |
dbcTypeForNull | 指定为空值时,没有特定的 JDBC 类型的参数的 JDBC 类型。有些驱动需要指定列的 JDBC 类型,但其他像 NULL,VARCHAR 或 OTHER 的工作与通用值。 | JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER | OTHER |
lazyLoadTriggerMethods | 指定触发延迟加载的对象的方法。 | A method name list separated by commas | equals,clone,hashCode,toString |
defaultScriptingLanguage | 指定所使用的语言默认为动态 SQL 生成。 | A type alias or fully qualified class name. |
org.apache.ibatis.scripting.xmltags .XMLDynamicLanguageDriver |
callSettersOnNulls | 指定如果 setter 方法或 map 的 put 方法时,将调用检索到的值是 null。它是有用的,当你依靠 Map.keySet()或 null 初始化。注意(如整型,布尔等)不会被设置为 null。 | true | false | FALSE |
logPrefix | 指定的前缀字串,MyBatis 将会增加记录器的名称。 | Any String | Not set |
logImpl | 指定 MyBatis 的日志实现使用。如果此设置是不存在的记录的实施将自动查找。 | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | Not set |
proxyFactory | 指定代理工具,MyBatis 将会使用创建懒加载能力的对象。 | CGLIB | JAVASSIST | CGLIB |
官方文档 settings 的例子:
<setting name="cacheEnabled" value="true"/> <setting name="lazyLoadingEnabled" value="true"/> <setting name="multipleResultSetsEnabled" value="true"/> <setting name="useColumnLabel" value="true"/> <setting name="useGeneratedKeys" value="false"/> <setting name="autoMappingBehavior" value="PARTIAL"/> <setting name="defaultExecutorType" value="SIMPLE"/> <setting name="defaultStatementTimeout" value="25"/> <setting name="safeRowBoundsEnabled" value="false"/> <setting name="mapUnderscoreToCamelCase" value="false"/> <setting name="localCacheScope" value="SESSION"/> <setting name="jdbcTypeForNull" value="OTHER"/> <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/> </settings>
示例:
这里设置 MyBatis 的日志输出到控制台:
mybatis:
type-aliases-package: com.zhangguo.mybatisdemo.entity #类型别名包的位置
mapper-locations: classpath:/mapper/*.xml #映射文件位置
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
结果:
1.2、typeAiases(别名)
在mapper.xml中,定义很多的statement,statement需要parameterType指定输入参数的类型、需要resultType指定输出结果的映射类型。
如果在指定类型时输入类型全路径,不方便进行开发,可以针对parameterType或resultType指定的类型定义一些别名,在mapper.xml中通过别名定义,方便开发。
如下所示类型 com.zhangguo.mybatis02.entities.Student 会反复出现,冗余:
<?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.zhangguo.mybatis02.mapper.studentMapper"> <select id="selectStudentById" resultType="com.zhangguo.mybatis02.entities.Student"> SELECT id,name,sex from student where id=#{id} </select><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">select </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="selectStudentsByName"</span><span style="color: rgba(255, 0, 0, 1)"> parameterType</span><span style="color: rgba(0, 0, 255, 1)">="String"</span><span style="color: rgba(255, 0, 0, 1)"> resultType</span><span style="color: rgba(0, 0, 255, 1)">="com.zhangguo.mybatis02.entities.Student"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> SELECT id,name,sex from student where name like '%${value}%'; </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">insert </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="insertStudent"</span><span style="color: rgba(255, 0, 0, 1)"> parameterType</span><span style="color: rgba(0, 0, 255, 1)">="com.zhangguo.mybatis02.entities.Student"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> insert into student(name,sex) VALUES(#{name},'${sex}') </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">insert</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">update </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="updateStudent"</span><span style="color: rgba(255, 0, 0, 1)"> parameterType</span><span style="color: rgba(0, 0, 255, 1)">="com.zhangguo.mybatis02.entities.Student"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> update student set name=#{name},sex=#{sex} where id=#{id} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">update</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">delete </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="deleteStudent"</span><span style="color: rgba(255, 0, 0, 1)"> parameterType</span><span style="color: rgba(0, 0, 255, 1)">="int"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> delete from student where id=#{id} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">delete</span><span style="color: rgba(0, 0, 255, 1)">></span>
</mapper>
1.2.1.MyBatis 默认支持的别名
别名 |
映射的类型 |
_byte |
byte |
_long |
long |
_short |
short |
_int |
int |
_integer |
int |
_double |
double |
_float |
float |
_boolean |
boolean |
string |
String |
byte |
Byte |
long |
Long |
short |
Short |
int |
Integer |
integer |
Integer |
double |
Double |
float |
Float |
boolean |
Boolean |
date |
Date |
decimal |
BigDecimal |
bigdecimal |
BigDecimal |
1.2.2.批量定义别名,扫描指定的包
定义单个别名的缺点很明显,如果项目中有很多别名则需要一个一个定义,且修改类型了还要修改配置文件非常麻烦,可以指定一个包,将下面所有的类都按照一定的规则定义成别名:
mybatis: #指定包名下所有的类被自动扫描并定义默认别名, #mybatis 会自动扫描包中的 pojo 类,自动定义别名,别名就是类名 (首字母大写或小写都可以) type-aliases-package: com.zhangguo.mybatisdemo.entity #类型别名包的位置 mapper-locations: classpath:/mapper/*.xml #映射文件位置 configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
如果 com.zhangguo.mybatis02.entities 包下有一个名为 Student 的类,则使用别名时可以是:student,或 Student。
你一定会想到当两个名称相同时的冲突问题,可以使用注解解决
解决方法:
1.3、typeHandlers(类型处理器)
mybatis中通过typeHandlers完成jdbc类型和java类型的转换。
通常情况下,mybatis提供的类型处理器满足日常需要,不需要自定义.
mybatis支持类型处理器:
类型处理器 |
Java 类型 |
JDBC 类型 |
BooleanTypeHandler |
Boolean,boolean |
任何兼容的布尔值 |
ByteTypeHandler |
Byte,byte |
任何兼容的数字或字节类型 |
ShortTypeHandler |
Short,short |
任何兼容的数字或短整型 |
IntegerTypeHandler |
Integer,int |
任何兼容的数字和整型 |
LongTypeHandler |
Long,long |
任何兼容的数字或长整型 |
FloatTypeHandler |
Float,float |
任何兼容的数字或单精度浮点型 |
DoubleTypeHandler |
Double,double |
任何兼容的数字或双精度浮点型 |
BigDecimalTypeHandler |
BigDecimal |
任何兼容的数字或十进制小数类型 |
StringTypeHandler |
String |
CHAR 和 VARCHAR 类型 |
ClobTypeHandler |
String |
CLOB 和 LONGVARCHAR 类型 |
NStringTypeHandler |
String |
NVARCHAR 和 NCHAR 类型 |
NClobTypeHandler |
String |
NCLOB 类型 |
ByteArrayTypeHandler |
byte[] |
任何兼容的字节流类型 |
BlobTypeHandler |
byte[] |
BLOB 和 LONGVARBINARY 类型 |
DateTypeHandler |
Date(java.util) |
TIMESTAMP 类型 |
DateOnlyTypeHandler |
Date(java.util) |
DATE 类型 |
TimeOnlyTypeHandler |
Date(java.util) |
TIME 类型 |
SqlTimestampTypeHandler |
Timestamp(java.sql) |
TIMESTAMP 类型 |
SqlDateTypeHandler |
Date(java.sql) |
DATE 类型 |
SqlTimeTypeHandler |
Time(java.sql) |
TIME 类型 |
ObjectTypeHandler |
任意 |
其他或未指定类型 |
EnumTypeHandler |
Enumeration 类型 |
VARCHAR- 任何兼容的字符串类型,作为代码存储(而不是索引)。 |
二、MyBatis 输入输出映射
2.1、输入映射
通过 parameterType 指定输入参数的类型,类型可以是简单类型、HashMap、POJO的包装类型。
Mybatis 的配置文件中的 select,insert,update,delete 有一个属性 parameter 来接收 mapper 接口方法中的参数。可以接收的类型有简单类型和复杂类型,但是只能是一个参数。这个属性是可选的,因为 Mybatis 可以通过 TypeHandler 来判断传入的参数类型,默认值是 unset。
2.1.1、基本类型
各种 java 的基本数据类型。常用的有 int、String、Data 等
接口:
/** * 根据学生编号获得学生对象 */ Student selectStudentById(int id);
映射:
<select id="selectStudentById" resultType="Student" parameterType="int"> SELECT id,name,sex from student where id=#{id} </select>
测试:
/** * Method: selectStudentById(int id) */ @Test public void testSelectStudentById() throws Exception { Student entity=dao.selectStudentById(1); System.out.println(entity); Assert.assertNotNull(entity); }
结果:
用 #{变量名} 来取值,这里的变量名是任意的,可以用 value 或者是其它的什么值,这里用 id 是为了便于理解,并不存在什么对应关系的。因为 java 反射主只能够得到方法参数的类型,而无从知道参数的名字的。当在动态 sql 中的 if 语句中的 test 传递参数时,就必须要用 _parameter 来传递参数了(OGNL 表达式),如果你传入 id 就会报错。
2.1.2、多个参数
(一)、直接使用参数名称
该方法在低版本中可能出现错误
(二)、使用 Map
接口:
/** * 根据学生姓名或性别获得学生集合 */ List<Student> selectStudentsByNameOrSex(Map<String,Object> params);
映射:
<select id="selectStudentsByNameOrSex" resultType="student"> SELECT id,name,sex from student where name like '%${name}%' or sex=#{sex}; </select>
测试:
/** * Method: List<Student> selectStudentsByNameOrSex(Map<String,Object> params); */ @Test public void selectStudentsByNameOrSex() throws Exception { Map<String,Object> params=new HashMap<String,Object>(); params.put("name","Candy"); params.put("sex","girl"); List<Student> students=dao.selectStudentsByNameOrSex(params);System.out.println(students); Assert.assertNotNull(students); }</span></pre>
结果:
(三)、注解参数名称:
接口:
/** * 根据学生姓名或性别获得学生集合 */ List<Student> selectStudentsByNameOrSex(@Param("realname") String name,@Param("sex") String sex);
映射:
<select id="selectStudentsByNameOrSex" resultType="student"> SELECT id,name,sex from student where name like '%${realname}%' or sex=#{sex}; </select>
测试:
/** * Method: selectStudentsByNameOrSex(String name,String sex) */ @Test public void testSelectStudentsByNameOrSex() throws Exception { List<Student> students=dao.selectStudentsByNameOrSex("C","boy"); System.out.println(students); Assert.assertNotNull(students); }
结果:
2.1.3、POJO 对象
POJO 是 Plain OrdinaryJava Object 的缩写,但是它通指没有使用 Entity Beans 的普通 java 对象,可以把 POJO 作为支持业务逻辑的协助类。
各种类型的 POJO,取值用 #{属性名}。这里的属性名是和传入的 POJO 中的属性名一一对应。
接口:
/** * 添加学生 */ int insertStudent(Student entity);
映射:
<insert id="insertStudent" parameterType="student"> insert into student(name,sex) VALUES(#{name},'${sex}') </insert>
测试:
/** * Method: insertStudent */ @Test public void testInsertStudent() throws Exception { Student entity=new Student(); entity.setName("张明"); entity.setSex("boy");Assert.assertEquals(</span>1<span style="color: rgba(0, 0, 0, 1)">,dao.insertStudent(entity)); }</span></pre>
结果:
如果要在 if 元素中测试传入的 user 参数, 仍然要使用 _parameter 来引用传递进来的实际参数, 因为传递进来的 User 对象的名字是不可考的。如果测试对象的属性, 则直接引用属性名字就可以了。
测试 user 对象:
<if test="_parameter!= null">
测试 user 对象的属性:
<if test="name!= null">
如果对象中还存在对象则需要使用 ${属性名. 属性.x} 方式访问
2.1.4、Map
具体请查看 2.1.2 节。
传入 map 类型, 直接通过 #{keyname} 就可以引用到键对应的值。使用 @param 注释的多个参数值也会组装成一个 map 数据结构, 和直接传递 map 进来没有区别。
mapper 接口:
int updateByExample(@Param("user") User user, @Param("example") UserExample example);
sql 映射:
<update id="updateByExample" parameterType="map" >update tb_user set id = #{user.id}, ...
<if test="_parameter != null" >
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
注意这里测试传递进来的 map 是否为空, 仍然使用 _parameter
2.1.5、集合类型
可以传递一个 List 或 Array 类型的对象作为参数,MyBatis 会自动的将 List 或 Array 对象包装到一个 Map 对象中,List 类型对象会使用 list 作为键名, 而 Array 对象会用 array 作为键名。集合类型通常用于构造 IN 条件,sql 映射文件中使用 foreach 元素来遍历 List 或 Array 元素。
假定这里需要实现多删除功能,示例如下:
接口:
/** * 删除多个学生通过编号 */ int deleteStudents(List<Integer> ids);
映射:
<delete id="deleteStudents"> delete from student where id in <foreach collection="list" item="id" open="(" separator="," close=")"> #{id} </foreach> </delete>
collection 这里只能是 list
测试:
/** * Method: deleteStudents */ @Test public void testDeleteStudents() throws Exception { List<Integer> ids=new ArrayList<Integer>(); ids.add(10); ids.add(11); Assert.assertEquals(2,dao.deleteStudents(ids)); }
结果:
当然查询中也可以这样使用
public List<XXXBean> getXXXBeanList(List<String> list);<select id="getXXXBeanList" resultType="XXBean">
select 字段... from XXX where id in
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</select>foreach 最后的效果是 select 字段... from XXX where id in ('1','2','3','4')
对于单独传递的 List 或 Array, 在 SQL 映射文件中映射时, 只能通过 list 或 array 来引用。但是如果对象类型有属性的类型为 List 或 Array,则在 sql 映射文件的 foreach 元素中, 可以直接使用属性名字来引用。
mapper 接口:
List<User> selectByExample(UserExample example);
sql 映射文件:
<where> <foreach collection="oredCriteria" item="criteria" separator="or"> <if test="criteria.valid"> </where>
在这里,UserExample 有一个属性叫 oredCriteria, 其类型为 List, 所以在 foreach 元素里直接用属性名 oredCriteria 引用这个 List 即可。
item="criteria" 表示使用 criteria 这个名字引用每一个集合中的每一个 List 或 Array 元素。
使用数组与可变参数
List<Category> findByIds(int... ids);
sql 映射文件:
<select id="findByIds" resultType="Category"> SELECT id,name from category where id in <foreach collection="array" open="(" close=")" separator=","> #{ids} </foreach> </select>
2.2、输出映射
输出映射主要有两种方式指定 ResultType 或 ResultMap,现在分别介绍一下:
2.2.1、ResultType
使用 ResultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
如果查询出来的列名和 POJO中的属性名全部不一致,没有创建 POJO对象。
只要查询出来的列名和 POJO中的属性有一个一致,就会创建 POJO对象。
(一)、输出简单类型
接口:
/** * 获得学生总数 * */ long selectStudentsCount();
映射:
<select id="selectStudentsCount" resultType="long"> SELECT count(*) from student </select>
测试:
/** * Method: selectStudentsCount() */ @Test public void testSelectStudentsCount() throws Exception { Assert.assertNotEquals(0,dao.selectStudentsCount());}
结果:
查询出来的结果集只有一行一列,可以使用简单类型进行输出映射。
( 二)、输出 POJO 对象和 POJO 列表
不管是输出的POJO单个对象还是一个列表(List中存放 POJO),在mapper.xml中 ResultType指定的类型是一样的,但方法返回值类型不一样。
输出单个 POJO 对象,方法返回值是单个对象类型
接口:
/** * 根据学生编号获得学生对象 */ Student selectStudentById(int id);
映射:
<select id="selectStudentById" resultType="Student"> SELECT id,name,sex from student where id=#{id} </select>
输出 pojo 对象 list,方法返回值是 List<POJO>
接口:
/** * 根据学生姓名获得学生集合 */ List<Student> selectStudentsByName(String name);
映射:
<select id="selectStudentsByName" parameterType="String" resultType="student"> SELECT id,name,sex from student where name like '%${value}%'; </select>
生成的动态代理对象中是根据 mapper.java 方法的返回值类型确定是调用 selectOne(返回单个对象调用) 还是 selectList(返回集合对象调用)
2.2.2、ResultMap
MyBatis中使用 ResultMap完成自定义输出结果映射,如一对多,多对多关联关系。
问题:
假定 POJO 对象与表中的字段不一致,如下所示:
接口:
/** * 根据性别获得学生集合 */ List<Stu> selectStudentsBySex(String sex);
映射:
<select id="selectStudentsBySex" parameterType="String" resultType="stu"> SELECT id,name,sex from student where sex=#{sex}; </select>
测试:
/** * Method: selectStudentsBySex(String sex) */ @Test public void testSelectStudentsBySex() throws Exception { List<Stu> students=dao.selectStudentsBySex("boy"); System.out.println(students); Assert.assertNotNull(students.get(0));}
结果:
(一)、定义并引用 ResultMap
修改映射文件:
<!--定义结果映射,id 是引用时的编号需唯一,stu 是最终被映射的类型--> <resultMap id="stuMap" type="stu"> <!--映射结果,collumn 表示列名,property 表示属性名--> <result column="id" property="stu_id"></result> <result column="name" property="stu_name"></result> <result column="sex" property="stu_sex"></result> </resultMap><span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)">resultMap指定引用的映射</span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">select </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="selectStudentsBySex"</span><span style="color: rgba(255, 0, 0, 1)"> parameterType</span><span style="color: rgba(0, 0, 255, 1)">="String"</span><span style="color: rgba(255, 0, 0, 1)"> resultMap</span><span style="color: rgba(0, 0, 255, 1)">="stuMap"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> SELECT id,name,sex from student where sex=#{sex}; </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
测试结果:
(二)、使用别名
修改映射文件:
<select id="selectStudentsBySex" parameterType="String" resultType="stu"> SELECT id stu_id,name stu_name,sex as stu_sex from student where sex=#{sex}; </select>
测试结果:
(三)、注解上使用 Result
@Results({ @Result(property ="id",column = "id"), @Result(property = "name",column = "name")}) @Select("select * from Category where id=#{id}") Category findById(int id);
2.2.3、返回 Map
假定要返回 id 作为 key,name 作为 value 的 Map。
接口:
/** * 获得所有学生 Map 集合 */ List<Map<String,Object>> selectAllStudents();
映射:
<resultMap id="stuKeyValueMap" type="HashMap"> <result property="name" column="NAME"></result> <result property="value" column="VALUE"></result> </resultMap><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">select </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="selectAllStudents"</span><span style="color: rgba(255, 0, 0, 1)"> resultMap</span><span style="color: rgba(0, 0, 255, 1)">="stuKeyValueMap"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> SELECT id NAME,name VALUE from student; </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
测试:
/** * Method: selectAllStudents() */ @Test public void testSelectAllStudents() throws Exception { List<Map<String,Object>> students=dao.selectAllStudents(); System.out.println(students); Assert.assertNotNull(students); }
结果:
<resultMap id="pieMap" type="HashMap"> <result property="value" column="VALUE" /> <result property="name" column="NAME" /> </resultMap><select id="queryPieParam" parameterType="String" resultMap="pieMap">
SELECT
PLAT_NAME NAME,
<if test='_parameter ==" 总量 "'>
AMOUNT VALUE
</if>
<if test='_parameter ==" 总额 "'>
TOTALS VALUE
</if>
FROM
DOMAIN_PLAT_DEAL_PIE
ORDER BY
<if test='_parameter ==" 总量 "'>
AMOUNT
</if>
<if test='_parameter ==" 总额 "'>
TOTALS
</if>
ASC
</select>
用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。
最终完成的映射器:
<?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.zhangguo.mybatis03.dao.StudentMapper"><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">select </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="selectStudentById"</span><span style="color: rgba(255, 0, 0, 1)"> resultType</span><span style="color: rgba(0, 0, 255, 1)">="Student"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> SELECT id,name,sex from student where id=#{id} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">select </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="selectStudentsCount"</span><span style="color: rgba(255, 0, 0, 1)"> resultType</span><span style="color: rgba(0, 0, 255, 1)">="long"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> SELECT count(*) from student </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">select </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="selectStudentsByName"</span><span style="color: rgba(255, 0, 0, 1)"> parameterType</span><span style="color: rgba(0, 0, 255, 1)">="String"</span><span style="color: rgba(255, 0, 0, 1)"> resultType</span><span style="color: rgba(0, 0, 255, 1)">="student"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> SELECT id,name,sex from student where name like '%${value}%'; </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">resultMap </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="stuKeyValueMap"</span><span style="color: rgba(255, 0, 0, 1)"> type</span><span style="color: rgba(0, 0, 255, 1)">="HashMap"</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">result </span><span style="color: rgba(255, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">="name"</span><span style="color: rgba(255, 0, 0, 1)"> column</span><span style="color: rgba(0, 0, 255, 1)">="NAME"</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">result</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">result </span><span style="color: rgba(255, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">="value"</span><span style="color: rgba(255, 0, 0, 1)"> column</span><span style="color: rgba(0, 0, 255, 1)">="VALUE"</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">result</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">resultMap</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">select </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="selectAllStudents"</span><span style="color: rgba(255, 0, 0, 1)"> resultMap</span><span style="color: rgba(0, 0, 255, 1)">="stuKeyValueMap"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> SELECT id NAME,name VALUE from student; </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)">定义结果映射,id是引用时的编号需唯一,stu是最终被映射的类型</span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">resultMap </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="stuMap"</span><span style="color: rgba(255, 0, 0, 1)"> type</span><span style="color: rgba(0, 0, 255, 1)">="stu"</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)">映射结果,collumn表示列名,property表示属性名</span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">result </span><span style="color: rgba(255, 0, 0, 1)">column</span><span style="color: rgba(0, 0, 255, 1)">="id"</span><span style="color: rgba(255, 0, 0, 1)"> property</span><span style="color: rgba(0, 0, 255, 1)">="stu_id"</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">result</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">result </span><span style="color: rgba(255, 0, 0, 1)">column</span><span style="color: rgba(0, 0, 255, 1)">="name"</span><span style="color: rgba(255, 0, 0, 1)"> property</span><span style="color: rgba(0, 0, 255, 1)">="stu_name"</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">result</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">result </span><span style="color: rgba(255, 0, 0, 1)">column</span><span style="color: rgba(0, 0, 255, 1)">="sex"</span><span style="color: rgba(255, 0, 0, 1)"> property</span><span style="color: rgba(0, 0, 255, 1)">="stu_sex"</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">result</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">resultMap</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)">resultMap指定引用的映射</span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)"><select id="selectStudentsBySex" parameterType="String" resultMap="stuMap"></span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)">SELECT id,name,sex from student where sex=#{sex};</span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)"></select></span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">select </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="selectStudentsBySex"</span><span style="color: rgba(255, 0, 0, 1)"> parameterType</span><span style="color: rgba(0, 0, 255, 1)">="String"</span><span style="color: rgba(255, 0, 0, 1)"> resultType</span><span style="color: rgba(0, 0, 255, 1)">="stu"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> SELECT id stu_id,name stu_name,sex as stu_sex from student where sex=#{sex}; </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">select </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="selectStudentsByNameOrSex"</span><span style="color: rgba(255, 0, 0, 1)"> resultType</span><span style="color: rgba(0, 0, 255, 1)">="student"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> SELECT id,name,sex from student where name like '%${realname}%' or sex=#{sex}; </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">select </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="selectStudentsByIdOrSex"</span><span style="color: rgba(255, 0, 0, 1)"> resultType</span><span style="color: rgba(0, 0, 255, 1)">="student"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> SELECT id,name,sex from student where id=#{no} or sex=#{sex}; </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">insert </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="insertStudent"</span><span style="color: rgba(255, 0, 0, 1)"> parameterType</span><span style="color: rgba(0, 0, 255, 1)">="student"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> insert into student(name,sex) VALUES(#{name},'${sex}') </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">insert</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">update </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="updateStudent"</span><span style="color: rgba(255, 0, 0, 1)"> parameterType</span><span style="color: rgba(0, 0, 255, 1)">="student"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> update student set name=#{name},sex=#{sex} where id=#{id} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">update</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">delete </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="deleteStudent"</span><span style="color: rgba(255, 0, 0, 1)"> parameterType</span><span style="color: rgba(0, 0, 255, 1)">="int"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> delete from student where id=#{id} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">delete</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">delete </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="deleteStudents"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> delete from student where id in </span><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">foreach </span><span style="color: rgba(255, 0, 0, 1)">collection</span><span style="color: rgba(0, 0, 255, 1)">="list"</span><span style="color: rgba(255, 0, 0, 1)"> item</span><span style="color: rgba(0, 0, 255, 1)">="id"</span><span style="color: rgba(255, 0, 0, 1)"> open</span><span style="color: rgba(0, 0, 255, 1)">="("</span><span style="color: rgba(255, 0, 0, 1)"> separator</span><span style="color: rgba(0, 0, 255, 1)">=","</span><span style="color: rgba(255, 0, 0, 1)"> close</span><span style="color: rgba(0, 0, 255, 1)">=")"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> #{id} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">foreach</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">delete</span><span style="color: rgba(0, 0, 255, 1)">></span>
</mapper>
最终完成的数据访问类似:
package com.zhangguo.mybatis03.dao;import com.zhangguo.mybatis03.entities.Stu;
import com.zhangguo.mybatis03.entities.Student;
import com.zhangguo.mybatis03.utils.SqlSessionFactoryUtil;
import org.apache.ibatis.session.SqlSession;import java.util.List;
import java.util.Map;public class StudentDao implements StudentMapper {
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 根据学生编号获得学生对象 </span><span style="color: rgba(0, 128, 0, 1)">*/</span> <span style="color: rgba(0, 0, 255, 1)">public</span> Student selectStudentById(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> id) { Student entity </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">打开一个会话</span> SqlSession session = SqlSessionFactoryUtil.openSession(<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获得一个映射器</span> StudentMapper mapper = session.getMapper(StudentMapper.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">查询单个对象,指定参数为3</span> entity =<span style="color: rgba(0, 0, 0, 1)"> mapper.selectStudentById(id); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">关闭</span>
SqlSessionFactoryUtil.closeSession(session);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> entity; } </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 获得学生总数 </span><span style="color: rgba(0, 128, 0, 1)">*/</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">long</span><span style="color: rgba(0, 0, 0, 1)"> selectStudentsCount() { </span><span style="color: rgba(0, 0, 255, 1)">long</span> count = 0<span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">打开一个会话</span> SqlSession session = SqlSessionFactoryUtil.openSession(<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获得一个映射器</span> StudentMapper mapper = session.getMapper(StudentMapper.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">查询单行单列,简单值</span> count =<span style="color: rgba(0, 0, 0, 1)"> mapper.selectStudentsCount(); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">关闭</span>
SqlSessionFactoryUtil.closeSession(session);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> count; } </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 根据学生姓名获得学生集合 </span><span style="color: rgba(0, 128, 0, 1)">*/</span> <span style="color: rgba(0, 0, 255, 1)">public</span> List<Student><span style="color: rgba(0, 0, 0, 1)"> selectStudentsByName(String name) { List</span><Student> entities = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">打开一个会话</span> SqlSession session = SqlSessionFactoryUtil.openSession(<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获得一个映射器</span> StudentMapper mapper = session.getMapper(StudentMapper.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">查询多个对象,指定参数</span> entities =<span style="color: rgba(0, 0, 0, 1)"> mapper.selectStudentsByName(name); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">关闭</span>
SqlSessionFactoryUtil.closeSession(session);
return entities;
}</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 获得所有学生Map集合 * </span><span style="color: rgba(0, 128, 0, 1)">*/</span> <span style="color: rgba(0, 0, 255, 1)">public</span> List<Map<String, Object>><span style="color: rgba(0, 0, 0, 1)"> selectAllStudents() { List</span><Map<String, Object>> entities = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">打开一个会话</span> SqlSession session = SqlSessionFactoryUtil.openSession(<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获得一个映射器</span> StudentMapper mapper = session.getMapper(StudentMapper.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">查询多个对象,指定参数</span> entities =<span style="color: rgba(0, 0, 0, 1)"> mapper.selectAllStudents(); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">关闭</span>
SqlSessionFactoryUtil.closeSession(session);
return entities;
}</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 根据性别获得学生集合 * * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> sex </span><span style="color: rgba(0, 128, 0, 1)">*/</span> <span style="color: rgba(0, 0, 255, 1)">public</span> List<Stu><span style="color: rgba(0, 0, 0, 1)"> selectStudentsBySex(String sex) { List</span><Stu> entities = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">打开一个会话</span> SqlSession session = SqlSessionFactoryUtil.openSession(<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获得一个映射器</span> StudentMapper mapper = session.getMapper(StudentMapper.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">查询多个对象,指定参数</span> entities =<span style="color: rgba(0, 0, 0, 1)"> mapper.selectStudentsBySex(sex); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">关闭</span>
SqlSessionFactoryUtil.closeSession(session);
return entities;
}</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 根据学生姓名或性别获得学生集合 * * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> name * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> sex </span><span style="color: rgba(0, 128, 0, 1)">*/</span> <span style="color: rgba(0, 0, 255, 1)">public</span> List<Student><span style="color: rgba(0, 0, 0, 1)"> selectStudentsByNameOrSex(String name, String sex) { List</span><Student> entities = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">打开一个会话</span> SqlSession session = SqlSessionFactoryUtil.openSession(<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获得一个映射器</span> StudentMapper mapper = session.getMapper(StudentMapper.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">查询多个对象,指定参数</span> entities =<span style="color: rgba(0, 0, 0, 1)"> mapper.selectStudentsByNameOrSex(name, sex); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">关闭</span>
SqlSessionFactoryUtil.closeSession(session);
return entities;
}</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 根据学生Id或性别获得学生集合 * * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> param </span><span style="color: rgba(0, 128, 0, 1)">*/</span> <span style="color: rgba(0, 0, 255, 1)">public</span> List<Student> selectStudentsByIdOrSex(Map<String, Object><span style="color: rgba(0, 0, 0, 1)"> param) { List</span><Student> entities = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">打开一个会话</span> SqlSession session = SqlSessionFactoryUtil.openSession(<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获得一个映射器</span> StudentMapper mapper = session.getMapper(StudentMapper.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">查询多个对象,指定参数</span> entities =<span style="color: rgba(0, 0, 0, 1)"> mapper.selectStudentsByIdOrSex(param); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">关闭</span>
SqlSessionFactoryUtil.closeSession(session);
return entities;
}</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 添加学生 </span><span style="color: rgba(0, 128, 0, 1)">*/</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> insertStudent(Student entity) { </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">影响行数</span> <span style="color: rgba(0, 0, 255, 1)">int</span> rows = 0<span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">打开一个会话</span> SqlSession session = SqlSessionFactoryUtil.openSession(<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获得一个映射器</span> StudentMapper mapper = session.getMapper(StudentMapper.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">执行添加</span> rows =<span style="color: rgba(0, 0, 0, 1)"> mapper.insertStudent(entity); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">关闭</span>
SqlSessionFactoryUtil.closeSession(session);
return rows;
}</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 更新学生 </span><span style="color: rgba(0, 128, 0, 1)">*/</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> updateStudent(Student entity) { </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">影响行数</span> <span style="color: rgba(0, 0, 255, 1)">int</span> rows = 0<span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">打开一个会话</span> SqlSession session = SqlSessionFactoryUtil.openSession(<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获得一个映射器</span> StudentMapper mapper = session.getMapper(StudentMapper.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">执行更新</span> rows =<span style="color: rgba(0, 0, 0, 1)"> mapper.updateStudent(entity); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">关闭</span>
SqlSessionFactoryUtil.closeSession(session);
return rows;
}</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 删除学生 </span><span style="color: rgba(0, 128, 0, 1)">*/</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> deleteStudent(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> id) { </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">影响行数</span> <span style="color: rgba(0, 0, 255, 1)">int</span> rows = 0<span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">打开一个会话</span> SqlSession session = SqlSessionFactoryUtil.openSession(<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获得一个映射器</span> StudentMapper mapper = session.getMapper(StudentMapper.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">执行删除</span> rows =<span style="color: rgba(0, 0, 0, 1)"> mapper.deleteStudent(id); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">关闭</span>
SqlSessionFactoryUtil.closeSession(session);
return rows;
}</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 删除多个学生通过编号 * * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> ids </span><span style="color: rgba(0, 128, 0, 1)">*/</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> deleteStudents(List<Integer><span style="color: rgba(0, 0, 0, 1)"> ids) { </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">影响行数</span> <span style="color: rgba(0, 0, 255, 1)">int</span> rows = 0<span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">打开一个会话</span> SqlSession session = SqlSessionFactoryUtil.openSession(<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获得一个映射器</span> StudentMapper mapper = session.getMapper(StudentMapper.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">执行删除</span> rows =<span style="color: rgba(0, 0, 0, 1)"> mapper.deleteStudents(ids); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">关闭</span>
SqlSessionFactoryUtil.closeSession(session);
return rows;
}}
最终完成的接口:
package com.zhangguo.mybatis03.dao;import com.zhangguo.mybatis03.entities.Stu;
import com.zhangguo.mybatis03.entities.Student;
import org.apache.ibatis.annotations.Param;import java.util.List;
import java.util.Map;public interface StudentMapper {
/**
* 根据学生编号获得学生对象
*/
Student selectStudentById(int id);</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 获得学生总数 * </span><span style="color: rgba(0, 128, 0, 1)">*/</span> <span style="color: rgba(0, 0, 255, 1)">long</span><span style="color: rgba(0, 0, 0, 1)"> selectStudentsCount(); </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 根据学生姓名获得学生集合 </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> List</span><Student><span style="color: rgba(0, 0, 0, 1)"> selectStudentsByName(String name); </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 获得所有学生Map集合 </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> List</span><Map<String,Object>><span style="color: rgba(0, 0, 0, 1)"> selectAllStudents(); </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 根据性别获得学生集合 </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> List</span><Stu><span style="color: rgba(0, 0, 0, 1)"> selectStudentsBySex(String sex); </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 根据学生姓名或性别获得学生集合 </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> List</span><Student> selectStudentsByNameOrSex(@Param("realname") String name,@Param("sex"<span style="color: rgba(0, 0, 0, 1)">) String sex); </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 根据学生Id或性别获得学生集合 </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> List</span><Student> selectStudentsByIdOrSex(Map<String,Object><span style="color: rgba(0, 0, 0, 1)"> param); </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 添加学生 </span><span style="color: rgba(0, 128, 0, 1)">*/</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> insertStudent(Student entity); </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 更新学生 </span><span style="color: rgba(0, 128, 0, 1)">*/</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> updateStudent(Student entity); </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 删除学生 </span><span style="color: rgba(0, 128, 0, 1)">*/</span> <span style="color: rgba(0, 0, 255, 1)">int</span> deleteStudent(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> id); </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> * 删除多个学生通过编号 </span><span style="color: rgba(0, 128, 0, 1)">*/</span> <span style="color: rgba(0, 0, 255, 1)">int</span> deleteStudents(List<Integer><span style="color: rgba(0, 0, 0, 1)"> ids);
}
最终完成的测试:
package com.zhangguo.mybatis03.dao;import com.zhangguo.mybatis03.entities.Stu;
import com.zhangguo.mybatis03.entities.Student;
import org.junit.*;
import org.junit.runners.MethodSorters;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/**
StudentDao Tester.
@author <Authors name>
@version 1.0
@since <pre>09/26/2018</pre>
*/
@FixMethodOrder(MethodSorters.JVM)//指定测试方法按定义的顺序执行
public class StudentDaoTest {
StudentMapper dao;
@Before
public void before() throws Exception {
dao=new StudentDao();
}@After
public void after() throws Exception {
}/**
- Method: selectStudentById(int id)
*/
@Test
public void testSelectStudentById() throws Exception {
Student entity=dao.selectStudentById(1);
System.out.println(entity);
Assert.assertNotNull(entity);
}//
/**
- Method: selectStudentsCount()
*/
@Test
public void testSelectStudentsCount() throws Exception {
Assert.assertNotEquals(0,dao.selectStudentsCount());
}
/**- Method: selectStudentsByName(String name)
*/
@Test
public void testSelectStudentsByName() throws Exception {
List<Student> students=dao.selectStudentsByName("C");
System.out.println(students);
Assert.assertNotNull(students);
}/**
- Method: selectAllStudents()
*/
@Test
public void testSelectAllStudents() throws Exception {
List<Map<String,Object>> students=dao.selectAllStudents();
System.out.println(students);
Assert.assertNotNull(students);
}/**
- Method: selectStudentsBySex(String sex)
*/
@Test
public void testSelectStudentsBySex() throws Exception {
List<Stu> students=dao.selectStudentsBySex("boy");
System.out.println(students);
Assert.assertNotNull(students.get(0));
}/**
- Method: selectStudentsByIdOrSex
*/
@Test
public void testSelectStudentsByNameOrSex() throws Exception {
Map<String ,Object> param=new HashMap<String,Object>();
param.put("no",1);
param.put("sex","girl");
List<Student> students=dao.selectStudentsByIdOrSex(param);
System.out.println(students);
Assert.assertNotNull(students);
}/**
Method: insertStudent
*/
@Test
public void testInsertStudent() throws Exception {
Student entity=new Student();
//entity.setName("张明");
entity.setSex("boy");Assert.assertEquals(1,dao.insertStudent(entity));
}/**
Method: updateStudent
*/
@Test
public void testUpdateStudent() throws Exception {
Student entity=dao.selectStudentById(11);
//entity.setName("张丽美");
entity.setSex("girl");Assert.assertEquals(1,dao.updateStudent(entity));
}/**
- Method: deleteStudent
*/
@Test
public void testDeleteStudent() throws Exception {
Assert.assertEquals(1,dao.deleteStudent(12));
}/**
- Method: deleteStudents
*/
@Test
public void testDeleteStudents() throws Exception {
List<Integer> ids=new ArrayList<Integer>();
ids.add(10);
ids.add(11);
Assert.assertEquals(2,dao.deleteStudents(ids));
}
}
三、多表关联查询
表与表之间有三种常见的关联关系,分别是一对一,一对多与多对多关系,MyBatis 直接提供一对一与一对多的关联关系,可能通过间接的方式实现一对多关联。
3.1、一对一关系
3.1.1、执行环境
假定一个员工(emp)拥有一个登录用户(user),员工与用户表之间是一对一关系:
用户表:
员工表:
SQL:
SET FOREIGN_KEY_CHECKS=0;-- ----------------------------
-- Table structure foruser
-- ----------------------------
DROP TABLE IF EXISTS<span style="color: rgba(255, 0, 255, 1)">user</span><span style="color: rgba(0, 0, 0, 1)">
;
CREATE TABLE<span style="color: rgba(255, 0, 255, 1)">user</span><span style="color: rgba(0, 0, 0, 1)">
(id
int(11) NOT NULL AUTO_INCREMENT COMMENT '编号',username
varchar(64) NOT NULL COMMENT '用户名',password
varchar(64) NOT NULL COMMENT '密码',
PRIMARY KEY (id
),
UNIQUE KEYusers_username_uindex
(username
)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='用户表';-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO<span style="color: rgba(255, 0, 255, 1)">user</span>
VALUES ('1', 'tom', '123456');
INSERT INTO<span style="color: rgba(255, 0, 255, 1)">user</span>
VALUES ('2', 'rose', '888888');
INSERT INTO<span style="color: rgba(255, 0, 255, 1)">user</span>
VALUES ('3', 'mark', 'qwerty');
INSERT INTO<span style="color: rgba(255, 0, 255, 1)">user</span>
VALUES ('4', 'jack', 'qaz123');
INSERT INTO<span style="color: rgba(255, 0, 255, 1)">user</span>
VALUES ('5', 'mali', 'uio890');SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure foremp
-- ----------------------------
DROP TABLE IF EXISTSemp
;
CREATE TABLEemp
(id
int(11) NOT NULL AUTO_INCREMENT COMMENT '编号',</span><span style="color: rgba(255, 0, 255, 1)">user_id</span>
int(11) DEFAULT NULL COMMENT '用户编号',realname
varchar(32) NOT NULL COMMENT '姓名',
PRIMARY KEY (id
),
KEYemp_user_id
(<span style="color: rgba(255, 0, 255, 1)">user_id</span><span style="color: rgba(0, 0, 0, 1)">
),
CONSTRAINTemp_user_id
FOREIGN KEY (<span style="color: rgba(255, 0, 255, 1)">user_id</span>
) REFERENCES<span style="color: rgba(255, 0, 255, 1)">user</span><span style="color: rgba(0, 0, 0, 1)">
(id
)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COMMENT='员工表';-- ----------------------------
-- Records of emp
-- ----------------------------
INSERT INTOemp
VALUES ('1', '1', '汤姆', 'tom@gmail.com');
INSERT INTOemp
VALUES ('2', '2', '梅贵', 'rose@163.com');
INSERT INTOemp
VALUES ('3', '3', '马克', 'mark@sina.com');
INSERT INTOemp
VALUES ('4', '4', '岳翰', 'jack@gmail.com');
INSERT INTOemp
VALUES ('5', '5', '马丽', 'mali@sina.com');
关系:
3.1.2、关联查询(1 次查询)
实体:
用户:
package com.zhangguo.mybatis03.entities;/**用户 POJO*/
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;
}
}
员工:
package com.zhangguo.mybatis03.entities;/员工 POJO*/
public class Emp {
private int id;
/用户编号*/
private int user_id;
private String realname;
private String email;/*用户对象/
private User user;public int getId() {
return id;
}public void setId(int id) {
this.id = id;
}public int getUser_id() {
return user_id;
}public void setUser_id(int user_id) {
this.user_id = user_id;
}public String getRealname() {
return realname;
}public void setRealname(String realname) {
this.realname = realname;
}public String getEmail() {
return email;
}public void setEmail(String email) {
this.email = email;
}public User getUser() {
return user;
}public Emp setUser(User user) {
this.user = user;
return this;
}
}
接口:
package com.zhangguo.mybatis03.dao;import com.zhangguo.mybatis03.entities.Emp;
/**员工数据访口*/
public interface EmpMapper {/**获得员工通过员工编号*/
Emp getEmpById_1(int 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.zhangguo.mybatis03.dao.EmpMapper"><!--一对一查询,方法 1,通过内联接-->
<select id="getEmpById_1" resultMap="empMap_1" parameterType="int">
SELECT
emp.id,
emp.user_id,
emp.realname,
emp.email,user
.username,user
.password
FROM
emp
INNER JOINuser
ON emp.user_id =user
.id where emp.id=#{id}
</select><!--员工关联查询结果映射-->
<resultMap id="empMap_1" type="Emp">
<id property="id" column="id"></id>
<result property="user_id" column="user_id"></result>
<result property="realname" column="realname"></result>
<result property="email" column="email"></result>
<!--映射关系,指定属性与属性的类型-->
<association property="user" javaType="User">
<id property="id" column="user_id"></id>
<result property="username" column="username"></result>
<result property="password" column="password"></result>
</association>
</resultMap></mapper>
测试:
package com.zhangguo.mybatis03.dao;import com.zhangguo.mybatis03.entities.Emp;
import org.junit.Assert;
import org.junit.Test;
import org.junit.Before;
import org.junit.After;/**
- EmpDao Tester.
- @author <Authors name>
- @version 1.0
- @since <pre>09/30/2018</pre>
*/
public class EmpDaoTest {
EmpMapper empDao;
@Before
public void before() throws Exception {
empDao=new EmpDao();
}@After
public void after() throws Exception {
}/**
- Method: getEmpById_1(int id)
- 获得员工通过员工编号
*/
@Test
public void testGetEmpById_1() throws Exception {
Emp entity=empDao.getEmpById_1(1);
System.out.println(entity);
Assert.assertNotNull(entity);
}}
结果:
3.1.3、嵌套查询(2 次查询)
实体:同上
接口:
/**获得员工通过员工编号,多次查询*/ Emp getEmpById_2(int id);
映射:
<!--一对一查询,方法 2,通过多次查询(嵌套查询)--> <select id="getEmpById_2" resultMap="empMap_2"> SELECT emp.id, emp.user_id, emp.realname, emp.email FROM emp where id=#{id} </select><!--员工多次查询结果映射-->
<resultMap id="empMap_2" type="Emp">
<id property="id" column="id"></id>
<result property="user_id" column="user_id"></result>
<result property="realname" column="realname"></result>
<result property="email" column="email"></result>
<!--通过外键 user_id 再次发起查询,调用 selectUserById 获得 User 对象-->
<association property="user" column="user_id" select="selectUserById"></association>
</resultMap><!--根据用户编号获得用户对象-->
<select id="selectUserById" resultType="User">
SELECTuser
.id,user
.username,user
.password
FROMuser
where id=#{id}
</select>
测试:
/** * Method: getEmpById_2(int id) * 获得员工通过员工编号,一对一方法二 */ @Test public void testGetEmpById_2() throws Exception { Emp entity=empDao.getEmpById_2(2); System.out.println(entity); Assert.assertNotNull(entity); }
结果:
MyBatis 中使用 association 标签来解决一对一的关联查询,association 标签可用的属性如下:
- property: 对象属性的名称
- javaType: 对象属性的类型
- column: 所对应的外键字段名称
- select: 使用另一个查询封装的结果
3.2、一对多关系
3.2.1、执行环境
一个用户帐号可以被多个员工使用,形成一个一对多的关系,表中的数据如下:
员工表 emp:
用户表 user:
3.2.2、关联查询(1 次查询)
实体:
员工:
package com.zhangguo.mybatis03.entities;/员工 POJO*/
public class Emp {
private int id;
/用户编号*/
private int user_id;
private String realname;
private String email;/**用户对象*/
private User user;public int getId() {
return id;
}public void setId(int id) {
this.id = id;
}public int getUser_id() {
return user_id;
}public void setUser_id(int user_id) {
this.user_id = user_id;
}public String getRealname() {
return realname;
}public void setRealname(String realname) {
this.realname = realname;
}public String getEmail() {
return email;
}public void setEmail(String email) {
this.email = email;
}public User getUser() {
return user;
}public Emp setUser(User user) {
this.user = user;
return this;
}@Override
public String toString() {
return "Emp{" +
"id=" + id +
", user_id=" + user_id +
", realname='"+ realname +''' +
", email='"+ email +''' +
", user=" + user +
'}';
}
}
用户:
package com.zhangguo.mybatis03.entities;import java.util.List;
/**用户 POJO*/
public class User {
private int id;
private String username;
private String password;/*员工集合,一个用户对象对应多个员工对象/
private List<Emp> emps;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;
}public List<Emp> getEmps() {
return emps;
}public User setEmps(List<Emp> emps) {
this.emps = emps;
return this;
}@Override
public String toString() {
return "User{" +
"id=" + id +
", username='"+ username +''' +
", password='"+ password +''' +
", emps=" + emps +
'}';
}
}
接口:
/**获得用户通过用户编号,1 对多级联查询*/ User getUserById_1(int id);
映射:
<!--一对多查询,方法 1,通过内联接--> <select id="getUserById_1" resultMap="userMap_1" parameterType="int"> SELECT emp.id, emp.user_id, emp.realname, emp.email, `user`.username, `user`.`password` FROM emp INNER JOIN `user` ON emp.user_id = `user`.id where `user`.id=#{id} </select><resultMap id="userMap_1" type="User">
<id property="id" column="user_id"></id>
<result property="username" column="username"></result>
<result property="password" column="password"></result>
<!--将 emps 对象映射成一个集合,emps 是 user 类型中的属性,ofType 用于指定集合中存放的对象类型-->
<collection property="emps" ofType="Emp">
<id property="id" column="id"></id>
<result property="user_id" column="user_id"></result>
<result property="realname" column="realname"></result>
<result property="email" column="email"></result>
</collection>
</resultMap>
测试:
/** * Method: getUserById_1(int id) * 获得用户过用户编号,级联查询 */ @Test public void testGetUserById_1() throws Exception { User entity=empDao.getUserById_1(2); System.out.println(entity); Assert.assertNotNull(entity); }
结果:
上面的示例中会发现 User 对象中包含多个 Emp 对象,此时的 Emp 对象中又引用了 User 对象,但值是空的,如果想设置值可以继续用 1 对 1 的办法赋值:
映射:
<resultMap id="userMap_1" type="User"> <id property="id" column="user_id"></id> <result property="username" column="username"></result> <result property="password" column="password"></result> <!--将 emps 对象映射成一个集合,emps 是 user 类型中的属性,ofType 用于指定集合中存放的对象类型--> <collection property="emps" ofType="Emp"> <id property="id" column="id"></id> <result property="user_id" column="user_id"></result> <result property="realname" column="realname"></result> <result property="email" column="email"></result> <!--映射关系,指定属性与属性的类型--> <association property="user" javaType="User"> <id property="id" column="user_id"></id> <result property="username" column="username"></result> <result property="password" column="password"></result> </association> </collection> </resultMap>
结果:
3.1.3、嵌套查询(多次查询)
实体:同上
接口:
/**获得用户通过用户编号,1 对多嵌套查询*/ User getUserById_2(int id);
映射:
<!--一对多查询,方法 2,通过嵌套查询多次--> <select id="getUserById_2" resultMap="userMap_2" parameterType="int"> SELECT `user`.id, `user`.username, `user`.`password` FROM `user` where id=#{id} </select><resultMap id="userMap_2" type="User">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="password" column="password"></result>
<!--将 emps 对象映射成一个集合,emps 是 user 类型中的属性,ofType 用于指定集合中存放的对象类型-->
<!--select 用于指定再次查询的 SQL 编号,column 用于指定参数列-->
<collection property="emps" ofType="Emp" column="id" select="selectEmpById"></collection>
</resultMap><!--根据员工编号获得员工对象-->
<select id="selectEmpById" resultType="Emp">
SELECT
emp.id,
emp.user_id,
emp.realname,
emp.email
FROM
emp where user_id=#{id}
</select>
测试:
/** * Method: getUserById_2(int id) * 获得用户过用户编号,嵌套查询 */ @Test public void testGetUserById_2() throws Exception { User entity=empDao.getUserById_2(5); System.out.println(entity); Assert.assertNotNull(entity); }
结果:
MyBatis 中使用 collection 标签来解决一对多的关联查询,ofType 属性指定集合中元素的对象类型。
四、动态 SQL
4.0、MySQL 环境与前置要求
数据与 SQL 环境如下:
前置要求:
4.1、什么是动态 SQL
MyBatis 的动态 SQL 是基于 OGNL 的表达式的。它对 SQL 语句进行灵活的操作,通过表达式判断来实现对 SQL 的灵活拼接、组装。
mybatis 核心对 sql 语句进行灵活操作,通过表达式进行判断,对 sql 进行灵活拼接、组装。
主要通过以下标签:if,where,choose(when,otherwise),trim,set,foreach。
4.2、if 条件判断
根据 name 和 sex 来查询数据。如果 name 为空,那么将只根据 sex 来查询;反之只根据 name 来查询
首先不使用 动态 SQL 来书写
接口:
/** * 根据学生姓名和性别获得学生集合 */ List<Student> selectStudentsByNameAndSex(@Param("name") String name,@Param("sex") String sex);
映射:
<select id="selectStudentsByNameAndSex" resultType="student"> SELECT id,name,sex from student where name=#{name} and sex=#{sex}; </select>
测试:
/** * Method: selectStudentsByNameAndSex */ @Test public void testSelectStudentsByNameAndSex() throws Exception { List<Student> students=dao.selectStudentsByNameAndSex("rose",null); System.out.println(students); Assert.assertNotNull(students); }
结果:
上面的查询语句,我们发现如果 #{sex} 为空,那么查询结果也是空,如何解决这个问题呢?使用 if 来判断
<select id="selectStudentsByNameAndSex" resultType="student">SELECT id,name,sex from student where 1=1 </span><span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)">如果test为真会输出中间的内容</span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">if </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="name!=null and name!=''"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> and name=#{name} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">if</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">if </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="sex!=null and sex!=''"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> and sex=#{sex} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">if</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
结果:
参考:
<!-- 2 if(判断参数) - 将实体类不为空的属性作为 where 条件 --> <select id="getStudentList_if" resultMap="resultMap_studentEntity" parameterType="liming.student.manager.data.model.StudentEntity"> SELECT ST.STUDENT_ID, ST.STUDENT_NAME, ST.STUDENT_SEX, ST.STUDENT_BIRTHDAY, ST.STUDENT_PHOTO, ST.CLASS_ID, ST.PLACE_ID FROM STUDENT_TBL ST WHERE <if test="studentName !=null"> ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName, jdbcType=VARCHAR}),'%') </if> <if test="studentSex != null and studentSex !='' "> AND ST.STUDENT_SEX = #{studentSex, jdbcType=INTEGER} </if> <if test="studentBirthday != null"> AND ST.STUDENT_BIRTHDAY = #{studentBirthday, jdbcType=DATE} </if> <if test="classId != null and classId!='' "> AND ST.CLASS_ID = #{classId, jdbcType=VARCHAR} </if> <if test="classEntity != null and classEntity.classId !=null and classEntity.classId !=' ' "> AND ST.CLASS_ID = #{classEntity.classId, jdbcType=VARCHAR} </if> <if test="placeId != null and placeId !='' "> AND ST.PLACE_ID = #{placeId, jdbcType=VARCHAR} </if> <if test="placeEntity != null and placeEntity.placeId != null and placeEntity.placeId !='' "> AND ST.PLACE_ID = #{placeEntity.placeId, jdbcType=VARCHAR} </if> <if test="studentId != null and studentId !='' "> AND ST.STUDENT_ID = #{studentId, jdbcType=VARCHAR} </if> </select>
虽然 1=1 这种方法结合 if 可以解决我们的需求,但是 1=1 明显是冗余的,通过 where 可以解决。
4.3、where 条件
where 元素知道只有在一个以上的 if 条件有值的情况下才去插入“WHERE”子句,若最后的内容是“AND”或“OR”开头的,where 元素也知道如何将他们去除。
修改后的映射:
<select id="selectStudentsByNameAndSex" resultType="student">SELECT id,name,sex from student </span><span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)">1、如果两个if只要有一个有输出就会在sql中添加 where</span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">where</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">if </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="name!=null and name!=''"</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)">2、如果where后以and或or开始则会删除and或or</span><span style="color: rgba(0, 128, 0, 1)">--></span><span style="color: rgba(0, 0, 0, 1)"> and name like concat(concat('%',#{name}),'%'); </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">if</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">if </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="sex!=null and sex!=''"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> and sex=#{sex} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">if</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">where</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
测试:
/** * Method: selectStudentsByNameAndSex */ @Test public void testSelectStudentsByNameAndSex() throws Exception { List<Student> students=dao.selectStudentsByNameAndSex("a",null); System.out.println(students); Assert.assertNotNull(students); }
结果:
这个“where”标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签返回的内容是以 AND 或 OR 开头的,则它会剔除掉。
where 标记的作用类似于动态 sql 中的 set 标记,他的作用主要是用来简化 sql 语句中 where 条件判断的书写的,如下所示:
<select id="selectByParams" parameterType="map" resultType="user"> select * from user <where> <if test="id != null">id=#{id}</if> <if test="name != null and name.length()>0" >and name=#{name}</if> <if test="gender != null and gender.length()>0">and gender = #{gender}</if> </where> </select>
在上述 SQL 中加入 ID 的值为 null 的话,那么打印出来的 SQL 为:select * from user where name="xx" and gender="xx"
where 标记会自动将其后第一个条件的 and 或者是 or 给忽略掉
4.4、if+set 设置值
当 update 语句中没有使用 if 标签时,如果有一个参数为 null,都会导致错误。
当在 update 语句中使用 if 标签时,如果前面的 if 没有执行,则或导致逗号多余错误。使用 set 标签可以将动态的配置 SET 关键字,和剔除追加到条件末尾的任何不相关的逗号。如果 set 包含的内容为空的话则会出错。
使用 if+set 标签修改后,如果某项为 null 则不进行更新,而是保持数据库原值。
如果通过 if 判断表面可以解决问题,如下所示:
<update id="updateStudent" parameterType="student">update student set </span><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">if </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="name!=null and name.lenght()>0"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> name=#{name} , </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">if</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">if </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="sex!=null and sex.lenght()>0"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> sex=#{sex} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">if</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> where id=#{id} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">update</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
这样做也会有问题,就是当 sex 为空时的 sql 就变成了 update student set name=#{name} , where id=#{id},这明显是错误的。
同理,上面的对于查询 SQL 语句包含 where 关键字,如果在进行更新操作的时候,含有 set 关键词,我们怎么处理呢?
接口:
/** * 更新学生 */ int updateStudent(Student entity);
映射:
<update id="updateStudent" parameterType="student"> update student <!--自动添加 set--> <set> <!--智能处理逗号问题--> <if test="name!=null and name.length()>0"> name=#{name} </if><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">if </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="sex!=null and sex.length()>0"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> sex=#{sex} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">if</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">set</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> where id=#{id} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">update</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
注意:某些情况下逗号必须添加,如下所示:
<update id="updateStudent" parameterType="student"> update student <!--自动添加 set--> <set> <!--智能处理逗号问题--> <if test="name!=null and name.length()>0"> name=#{name} , </if><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">if </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="sex!=null and sex.length()>0"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> sex=#{sex} , </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">if</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">set</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> where id=#{id} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">update</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
结尾的逗号会被自动删除。
测试:
/** * Method: updateStudent */ @Test public void testUpdateStudent() throws Exception { //会将实体中的每一个字段都更新,不好 // Student entity=dao.selectStudentById(11); // //entity.setName("张丽美"); // entity.setSex("girl"); // // Assert.assertEquals(1,dao.updateStudent(entity));</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">不需要先执行查询</span> Student student=<span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Student(); student.setId(</span>9<span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">只更新了name与sex没有关系</span> student.setName("malili"<span style="color: rgba(0, 0, 0, 1)">); Assert.assertEquals(</span>1<span style="color: rgba(0, 0, 0, 1)">,dao.updateStudent(student)); }</span></pre>
结果:
这样写,如果第一个条件 name 为空,那么 sql 语句为:update student set sex=? where id=?
如果第一个条件不为空,那么 sql 语句为:update student u set name= ? , sex = ? where id=?
set 主要解决了自动添加标签与处理逗号的问题,另外这种更新方法比较以前的全部更新方式在开发中性能更高。
4.5、choose(when,otherwise) 开关
如果不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose 标签可以解决此类问题,类似于 Java 的 switch 语句。
假定这里需要优先根据编号搜索,没有时选择 name,最后考虑 sex:
接口:
/** * 根据学生编号、姓名和性别获得学生集合 */ List<Student> selectStudentsByNameAndSex(@Param("id") int id, @Param("name") String name,@Param("sex") String sex);
映射:
<select id="selectStudentsByNameAndSex" resultType="student">SELECT id,name,sex from student </span><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">where</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">choose</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">when </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="id>0"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> id=#{id} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">when</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">when </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="name!=null and name!=''"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> name=#{name} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">when</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">otherwise</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> sex=#{sex} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">otherwise</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">choose</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">where</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
测试:
/** * Method: selectStudentsByNameAndSex */ @Test public void testSelectStudentsByNameAndSex() throws Exception { List<Student> students=dao.selectStudentsByNameAndSex(1,"rose","girl"); System.out.println(students); Assert.assertNotNull(students); }
结果:
也就是说,这里我们有三个条件,id,name,sex,只能选择一个作为查询条件
如果 id 不为空,那么查询语句为:select * from student where id=?
如果 id 为空,那么看 name 是否为空,如果不为空,那么语句为 select * from student where name=?;
如果 name 为空,那么查询语句为 select * from student where sex=?
4.6、trim 裁剪
trim 标记是一个格式化的标记,可以完成 set 或者是 where 标记的功能
①、用 trim 改写上面第二点的 if+where 语句
if+where 的办法:
<select id="selectStudentsByNameAndSex" resultType="student">SELECT id,name,sex from student </span><span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)">1、如果两个if只要有一个有输出就会在sql中添加 where</span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">where</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">if </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="name!=null and name!=''"</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)">2、如果where后以and或or开始则会删除and或or</span><span style="color: rgba(0, 128, 0, 1)">--></span><span style="color: rgba(0, 0, 0, 1)"> and name like concat(concat('%',#{name}),'%'); </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">if</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">if </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="sex!=null and sex!=''"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> and sex=#{sex} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">if</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">where</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
trim 的办法:
<select id="selectStudentsByNameAndSex" resultType="student">SELECT id,name,sex from student </span><span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)">1、prefix表示将前置where,prefixOverrides将删除打头内容</span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">trim </span><span style="color: rgba(255, 0, 0, 1)">prefix</span><span style="color: rgba(0, 0, 255, 1)">="where"</span><span style="color: rgba(255, 0, 0, 1)"> prefixOverrides</span><span style="color: rgba(0, 0, 255, 1)">="and | or"</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">if </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="name!=null and name!=''"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> and name like concat(concat('%',#{name}),'%') </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">if</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">if </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="sex!=null and sex!=''"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> and sex=#{sex} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">if</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">trim</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
测试结果:
prefix:将加上前缀
prefixoverride:去掉第一个 and 或者是 or
②、用 trim 改写上面第三点的 if+set 语句
if+set 的方法:
<update id="updateStudent" parameterType="student"> update student <!--自动添加 set--> <set> <!--智能处理逗号问题--> <if test="name!=null and name.length()>0"> name=#{name} </if><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">if </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="sex!=null and sex.length()>0"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> sex=#{sex} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">if</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">set</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> where id=#{id} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">update</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
trim 的方法:
<update id="updateStudent" parameterType="student"> update student</span><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">trim </span><span style="color: rgba(255, 0, 0, 1)">prefix</span><span style="color: rgba(0, 0, 255, 1)">="set"</span><span style="color: rgba(255, 0, 0, 1)"> suffixOverrides</span><span style="color: rgba(0, 0, 255, 1)">=","</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">if </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="name!=null and name.length()>0"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> name=#{name}, </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">if</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">if </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="sex!=null and sex.length()>0"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> sex=#{sex}, </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">if</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">trim</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> where id=#{id} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">update</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
结果:
suffix:后缀
suffixoverride:去掉最后一个逗号(也可以是其他的标记,就像是上面前缀中的 and 一样)
可以自定义添加前后缀,与之对应的属性是 prefix 和 suffix。同时通过 prefixOverrides 和 suffixOverrides 分别来覆盖首尾部的内容,即忽略不必要的前后缀。就是说它可以充当 where 标签,也可以充当 set 标签啦 ~
充当 where 标签:
<trim prefix = "where" prefixOverrides="and|or" > ... </trim>
充当 set 标签:
<trim prefix="set" suffixOverrides=","> ... </trim>
例子:动态添加用户属性
<insert id="find" resultType="Admin"> insert into admin <trim prefix="(" suffix=")" suffixOverrides=","> <if test = "aname != null and aname !='' "> aname, </if> <if test = "city != null and city !='' "> city, </if> <if test = "age != null and age !='' "> age, </if> </trim> <trim prefix="values(" suffix=")" suffixOverrides=","> <if test = "aname != null and aname !='' "> #{aname}, </if> <if test = "city != null and city !='' "> #{city}, </if> <if test = "age != null and age !='' "> #{age}, </if> </trim> </insert>
上面相应的语句为:insert into admin (…) values(…);。通过 trim 标签用 () 包裹,以及自动忽略尾部的逗号。
4.7、SQL 片段
有时候可能某个 sql 语句我们用的特别多,为了增加代码的重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用。
比如:下面的映射文件中对于 id,name,sex 出现多次:
<select id="selectStudentsByNameOrSex" resultType="student"> SELECT id,name,sex from student where name like '%${realname}%' or sex=#{sex}; </select><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">select </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="selectStudentsByIdOrSex"</span><span style="color: rgba(255, 0, 0, 1)"> resultType</span><span style="color: rgba(0, 0, 255, 1)">="student"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> SELECT <strong>id,name,sex</strong> from student where id=#{no} or sex=#{sex}; </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">select </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="selectStudentsByNameAndSex"</span><span style="color: rgba(255, 0, 0, 1)"> resultType</span><span style="color: rgba(0, 0, 255, 1)">="student"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> SELECT <strong>id,name,sex</strong> from student </span><span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)">1、prefix表示将前置where,prefixOverrides将删除打头内容</span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">trim </span><span style="color: rgba(255, 0, 0, 1)">prefix</span><span style="color: rgba(0, 0, 255, 1)">="where"</span><span style="color: rgba(255, 0, 0, 1)"> prefixOverrides</span><span style="color: rgba(0, 0, 255, 1)">="and | or"</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">if </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="name!=null and name!=''"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> and name like concat(concat('%',#{name}),'%') </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">if</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">if </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="sex!=null and sex!=''"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> and sex=#{sex} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">if</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">trim</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
加粗的内容是重复的,通过 sql 片段复用。
定义 sql 片段:
<!--定义 sql 片段--> <sql id="col_student"> id,name,sex </sql>
引用 sql 片段
<select id="selectStudentsByNameOrSex" resultType="student"> <!--引用 sql 片段--> SELECT <include refid="col_student"></include> from student where name like '%${realname}%' or sex=#{sex}; </select><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">select </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="selectStudentsByIdOrSex"</span><span style="color: rgba(255, 0, 0, 1)"> resultType</span><span style="color: rgba(0, 0, 255, 1)">="student"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> SELECT </span><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">include </span><span style="color: rgba(255, 0, 0, 1)">refid</span><span style="color: rgba(0, 0, 255, 1)">="col_student"</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">include</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> from student where id=#{no} or sex=#{sex}; </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">select </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="selectStudentsByNameAndSex"</span><span style="color: rgba(255, 0, 0, 1)"> resultType</span><span style="color: rgba(0, 0, 255, 1)">="student"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> SELECT </span><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">include </span><span style="color: rgba(255, 0, 0, 1)">refid</span><span style="color: rgba(0, 0, 255, 1)">="col_student"</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">include</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> from student </span><span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)">1、prefix表示将前置where,prefixOverrides将删除打头内容</span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">trim </span><span style="color: rgba(255, 0, 0, 1)">prefix</span><span style="color: rgba(0, 0, 255, 1)">="where"</span><span style="color: rgba(255, 0, 0, 1)"> prefixOverrides</span><span style="color: rgba(0, 0, 255, 1)">="and | or"</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">if </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="name!=null and name!=''"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> and name like concat(concat('%',#{name}),'%') </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">if</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">if </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="sex!=null and sex!=''"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> and sex=#{sex} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">if</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">trim</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">></span> </pre>
结果:
注意:①、最好基于 单表来定义 sql 片段,提高片段的可重用性
②、在 sql 片段中不要包括 where
sql 片段带参数:
定义时使用参数:
<!--定义 sql 片段--> <sql id="col_student"> ${alias}.id,${alias}.name,${alias}.sex </sql>
引用时指定参数:
<select id="selectStudentsByNameAndSex" resultType="student">SELECT </span><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">include </span><span style="color: rgba(255, 0, 0, 1)">refid</span><span style="color: rgba(0, 0, 255, 1)">="col_student"</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="alias"</span><span style="color: rgba(255, 0, 0, 1)"> value</span><span style="color: rgba(0, 0, 255, 1)">="s"</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">include</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> from student s </span><span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)">1、prefix表示将前置where,prefixOverrides将删除打头内容</span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">trim </span><span style="color: rgba(255, 0, 0, 1)">prefix</span><span style="color: rgba(0, 0, 255, 1)">="where"</span><span style="color: rgba(255, 0, 0, 1)"> prefixOverrides</span><span style="color: rgba(0, 0, 255, 1)">="and | or"</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">if </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="name!=null and name!=''"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> and name like concat(concat('%',#{name}),'%') </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">if</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">if </span><span style="color: rgba(255, 0, 0, 1)">test</span><span style="color: rgba(0, 0, 255, 1)">="sex!=null and sex!=''"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> and sex=#{sex} </span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">if</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">trim</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">select</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
结果:
4.8、foreach 循环
foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及在迭代结果之间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符。
注意 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象传递给 foreach 作为集合参数。当使用可迭代对象或者数组时,index 是当前迭代的次数,item 的值是本次迭代获取的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。
到此我们已经完成了涉及 XML 配置文件和 XML 映射文件的讨论。下一章将详细探讨 Java API,这样就能提高已创建的映射文件的利用效率。
foreach 的主要用在构建 in 条件中,他可以迭代一个集合。foreach 元素的属性主要有:item,index,collection,open,separator,close。
下面对属性进行简单的介绍:
item: 表示集合中每一个元素进行迭代时的别名。
index: 指定一个名字,用于表示在迭代过程中每次迭代的位置。
open: 表示以什么开始。
separator: 每次迭代以什么分割。
close: 以什么关闭。
collection: 最重要且必须指定的有三种情况:
1. 如果传入的是单独参数的 List 类型时,collection 的属性值为 list。
2. 如果传入的是单独参数的数组时,collection 的属性值为 array。
3. 如果传入多个参数时,我们把多个参数放入 map 中,单参数也可以放入 map 中。map 中的 key 就是参数名,所以 collection 属性值就是传入的 List 或者 array 对象在 Map 里的 key。
一、用 foreach 来改写 select * from user where id=1 or id=2 or id=3
<select id="selectUserByListId" parameterType="com.ys.vo.UserVo" resultType="com.zhangguo.User"> select * from user <where> <!-- collection: 指定输入对象中的集合属性 item: 每次遍历生成的对象 open: 开始遍历时的拼接字符串 close: 结束时拼接的字符串 separator: 遍历对象之间需要拼接的字符串 select * from user where 1=1 and (id=1 or id=2 or id=3) --> <foreach collection="ids" item="id" open="and (" close=")" separator="or"> id=#{id} </foreach> </where> </select>
二、我们用 foreach 来改写 select * from user where id in (1,2,3)
<select id="selectUserByListId" parameterType="com.ys.vo.UserVo" resultType="com.zhangguo.User"> select * from user <where> <!-- collection: 指定输入对象中的集合属性 item: 每次遍历生成的对象 open: 开始遍历时的拼接字符串 close: 结束时拼接的字符串 separator: 遍历对象之间需要拼接的字符串 select * from user where 1=1 and id in (1,2,3) --> <foreach collection="ids" item="id" open="and id in (" close=")" separator=","> #{id} </foreach> </where> </select>
其实动态 sql 语句的编写往往就是一个拼接的问题,为了保证拼接准确,我们最好首先要写原生的 sql 语句出来,然后在通过 mybatis 动态 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"><!-- namespace 的名字需要跟接口的类名一致 -->
<mapper namespace="cn.bdqn.dao.UserMapper">
<!--
1、resultMap 属性:type 为 java 实体类;id 为此 resultMap 的标识
2、resultMap 的子元素:
id – 一般对应到数据库中该行的 ID, 设置此项可以提高 Mybatis 性能.
result – 映射到 JavaBean 的某个“简单类型”属性,String,int 等.
association – 映射到 JavaBean 的某个“复杂类型”属性, 其他 JavaBean 类.
collection –复杂类型集合
--><!--根据 roleId 获取用户列表: 当数据库中的字段信息与对象的属性不一致时需要通过 resultMap 来映射 -->
<!-- <resultMap type="User" id="seachUserResult">
<result property="id" column="id"/>
<result property="userCode" column="userCode"/>
<result property="userName" column="userName"/>
<result property="roleId" column="roleId"/>
<result property="roleName" column="roleName"/>
</resultMap><select id="getUserListByRoleId" parameterType="Role" resultMap="seachUserResult">
select u.*,r.roleName as roleName from user u,role r where u.roleId = r.id and u.roleId = #{id}
</select> --><!-- 根据 roleId 获取用户列表 association start-->
<resultMap type="User" id="seachUserResult">
<result property="id" column="id"/>
<result property="userCode" column="userCode" />
<result property="userName" column="userName" />
<result property="roleId" column="roleId" />
<!-- <association property="role" javaType="Role" >
<result property="id" column="id"/>
<result property="roleCode" column="roleCode"/>
<result property="roleName" column="roleName"/>
</association> -->
<association property="role" javaType="Role" resultMap="roleMap"/>
</resultMap><resultMap type="Role" id="roleMap">
<result property="id" column="id"/>
<result property="roleCode" column="roleCode"/>
<result property="roleName" column="roleName"/>
</resultMap><select id="getUserListByRoleId" parameterType="Role" resultMap="seachUserResult">
select u.*,r.roleCode as roleCode,r.roleName as roleName from user u,role r where u.roleId = r.id and u.roleId = #{id}
</select><!-- association end-->
<!-- 获取指定用户的地址列表 (user 表 -address 表:1 对多关系) collection start-->
<resultMap type="User" id="userMap">
<id property="id" column="userId"/>
<collection property="addressList" ofType="Address">
<id property="id" column="a_id"/>
<result property="postCode" column="postCode"/>
<result property="addressContent" column="addressContent"/>
</collection>
</resultMap><select id="getAddressListByUserId" parameterType="User" resultMap="userMap">
select *,a.id as a_id from user u,address a where u.id=a.userId and u.id=#{id}
</select>
<!-- collection end --><resultMap type="User" id="seachUser">
<result property="id" column="id"/>
<result property="userCode" column="userCode"/>
<result property="userName" column="userName"/>
<result property="roleId" column="roleId"/>
<result property="roleName" column="roleName"/>
</resultMap><!-- <select id="searchUserList" parameterType="User" resultMap="seachUser">
select u.*,r.roleName as roleName from user u,role r where u.roleId = r.id
and u.roleId = #{roleId}
and u.userCode like CONCAT ('%',#{userCode},'%') // 防止 sql 注入
and u.userName like CONCAT ('%',#{userName},'%')
</select> --><!--
1、有些时候,sql 语句 where 条件中,需要一些安全判断,例如按性别检索,如果传入的参数是空的,此时查询出的结果很可能是空的,也许我们需要参数为空时,是查出全部的信息。这是我们可以使用动态 sql,增加一个判断,当参数不符合要求的时候,我们可以不去判断此查询条件。
2、mybatis 的动态 sql 语句是基于 OGNL 表达式的。可以方便的在 sql 语句中实现某些逻辑. 总体说来 mybatis 动态 SQL 语句主要有以下几类:
if 语句 (简单的条件判断)
choose (when,otherwize) , 相当于 java 语言中的 switch , 与 jstl 中的 choose 很类似.
trim (对包含的内容加上 prefix, 或者 suffix 等,前缀,后缀)
where (主要是用来简化 sql 语句中 where 条件判断的,能智能的处理 and or , 不必担心多余导致语法错误)
set (主要用于更新时)
foreach (在实现 mybatis in 语句查询时特别有用)
--><!-- if(判断参数) - 将实体类不为空的属性作为 where 条件 -->
<select id="searchUserList" parameterType="User" resultMap="seachUser">
select u.*,r.roleName as roleName from user u,role r where u.roleId = r.id
<if test="roleId!=null">
and u.roleId = #{roleId}
</if>
<if test="userCode != null">
and u.userCode like CONCAT ('%',#{userCode},'%')
</if>
<if test="userName != null">
and u.userName like CONCAT ('%',#{userName},'%')
</if>
</select><select id="count" resultType="int">
select count(1) from user
</select><insert id="add" parameterType="User">
insert into user (userCode,userName,userPassword)
values (#{userCode},#{userName},#{userPassword})
</insert><!-- if/set(判断参数) - 将实体类不为空的属性更新 -->
<!-- <update id="update" parameterType="User">
update user
<set>
<if test="userCode != null and userCode !=''">userCode=#{userCode},</if>
<if test="userName != null">userName=#{userName},</if>
<if test="userPassword != null">userPassword=#{userPassword},</if>
<if test="roleId != null">roleId=#{roleId}</if>
</set>
where id=#{id}
</update> --><!-- if/trim 代替 set(判断参数) - 将实体类不为空的属性更新 -->
<update id="update" parameterType="User">
update user
<trim prefix="set" suffixOverrides=",">
<if test="userCode != null and userCode !=''">userCode=#{userCode},</if>
<if test="userName != null">userName=#{userName},</if>
<if test="userPassword != null">userPassword=#{userPassword},</if>
<if test="roleId != null">roleId=#{roleId}</if>
</trim>
where id=#{id}
</update><!--注意: 你可以传递一个 List 实例或者数组作为参数对象传给 MyBatis。
当你这么做的时候,MyBatis 会自动将它包装在一个 Map 中,用名称在作为键。
List 实例将会以“list”作为键,而数组实例将会以“array”作为键。
配置文件中的 parameterType 是可以不配置的-->
<resultMap type="User" id="userMapByDep">
<result property="id" column="id"/>
<result property="userCode" column="userCode"/>
<result property="userName" column="userName"/>
</resultMap>
<!-- foreach(循环 array 参数) - 作为 where 中 in 的条件 -->
<select id="getUserByDepId_foreach_array" resultMap="userMapByDep">
select * from user where depId in
<foreach collection="array" item="depIds" open="(" separator="," close=")">
#{depIds}
</foreach>
</select><!-- foreach(循环 List<String> 参数) - 作为 where 中 in 的条件 -->
<select id="getUserByDepId_foreach_list" resultMap="userMapByDep">
select * from user where depId in
<foreach collection="list" item="depIdList" open="(" separator="," close=")">
#{depIdList}
</foreach>
</select><delete id="delete" parameterType="User">
delete from user where id=#{id}
</delete><select id="getUserList" resultType="User">
select * from user
</select>
</mapper>
假定我们要多删除:
接口:
/** * 删除多个学生通过编号 */ int deleteStudents(List<Integer> ids);
映射:
<delete id="deleteStudents"> delete from student where id in <foreach collection="list" item="id" open="(" separator="," close=")"> #{id} </foreach> </delete>
注意 collection 这里只能是 list,不能是 ids,因为反射时获取不到参数名称。
测试:
/** * Method: deleteStudents */ @Test public void testDeleteStudents() throws Exception { List<Integer> ids=new ArrayList<Integer>(); ids.add(8); ids.add(9); Assert.assertEquals(2,dao.deleteStudents(ids)); }
结果:
4.9、bind 绑定变量
bind 标签可以使用 OGNL 表达式创建一个变量并将其绑定到上下文中。
bind 标签的两个属性都是不选项,name 为绑定到上下文的变量名,value 为 OGNL 表达式,创建一个 bind 标签后,就可以在下面直接使用了。 使用 bind 拼接字符串不仅可以避免因更换数据库而修改 SQL,也能预防 SQL 注入。
<!-- List<Employee> getEmpsTestInnerParameter(Employee employee); --> <select id="getEmpsTestInnerParameter" resultType="com.hand.mybatis.bean.Employee"> <!-- bind: 可以将 OGNL 表达式的值绑定到一个变量中,方便后来引用这个变量的值 --> <bind name="bindeName" value="'%'+eName+'%'"/> eName 是 employee 中一个属性值 SELECT * FROM emp <if test="_parameter!=null"> where ename like #{bindeName} </if> </select>
4.10、MyBatisX 代码生成
前言
MybatisX 是一款基于 IDEA 的快速开发插件,方便在使用 mybatis 以及 mybatis-plus 开发时简化繁琐的重复操作,提高开发速率。
MybatisX 的作用就是帮助我们自动化建立 mybatis 的相关文件,免去手动建立的繁琐!
4.10.1、安装 MybatisX 插件
在插件管理中,搜索 Mybatis,就会显示 MybatisX,然后我们点击它右侧的 Install 按钮,就能安装了。
4.10.2、引用相关的依赖
本人是 SpringBoot 框架,引入如下 Pom 内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
< dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-web</ artifactId > </ dependency > < dependency > < groupId >com.alibaba</ groupId > < artifactId >druid</ artifactId > < version >1.1.0</ version > </ dependency > < dependency > < groupId >org.projectlombok</ groupId > < artifactId >lombok</ artifactId > < optional >true</ optional > </ dependency > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-tomcat</ artifactId > < scope >provided</ scope > </ dependency > < dependency > < groupId >com.baomidou</ groupId > < artifactId >mybatis-plus-boot-starter</ artifactId > < version >3.5.1</ version > </ dependency > |
4.10.3、连接 MySQL
1、点击“Database”
2、点击“+”号,然后选择 Data Source
3、在显示的所有数据源中。选择 Mysql
4、在显示的数据源配置页面,至少填写 3 项内容
1)用户名
2)密码
3)数据库链接信息
5、填写完数据源配置信息后,在 Database 下面多出了一个数据库显示:
6、在我们添加的数据源 Mysql 数据库中,添加我们需要使用的数据库。
点击“0 of 7”这个位置,显示了该 Mysql 数据库下面所有的数据库
我们选中其中我们需要使用的数据库,然后按键盘上的 enter 键,就会完成数据库的选中工作。然后,显示如下内容:
4.10.4、开始使用 MybatisX,选择数据表,配置生产 Mybatis 文件的路径,生产最后的文件
1. 选择一个数据表,然后“右点击”,在显示的菜单中选择“MybatisX-generator”
2. 点击“MybatisX-generator”,显示如下信息:
选择 “Mybatis-Plus3”
点击 finish,最后结果如下:
五、MyBatisPlus
https://baomidou.com/getting-started/
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.15</version> </parent> <groupId>com.zhangguo</groupId> <artifactId>mybatisplusdemo</artifactId> <version>1.0.0</version> <name>mybatisplusdemo</name> <description>mybatisplusdemo</description> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>17</java.version> <druid.version>1.2.13</druid.version> <mybatisplus.version>3.5.3.2</mybatisplus.version> <sqlserver.version>4.0</sqlserver.version> <oracle.version>11.2.0.3</oracle.version> <dameng.version>8.1.2.79</dameng.version> <hutool.version>5.8.22</hutool.version> <jsoup.version>1.15.3</jsoup.version> <knife4j.version>2.0.9</knife4j.version> <lombok.version>1.18.24</lombok.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <!-- mysql 驱动 --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> </dependency> <!-- oracle 驱动 --> <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc6</artifactId> <version>${oracle.version}</version> </dependency> <!-- sqlserver 驱动 --> <dependency> <groupId>com.microsoft.sqlserver</groupId> <artifactId>sqljdbc4</artifactId> <version>${sqlserver.version}</version> </dependency> <!-- postgresql 驱动 --> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> </dependency> <!-- 达梦驱动 --> <dependency> <groupId>com.dameng</groupId> <artifactId>DmJdbcDriver18</artifactId> <version>${dameng.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>${druid.version}</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>${mybatisplus.version}</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>${hutool.version}</version> </dependency> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>${jsoup.version}</version> </dependency> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>${knife4j.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </dependency> </dependencies><span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)"> 阿里云maven仓库 </span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">repositories</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">repository</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">></span>public<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">></span>aliyun nexus<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">url</span><span style="color: rgba(0, 0, 255, 1)">></span>https://maven.aliyun.com/repository/public/<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">url</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">releases</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">enabled</span><span style="color: rgba(0, 0, 255, 1)">></span>true<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">enabled</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">releases</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">repository</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">repositories</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">build</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">plugins</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">plugin</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">></span>org.springframework.boot<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">></span>spring-boot-maven-plugin<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">configuration</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">excludes</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">exclude</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">></span>org.projectlombok<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">></span>lombok<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">exclude</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">excludes</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">configuration</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">plugin</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">plugins</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">build</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">pluginRepositories</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">pluginRepository</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">></span>public<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">></span>aliyun nexus<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">url</span><span style="color: rgba(0, 0, 255, 1)">></span>https://maven.aliyun.com/repository/public/<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">url</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">releases</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">enabled</span><span style="color: rgba(0, 0, 255, 1)">></span>true<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">enabled</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">releases</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">snapshots</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">enabled</span><span style="color: rgba(0, 0, 255, 1)">></span>false<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">enabled</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">snapshots</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">pluginRepository</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">pluginRepositories</span><span style="color: rgba(0, 0, 255, 1)">></span>
</project>
5.1 什么是 Mybatis-Plus
MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window) 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
5.2 Mybatis-Plus 特性
无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
六、视频
https://www.bilibili.com/video/av32447485/
七、示例
https://git.coding.net/zhangguo5/MyBatis02.git
https://git.coding.net/zhangguo5/MyBatis03.git
八、作业
0、完成一个多删除功能,前端可以勾选任意条记录,后端实现多删除功能,删除前提示是否删除。
1、个人项目的数据库设计,个人项目的静态页面设计(2 个,一个必须是首页,PC 端)
2、重现本章示例
3、任务指导手册所有 mybatis 理论题
4、根据如下 ER 图创建 4 个表,完成 1-1,1-N,M-N 关系的查询,无需界面,测试通过即可
5、完成图书管理系统中二表关联,显示图书类型
请实现一个简易图书管理系统(LibSystem),实现图书管理功能,要求如下: 1、管理数据库中所有图书(Books),包含图书编号(isbn)、书名(title)、作者(author)、价格(price)、出版日期(publishDate) 2、Maven 多模块 +MySQL+Git+MyBatis+JUnit 单元测试 3、表示层可以是 AJAX 或 JSTL请实现一个迷你图书管理系统(LibSystem),实现图书管理功能,要求如下:
1、管理数据库中所有图书分类(Categories),包含图书编号(id), 名称(name)
2、管理数据库中所有图书(Books),包含图书编号(isbn)、类别(categoryId,外键)书名(title)、作者(author)、价格(price)、出版日期(publishDate)、封面(cover)、详细介绍(details)
3、分页
4、多条件组件查询(3 个以上的条件)
5、上传封面
6、富文本编辑器
6、使用任意的原型开发工具设计出个人项目的 1-2 个界面,工具:Balsamiq Mockups,Axure RP Pro 7.0。
7、将动态 sql 中的所有知识点全部应用于作业 4
1、重现上所有上课示例
2、请使用 Maven 多模块 +Git+MyBatis 完成一个单表的管理功能,需要 UI, 可以 AJAX 也可以 JSTL 作表示层。
3、分页,多条件组合查询,多表连接(选作)
4、内部测试题(4 个小时)
4.1、请实现一个简易图书管理系统(LibSystem),实现图书管理功能,要求如下:(初级)
1、管理数据库中所有图书(Books),包含图书编号(isbn)、书名(title)、作者(author)、价格(price)、出版日期(publishDate)
2、Maven 多模块 +MySQL+Git+MyBatis+JUnit 单元测试
3、表示层可以是 AJAX 或 JSTL
C10 R(10+10) U10 D10
4.2、请实现一个迷你图书管理系统(LibSystem),实现图书管理功能,要求如下:(中级)
1、管理数据库中所有图书分类(Categories),包含图书编号(id), 名称(name)
2、管理数据库中所有图书(Books),包含图书编号(isbn)、类别(categoryId,外键)书名(title)、作者(author)、价格(price)、出版日期(publishDate)、封面(cover)、详细介绍(details)
3、分页 10
4、多条件组件查询(3 个以上的条件任意组合)(高级) 10
5、多删除 (高级) 10
6、上传封面 (高级) 10
7、富文本编辑器 (高级) 10
九、视频
https://www.bilibili.com/video/BV1fi4y1S79P?share_source=copy_web
https://space.bilibili.com/87194917/video
作业解答:https://www.bilibili.com/video/BV1Hs411F71x?share_source=copy_web