MyBatis select标签, 常用元素有:id、parameterType、resultType、resultMap等
id:配合Mapper的全限定名,联合成为一个唯一的标识,用户标识这条SQL。
parameterType:表示这条SQL接受的参数类型,可以是MyBatis系统定义或者自定义的别名
resultType:表示这条SQL返回的结果类型,与parameterType一样,可以是系统定义的别名,也可以是类的全限定名。
resultMap:它是映射器的引用,将执行强大的映射功能。resultMap也提供了自定义映射的POJO类型。
我们可以使用resultType和resultMap中的一个,但不能同时使用。
id在命名空间中唯一的标识符,可以被用来引用这条语句。parameterType将会传入这条语句的参数类的完全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过 TypeHandler 推断出具体传入语句的参数,默认值为 unset。resultType从这条语句中返回的期望类型的类的完全限定名或别名。注意如果是集合情形,那应该是集合可以包含的类型,而不能是集合本身。使用 resultType 或 resultMap,但不能同时使用。resultMap外部 resultMap 的命名引用。结果集的映射是 MyBatis 最强大的特性,对其有一个很好的理解的话,许多复杂映射的情形都能迎刃而解。使用 resultMap 或 resultType,但不能同时使用。一、resultType元素
resultType属性:要求结果集的列名和属性名必须要匹配, 若不匹配时,可以使用SQL语句的AS别名(不推荐) 或者 设置开启自动驼峰命名规则映射 或者使用 resultMap属性。
1、查询一条记录, 返回 POJO类 或者返回MyBatis封装好的 Map集合(key是列名称,value是列对应的值)
POJO类
public User getUser(Integer id);
select * from t_user where id = #{id}
User user = userMapper.getUser(1);
System.out.println(user);
----
User [id=1, username=admin, pazzword=172eee54aa664e9dd0536b063796e54e, state=1, regDate=Sun Oct 14 00:00:00 CST 2018]
Map集合(key是列名称,value是列对应的值)
public Map selectUserMap(int id);
select * from t_user where id = #{id}
Map userMap = userMapper.selectUserMap(1);
System.out.println(userMap);
----
{reg_date=2018-10-14 00:00:00.0, pazzword=172eee54aa664e9dd0536b063796e54e, id=1, state=1, username=admin}
2、查询所有结果,返回 List集合 和 Map集合
List集合
public List selectUserAll();
select * from t_user
List userlist = userMapper.selectUserAll();
System.out.println(Arrays.asList(userlist));
----
[[User [id=1, username=admin, pazzword=172eee54aa664e9dd0536b063796e54e, state=1, regDate=Sun Oct 14 00:00:00 CST 2018], User [id=2, username=user, pazzword=3be7f713d9321e812231bb838448385d, state=1, regDate=Mon Oct 15 00:00:00 CST 2018]]
Map集合
Map,Map中的key是User的id,Map的值是User对象,实现它的关键是我们要在接口的方法上加一个注解,告诉Mybatis用哪个字段做Map的key.
@MapKey("id")
public Map selectUserMap();
select * from t_user
Map userMap = userMapper.selectUserMap();
System.out.println(Arrays.asList(userMap));
----
[{1={reg_date=2018-10-14 00:00:00.0, pazzword=172eee54aa664e9dd0536b063796e54e, id=1, state=1, username=admin}, 2={reg_date=2018-10-15 00:00:00.0, pazzword=3be7f713d9321e812231bb838448385d, id=2, state=1, username=user}]
二、resultMap元素
使用场景很广泛:
- 字段有自定义的转化规则
- 复杂的多表查询
1、使用resultMap自定义数据库字段名称和JavaBean的属性名称的对应关系
public User getUser(Integer id);
select * from t_user where id = #{id}
User user = userMapper.getUser(1);
System.out.println(user);
----
User [id=1, username=admin, pazzword=172eee54aa664e9dd0536b063796e54e, state=1, regDate=Sun Oct 14 00:00:00 CST 2018]
2、使用resultMap实现关联查询 ( 类(引用)类型成员属性 )使用 association 标签
假设 一个用户对应一个角色,
1)使用 association标签实现关联查询, 两个表的重复字段通过别名识别
association 标签 :类(引用)类型成员属性映射 property - 对应属性名 javaType - 类的具体类型
public User getUser(Integer id);
select
t.id,
t.username,
t.pazzword,
t.state,
t.reg_date regDate,
r.id rid,
r.roleName,
r.state rstate
from t_user t, t_role r
where t.role_id = r.id and t.id = #{id}
User user = userMapper.getUser(1);
System.out.println(user);
----
User [id=1, username=admin, pazzword=172eee54aa664e9dd0536b063796e54e, state=1, regDate=Sun Oct 14 00:00:00 CST 2018, role=Role [id=1, roleName=超级管理员, state=0]]
2)使用 association标签分步实现关联查询(传递一个参数)
分步查询通常应用于关联表查询,将查询sql拆分,分步查询与关联表查询的不同:
从代码层面来说:关联表查询能够有效的简化代码编写逻辑,减小代码编写难度,同时避免BUG(代码多了,bug就多了);
而分步查询则能够增强代码的可用性
从功能上说:关联表查询毕竟只需要查询一次数据库,对于业务量较小的系统来说,效率更高,数据库压 力相对较小;
分步查询虽然需要多次查询数据,但是这也意味着能够更好地使用数据缓存服务,且缓存的 数据耦合度低,利用率高,而且单次查询效率很高,数据库压力较小(对于业务量较大的系统来说)。还有一点则是数据库锁的问题,毕竟关联查询是多表同时使用,分步查询每次只操作一个表。
role
public Role getRole(Integer id);
select * from t_role where id = #{id}
user
select::表明当前属性是调用select指定方法查出的结果 是XXXMapper.xml中namespace。方法名 column:指定将哪一列的值传给这个方法
public User getUser(Integer id);
select * from t_user where id = #{id}
User user = userMapper.getUser(1);
System.out.println(user);
----
User [id=1, username=admin, pazzword=172eee54aa664e9dd0536b063796e54e, state=1, regDate=Sun Oct 14 00:00:00 CST 2018, role=Role [id=1, roleName=超级管理员, state=0]]
3、使用resultMap实现关联查询 ( 集合 List/Set 类型成员属性 )使用 collection 标签
假设 一个角色对应多个用户,
1)使用 collection 标签实现关联查询, 两个表的重复字段通过别名识别
collection 标签 :集合类型成员属性映射 property - 对应属性名 ofType - 设置集合中存放的数据的类型
public Role getRoleOfUser(Integer id);
select
r.id,
r.rolename,
r.state,
t.id tid,
t.username,
t.pazzword,
t.state tstate,
t.reg_date regDate
from t_role r, t_user t
where r.id=t.role_id and r.id = #{id}
Role role = roleMapper.getRoleOfUser(1);
System.out.println(role);
----
Role [id=1, roleName=超级管理员, state=0, users=[User [id=1, username=admin, pazzword=172eee54aa664e9dd0536b063796e54e, state=1, regDate=Sun Oct 14 00:00:00 CST 2018], User [id=2, username=user, pazzword=3be7f713d9321e812231bb838448385d, state=1, regDate=Mon Oct 15 00:00:00 CST 2018]]]
2)使用 collection 标签分步实现关联查询(传递一个参数)
user
public List selectUserByRoleid(Integer roleId);
select * from t_user where role_id = #{roleId}
role
select - 对应属性名的实现接口.id名(即方法名) column - 传过去的数据库表的字段别名(无别名用列名)
public Role getRoleOfUser(Integer id);
select * from t_role where id = #{id}
在开发中
针对属性是单对象类型时,使用 association元素,通常直接使用多表查询操作,即内联查询
针对属性是集合对象类型时,使用 collection元素,通常使用延迟加载,即额外SQL查询
三、延迟加载(也称懒加载)Hibernate中,涉及到关联查询的时候,懒加载是默认就开启着的
延迟加载就是当在真正需要使用到数据时,才会发送SQL语句进行查询该数据。
MyBatis 默认关闭延迟加载,需要我们在全局配置文件里手动配置, 也可在sql映射文件设置。
lazyLoadingEnabled延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。true | falsefalseaggressiveLazyLoading当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载(参考lazyLoadTriggerMethods).true | falsefalse (true in ≤3.4.1)
jdbcTypeForNull当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。JdbcType 常量. 大多都为: NULL, VARCHAR and OTHEROTHERlazyLoadTriggerMethods指定哪个对象的方法触发一次延迟加载。用逗号分隔的方法列表。equals,clone,hashCode,toString开启的方法就是配置三个全局变量:
. 如果想单个开启或禁用延迟加载,可以使用fetchType属性来实现
fetchType="lazy" 表示使用懒加载 fetchType="eager"表示开启立即加载
四、分步查询传入多参数
不管是 association 标签还是 collection 标签,在分步查询的时候,都可以用column属性,给select指定的sql语句传入某列的值做参数,如果需要传入多个参数的话,可以把参数封装成Map对象,写成这个格式 column="{key1=column1,key2=column2}"。
key - 指接收参数的#{value} value值,
column1 - 指传入的数据库表的字段别名(无别名用列名)
把上面 二 -- 3 -- 2的实例, 业务改为, 查询 一个角色中的多用户state与role的state相同的user
use
public List selectUserByRoleid(Integer roleId, Integer rstate);
select * from t_user where role_id = #{roleId} and state = #{rstate}
role
public Role getRoleOfUser(Integer id);
select * from t_role where id = #{id}
Role role = roleMapper.getRoleOfUser(1);
System.out.println(role);
----
Role [id=1, roleName=超级管理员, state=0, users=[User [id=2, username=user, pazzword=3be7f713d9321e812231bb838448385d, state=0, regDate=Mon Oct 15 00:00:00 CST 2018]]]
不要注重实例业务, 学习其中知识点。
ends~