<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mappernamespace="com.lagou.mapper.UserMapper"><!--根据id查询用户--><selectid="findUserById"parameterType="int"resultType="user">
select * from user where id = #{id}
</select><!-- resultMap:手动配置实体属性与表中字段的映射关系,完成手动封装-
指向对应的唯一标识的映射,读取到的一系列数据会被这个标识进行确定位置,从而完成映射
从这里可以得出,读取映射文件,不只是读取一次,然后操作一次,也可以全部读取,将数据封装好,进行操作
这里就是如此,封装的对应MappedStatement对象(即类),每个元素基本就是一个MappedStatement对象
--><selectid="findAllResultMap"resultMap="userResultMap">
select * from User
</select><!-- id唯一标识,可以随便写,type也受别名影响,与resultType不同的是,resultType是用来默认封装
而type是自定义封装,会先判断默认封装,如果默认封装找不到了,则会看自定义封装
当数据库改变时,我们可以将resultType改为type,这样就可以自定义封装了
由于数据库的字段,最终都会是大小写忽略的过来判断,所以下面column是可以进行大小写的替换的,但我们通常都是小写
就如数据库也默认小写一样,所以像这样没有判断的基本大小写忽略
--><resultMapid="userResultMap"type="user"><!--手动配置映射关系--><!--id:用来配置主键--><idproperty="id"column="id"/><!--result:用来配置普通字段--><resultproperty="username"column="username"/><!--property可以是变量的小写,但不能是对应的大写,column可以大小写忽略
因为对应字段基本上是小写字段--><resultproperty="birthday"column="birthday"/><resultproperty="sex"column="sex"/><resultproperty="address"column="address"></result><!-- 大小写通常是忽略的,有些情况下,如判断下,基本是对应的小写,如#{},和property都是判断变量是否符号--></resultMap><!--多条件查询 1--><selectid="findByIdAndUsername1"resultMap="userResultMap"><!--select * from user where id = #{arg0} and username = #{arg1}-->
select * from user where id = #{param1} and username = #{param2}
<!--一般情况下,若需要两个以及两个以上的参数(不是类),parameterType只能操作其中一个,基本上是左边(当然,这些是需要看规则的,具体情况是,如果使用其他等等框架或者其他的一些某些操作,如MPJ,那么可能会拿取后面的,具体可以百度),且多余的一般默认为null(除非是相同的开始参数,如都是param1,那么就是对应的值)
因为没有替换(需要在数据库里加上null,而不是null字符串,使用程序得到的),这时若在
数据库表里没有找到对应值
那么一般不会报错,与?不同,没有替换,那么就会当作就是这个#{username},所以报错的,而?,则必须替换,否则报错
即找到了,那么一般就会报错,因为例外一个没有进行替换
所以为了实现这个操作,那么就基本不能使用parameterType
我们可以使用使用 #{arg0}-#{argn} 或者 #{param1}-#{paramn} 获取参数
arg0代表传递参数的第一位参数,param1也是
一般传统的需要一些特殊操作,才可实现多参数的传递,而这里的代理,可以直接进行多参数的传递(实际上也是特殊的操
作)
特殊操作,可以理解为使用map集合和类
使得对应替换为集合替换,对于类,当然使用的是替换类
而单参数,当然替换的是对应参数(名字可以随便起,因为最后只会替换单参数,写的名称会直接覆盖,不会像类和map那样
识别)
但必须有,否则报错,因为没有替换的值(实际上会识别#{}是否有对应名称,没有就会报错,对所有方式都会进行,所以随
便写的就是为了防止这个错误)
可以理解为他们赋值给Object
而多参数,可以理解为一个map集合(基本所有元素都可以使用),所以上面的特殊操作,也可以看成是map集合的操作
我们替换的就是对应集合的数,即key的值,且没有大小写忽略
因为map集合的key基本不能是不一样的获得的
最后:parameterType,一般是可以不写的,即会自动识别对应类型,写了是为了好知道传入的参数是什么,基本只是一个识别,所以这里还需要注意一点,就是他写错了,可能在不匹配的情况下,会操作自动,所以这个参数基本上主要作用只是告诉你他应该传递什么,而并非一定是他,写错了是会对开发人员造成一定的混淆,所以有时候在不规范的情况下,建议不要写,而规范的前提下,写上有利于开发
--></select><!--多条件查询 2--><selectid="findByIdAndUsername2"resultMap="userResultMap">
select * from user where id = #{id} and username = #{username}
<!--
假设,有两个@Param("id"),那么一般后面的覆盖前面的,假如两个
只有一个有@Param("id"),那么有id时操作该值
否则就相当于没有操作,即他是一个别名--></select><!--多条件查询 3
注意:id不能相同,否则报错
--><selectid="findByIdAndUsername3"resultMap="userResultMap"parameterType="user">
select * from user where id = #{id} and username = #{Username}
</select></mapper>
<!--
模糊查询:方式一 string不能写成String,没有封装String这个别名
--><selectid="findByUsername"resultMap="userResultMap"parameterType="string">
select * from user where username like #{username}
</select>
<!--这个标签可以封装好一个语句,由于所以元素基本会封装到一个MappedStatement对象
所以可以知道,他们都是一步一步读取,经过一系列操作,将结果语句放到对应对象
当读取到sql元素时,那么就会将对应对象中的对应标签值进行替换,从而形成了改变
--><sqlid="selectUser">
select * from user
</sql><!--引入方式,即改变方式,将对应的 select * from user改成下面的操作,将sql元素写在外面,使得读取到
即他们的位置是sql元素与其他元素平级,include与sql语句元素平级,否则的话,就会报错
--><includerefid="selectUser"></include>
DROPTABLEIFEXISTS`orders`;CREATETABLE`orders`(`id`int(11)NOTNULLAUTO_INCREMENT,`ordertime`varchar(255)DEFAULTNULL,`total`DOUBLEDEFAULTNULL,`uid`INT(11)DEFAULTNULL,PRIMARYKEY(`id`),KEY`uid`(`uid`),CONSTRAINT`orders_ibfk_1`FOREIGNKEY(`uid`)REFERENCES`user`(`id`))ENGINE=INNODBAUTO_INCREMENT=4DEFAULTCHARSET=utf8;-- ---------------------------- -- Records of orders -- ---------------------------- INSERTINTO`orders`VALUES('1','2020-12-12','3000','1');INSERTINTO`orders`VALUES('2','2020-12-12','4000','1');INSERTINTO`orders`VALUES('3','2020-12-12','5000','2');-- ---------------------------- -- Table structure for sys_role -- ---------------------------- DROP TABLE IF EXISTS `sys_role`; CREATETABLE`sys_role`(`id`INT(11)NOTNULLAUTO_INCREMENT,`rolename`VARCHAR(255)DEFAULTNULL,`roleDesc`VARCHAR(255)DEFAULTNULL,PRIMARYKEY(`id`))ENGINE=INNODBAUTO_INCREMENT=3DEFAULTCHARSET=utf8;-- ---------------------------- -- Records of sys_role -- ---------------------------- INSERTINTO`sys_role`VALUES('1','CTO','CTO');INSERTINTO`sys_role`VALUES('2','CEO','CEO');-- ---------------------------- -- Table structure for sys_user_role -- ---------------------------- DROPTABLEIFEXISTS`sys_user_role`;CREATETABLE`sys_user_role`(`userid`INT(11)NOTNULL,`roleid`INT(11)NOTNULL,PRIMARYKEY(`userid`,`roleid`),KEY`roleid`(`roleid`),CONSTRAINT`sys_user_role_ibfk_1`FOREIGNKEY(`userid`)REFERENCES`user`(`id`),CONSTRAINT`sys_user_role_ibfk_2`FOREIGNKEY(`roleid`)REFERENCES`sys_role`(`id`))ENGINE=InnoDBDEFAULTCHARSET=utf8;-- ---------------------------- -- Records of sys_user_role -- ---------------------------- INSERTINTO`sys_user_role`VALUES('1','1');INSERTINTO`sys_user_role`VALUES('2','1');INSERTINTO`sys_user_role`VALUES('1','2');INSERTINTO`sys_user_role`VALUES('2','2');
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mappernamespace="com.lagou.mapper.OrderMapper"><!--一对一关联查询:查询所有订单,与此同时还要查询出每个订单所属的用户信息--><resultMapid="orderMap"type="com.lagou.domain.Orders"><idproperty="id"column="id"/><resultproperty="ordertime"column="ordertime"/><resultproperty="total"column="total"/><resultproperty="uid"column="uid"/><!--
可以多次对应,包括collection,他们之间也可嵌套(包括自己),但是idea可能并没有解决嵌套的显示问题(如<collection property的值(他对应的result的不会),在嵌套的情况下会认为显示错误,可能解决了,需要看版本吧),所以与之前property的首字母大写一样,会出现显示错误,虽然并不影响运行
association : 在进行一对一关联查询配置时,使用association标签进行关联
通常操作的是对应实体类
property="user" :要封装实体的属性名
javaType="com.lagou.domain.User" 要封装的实体的属性类型
这个属性可以不写,因为没有的话,默认property的user类型,但写了,就会按照写的
其他的属性基本也是如此操作
而resultType的必须写,因为没有默认
只识别resultType,没有的话,就会报错
--><associationproperty="user"javaType="com.lagou.domain.User"><idproperty="id"column="uid"></id><!--uid与用户表的id是一样的,如果写id的话,不知道是哪个表的id,一般取最左边的--><resultproperty="username"column="username"></result><resultproperty="birthday"column="birthday"></result><resultproperty="sex"column="sex"></result><resultproperty="address"column="address"></result><!--一般的,一个类或者集合类型的,在这个设置值若设置不了,通常会报错,所以这里需要这样--></association></resultMap><!--想要完成映射封装,默认的封装基本封装不了Orders的user变量里面去,所以需要自定义封装--><selectid="findAllWithUser"resultMap="orderMap">
SELECT * FROM orders o LEFT JOIN USER u ON o.uid = u.id
</select></mapper>
SELECT u.*,o.id oid,o.ordertime,o.total,o.uid FROM orders o RIGHTJOINUSER u ON o.uid = u.id;-- 或者SELECT*,o.id oid FROMUSER u LEFTJOIN orders o ON u.`id`= o.`uid`-- 其中前面的*就是代表所有了,那么后面的就是起一个别名
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mappernamespace="com.lagou.mapper.UserMapper"><!--一对多关联查询:查询所有的用户,同时还要查询出每个用户所关联的订单信息--><resultMapid="userMap"type="com.lagou.domain.User"><idproperty="id"column="id"></id><resultproperty="username"column="username"></result><resultproperty="birthday"column="birthday"></result><resultproperty="sex"column="sex"></result><resultproperty="address"column="address"></result><!--
可以多次对应,包括association,他们之间也可嵌套(包括自己)
collection : 一对多使用collection标签进行关联
通常操作的是集合
ofType泛型类型
注意:在上面相同的情况下,对应下面的信息会发在一个集合里
因为会检查,具体描述,当上面的字段内容都相同时,进行去重,即对应的下面内容放一个集合(合并)
不相同,则不会,若上面使用了对应id标签,那么就会对id进行去重,一样的,下面内容放一个集合
这个集合是第一个查到的没有去重的集合,那么说明,当出现第二个满足去重的集合时
将下面的内容放入第一个集合中,形成合并,而不相同的,可以将两个表的主键去掉,自己实验一下,我通过实验
只有当上面没有对应id标签,且上面字段内容有不一样的,那么后台查询时,会出现两个相同的id(因为条件是判断id的)
--><collectionproperty="ordersList"ofType="com.lagou.domain.Orders"><idproperty="id"column="oid"></id><!--通过起别名,使得同样的字段,不同了--><resultproperty="ordertime"column="ordertime"/><resultproperty="total"column="total"/><resultproperty="uid"column="uid"/></collection></resultMap><selectid="findAllWithOrder"resultMap="userMap">
SELECT u.*,o.id oid,o.ordertime,o.total,o.uid FROM orders o RIGHT JOIN USER u ON o.uid = u.id
</select></mapper>
SELECT u.*,r.id rid,r.rolename,r.roleDesc FROMUSER u LEFTJOIN sys_user_role ur ON ur.userid = u.id
LEFTJOIN sys_role r ON ur.roleid = r.id
-- 可以在上一个查询结果前,再次进行查询,from起作用,连接,select然后查询
<!--多对多关联查询:查询所有的用户,同时还要查询出每个用户所关联的角色信息--><resultMapid="userRoleMap"type="user"><idproperty="id"column="id"/><resultproperty="username"column="username"></result><resultproperty="birthday"column="birthday"></result><resultproperty="sex"column="sex"></result><resultproperty="address"column="address"></result><collectionproperty="roleList"ofType="role"><!--如果没有值,那么就是空值或者默认(真的没有值,不对的自然报错),而不是null--><idcolumn="rid"property="id"></id><resultcolumn="rolename"property="rolename"></result><resultcolumn="roleDesc"property="roleDesc"></result></collection></resultMap><selectid="findAllWithRole"resultMap="userRoleMap">
SELECT u.*,r.id rid,r.rolename,r.roleDesc FROM USER u LEFT JOIN sys_user_role ur ON ur.userid
= u.id
LEFT JOIN sys_role r ON ur.roleid = r.id
</select>
/*
如
需求:查询一个订单,与此同时查询出该订单所属的用户
联合查询:
SELECT * FROM orders o LEFT JOIN USER u ON o.`uid`=u.`id`;
嵌套查询:
先查询订单
SELECT * FROM orders
再根据订单uid 外键,查询用户
SELECT * FROM `user` WHERE id = #{根据订单查询的 uid}
最后使用mybatis,将以上二步嵌套起来
*/
一对一嵌套查询 :
需求:查询一个订单,与此同时查询出该订单所属的用户
sql语句:
//SELECT * FROM orders//SELECT * FROM user WHERE id = #{id}
SELECT*FROMUSERSELECT*FROM orders WHERE uid =#{uid}
<!--一对多嵌套查询:查询所有的用户,同时还要查询出每个用户所关联的订单信息--><resultMapid="userOrderMap"type="com.lagou.domain.User"><idproperty="id"column="id"/><resultproperty="username"column="username"></result><resultproperty="birthday"column="birthday"></result><resultproperty="sex"column="sex"></result><resultproperty="address"column="address"></result><!--
association和collection都可以使用select来再次进行语句执行,将结果赋值,一般的,都会将id作为参数
当然了,使用select和column通常情况下,不会再写sql语句,但若写的话
则会使用对应sql语句的结果,即自己写的不会进行赋值
对于association来说,字段赋值时,只会操作一个类,进行赋值,所以使用对应语句的话,基本全是该语句的赋值
对于collection来说,一般的会进行去重,但是使用对应sql语句,那么进行赋值时,没有去重(没有判断了)
他们的操作,都是在对应MappedStatement对象里操作,当指定对应位置时,就会通过反射执行对应语句
而下面的操作,实际上可以看成内部嵌套一个这个对象,再次反射执行,形成一个赋值,然后返回
--><collectionproperty="ordersList"ofType="com.lagou.domain.Orders"column="id"select="com.lagou.mapper.OrderMapper.findByUid"></collection><!--一般情况下,对应的参数column都是传递的一个的值,这里与其他不关联的是不同的--></resultMap><selectid="findAllWithOrder2"resultMap="userOrderMap">
SELECT * FROM USER
</select>
<selectid="findByUid"parameterType="int"resultType="com.lagou.domain.Orders">
SELECT * FROM orders WHERE uid = #{uid}
<!--后面基本可以继续加参数(对应的参数column都是传递的一个的值),当然,可能会报错,主要看自己的测试--></select>
SELECT*FROMUSERSELECT*FROM sys_role r INNERJOIN sys_user_role ur ON ur.roleid = r.id
WHERE ur.userid =#{uid}-- 对于数据来说,多对多其实也是一个一对多,但是对于表来说,就是多对多
<resultMapid="userRoleMap2"type="com.lagou.domain.User"><idproperty="id"column="id"/><resultproperty="username"column="username"></result><resultproperty="birthday"column="birthday"></result><resultproperty="sex"column="sex"></result><resultproperty="address"column="address"></result><!--注意:使用对应sql,就是自动赋值了,使用对应set方法执行
参数就是赋值的参数,没有对应的当然就是默认了
且会根据变量直接赋值,在Mybatis里是这样的,Mybatis会直接赋值,而一般的是不会的
实际上都是一个新的对象,所以没赋值就是默认值
--><collectionproperty="roleList"ofType="com.lagou.domain.Role"column="id"select="com.lagou.mapper.RoleMapper.findByUid"></collection><!--这个感觉就像没有去重一样,直接将查询的所有结果封装好--></resultMap><!--多对多嵌套查询:查询所有的用户,同时还要查询出每个用户所关联的角色信息--><selectid="findAllWithRole2"resultMap="userRoleMap2">
SELECT * FROM USER
</select>
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mappernamespace="com.lagou.mapper.RoleMapper"><selectid="findByUid"resultType="com.lagou.domain.Role"parameterType="int">
SELECT * FROM sys_role r INNER JOIN sys_user_role ur ON ur.roleid = r.id
WHERE ur.userid = #{uid}
</select></mapper>