Java--Mybatis关联查询,多表同名字段导致SQL报错
Posted MinggeQingchun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java--Mybatis关联查询,多表同名字段导致SQL报错相关的知识,希望对你有一定的参考价值。
在Mybatis中用了PageHelper的时候如果遇到多表查询,尤其是关联查询(一对一,一对多)
某两张表或者多表中含有相同的列名,会导致:
1、一对多,多方会出现一个未明确定义列(主键名或者某个字段名相同时)
### The error may exist in file [/Users/XX/XXMapper.xml]
### The error may involve com.XX.mapper.LklmesStandardpropathMapper.XX-Inline
### The error occurred while setting parameters
### SQL: SELECT count(0) FROM user u LEFT JOIN role r ON u.role_id = r.role_id WHERE status = ?
### Cause: java.sql.SQLSyntaxErrorException: ORA-00918: 未明确定义列
; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: ORA-00918: 未明确定义列
]
2、同时采用了PageHelper时,会出现文明确定义列的问题( tmp_page.*这里
相当于有同的列),此时可以用别名 as 处理,如
select name as n, country as c from user;
SELECT TMP_PAGE.*, ROWNUM PAGEHELPER_ROW_ID FROM (
select u.user_id, u.dept_id, u.user_name, u.nick_name,
d.dept_id, d.parent_id, d.dept_name, d.status as dept_status,
r.role_id, r.role_name, r.status as role_status
from sys_user u
left join sys_dept d on u.dept_id = d.dept_id
left join sys_user_role ur on u.user_id = ur.user_id
left join sys_role r on r.role_id = ur.role_id
) TMP_PAGE
ORA-00918: column ambiguously defined
, Time: 0.010000s
这里要注意的是user 表,role表中都有role_id,status两个字段,因此select查询时
1、可以只查询 select u.user_id,u.user_name
from user u
left join role r on r.role_id = u.role_id ,则不需要去查询 u.role_id,导致和user表中的u.role_id重复报错
2、用别名明确指定哪些列属于哪些表,如 select * from user u ,使用u.status
<if test="status != null and status != ''">
and u.status = #status
</if>
如,有三张表:用户表user,部门表dept,权限表role
Mybatis 一对一,使用 association 标签
Mybatis 一对多,使用 collection 标签
association 标签有两种用法:join查询、嵌套查询
<?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="XX.SysUserMapper">
<!--user用户表映射-->
<resultMap type="SysUser" id="SysUserResult">
<id property="userId" column="user_id" />
<result property="deptId" column="dept_id" />
<result property="userName" column="user_name" />
<result property="nickName" column="nick_name" />
<result property="status" column="status" />
<association property="dept" column="dept_id" javaType="SysDept" resultMap="deptResult" />
<collection property="roles" javaType="java.util.List" resultMap="RoleResult" />
</resultMap>
<!--dept部门表映射-->
<resultMap id="deptResult" type="SysDept">
<id property="deptId" column="dept_id" />
<result property="parentId" column="parent_id" />
<result property="deptName" column="dept_name" />
<result property="status" column="dept_status" />
</resultMap>
<!--role权限表映射-->
<resultMap id="RoleResult" type="SysRole">
<id property="roleId" column="role_id" />
<result property="roleName" column="role_name" />
<result property="status" column="role_status" />
</resultMap>
<sql id="selectUserVo">
select u.user_id, u.dept_id, u.user_name, u.nick_name,
d.dept_id, d.parent_id, d.dept_name, d.status as dept_status,
r.role_id, r.role_name, r.status as role_status
from sys_user u
left join sys_dept d on u.dept_id = d.dept_id
left join sys_user_role ur on u.user_id = ur.user_id
left join sys_role r on r.role_id = ur.role_id
</sql>
<select id="selectUserList" parameterType="SysUser" resultMap="SysUserResult">
select u.user_id, u.dept_id, u.nick_name, u.user_name,
d.dept_name, d.leader
from sys_user u
left join sys_dept d on u.dept_id = d.dept_id
where u.del_flag = '0'
<if test="userName != null and userName != ''">
AND u.user_name like concat(concat('%',#userName),'%')
</if>
<if test="status != null and status != ''">
AND u.status = #status
</if>
<if test="deptId != null and deptId != 0">
AND (u.dept_id = #deptId OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE FIND_IN_SET(#deptId, ancestors) <![CDATA[ <> ]]> 0 ))
</if>
</select>
</mapper>
不使用中间表 sys_user_role,我们通过关键字 JOIN 类型也可实现关联
INNER JOIN:内连接,又叫等值连接,返回两个表中连接字段相等的行
LEFT JOIN:左连接,即使右表中没有匹配,也从左表返回所有的行
RIGHT JOIN:右连接,即使左表中没有匹配,也从右表返回所有的行
FULL JOIN:外连接,只要其中一个表中存在匹配,则返回;即返回两个表中的行:left join + right join
CROSS JOIN : 结果是笛卡尔积,就是第一个表的行数乘以第二个表的行数
关键字 on
数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表,然后再将这张临时表返回给用户
在使用 left jion 时,on 和 where 条件的区别如下:
(1) on 条件是在生成临时表时使用的条件,它不管 on 中的条件是否为真,都会返回左边表中的记录。
(2)where 条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有 left join 的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉。
<?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="XX.SysUserMapper">
<!--user用户表映射-->
<resultMap type="SysUser" id="SysUserResult">
<id property="userId" column="user_id" />
<result property="deptId" column="dept_id" />
<result property="userName" column="user_name" />
<result property="roleId" column="role_id" />
<result property="status" column="status" />
<association property="dept" column="dept_id" javaType="SysDept" resultMap="deptResult" />
<collection property="roles" javaType="java.util.List" resultMap="RoleResult" />
</resultMap>
<!--dept部门表映射-->
<resultMap id="deptResult" type="SysDept">
<id property="deptId" column="dept_id" />
<result property="parentId" column="parent_id" />
<result property="deptName" column="dept_name" />
<result property="status" column="dept_status" />
</resultMap>
<!--role权限表映射-->
<resultMap id="RoleResult" type="SysRole">
<id property="roleId" column="role_id" />
<result property="roleName" column="role_name" />
<result property="status" column="role_status" />
</resultMap>
<sql id="selectUserVo">
select u.user_id, u.dept_id, u.user_name, u.role_id,
d.dept_id, d.parent_id, d.dept_name, d.status as dept_status,
r.role_id, r.role_name, r.status as role_status
from sys_user u
left join sys_dept d on d.dept_id = u.dept_id
left join sys_role r on r.role_id = u.role_id
</sql>
<select id="selectUserList" parameterType="SysUser" resultMap="SysUserResult">
<if test="userName != null and userName != ''">
AND u.user_name like concat(concat('%',#userName),'%')
</if>
<if test="status != null and status != ''">
AND u.status = #status
</if>
</select>
</mapper>
以上是关于Java--Mybatis关联查询,多表同名字段导致SQL报错的主要内容,如果未能解决你的问题,请参考以下文章