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报错的主要内容,如果未能解决你的问题,请参考以下文章

sql 多表关联查询

ORACLE中如何多表关联查询。如有A、B、C三张表,A表字段a和B表字段b以及C表字段c关联,写出查询语句

sql mysql多表如何关联查询

mysql查询语句 和 多表关联查询 以及 子查询

多表之间关联查询

28.多表查询——跨关联关系的多表查询