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> 

​

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Mybatis-plus多表关联查询是指在使用Mybatis-plus框架进行数据库操作时,通过多个表之间的关联关系,实现一次性查询多个表中的数据。这种查询方式可以大大提高查询效率,减少数据库访问次数,提高系统性能。在Mybatis-plus中,可以使用注解或XML配置的方式实现多表关联查询,具体实现方式可以参考Mybatis-plus官方文档。 ### 回答2: MyBatis-Plus是基于MyBatis的增强工具,提供了很多实用的功能,其中包括了多表关联查询。在实际开发中,我们经常需要查询多个表的数据,此时就需要用到多表关联查询。下面介绍一下MyBatis-Plus多表关联查询的实现方法。 1.通过@TableName注解指定表名 在实体类上使用@TableName注解,可以指定当前实体类对应的表名,这样在进行多表关联查询时,就可以直接使用表名进行操作。示例代码如下: ``` @Data @TableName("t_user") public class User { @TableId(type = IdType.AUTO) private Long id; private String username; private String password; } ``` 2.使用Mapper中的方法进行多表关联查询 MyBatis-Plus提供了一些方法,可以进行多表关联查询。其中比较常用的方法是selectList()和selectPage()。这些方法可以通过Wrapper条件构造器指定查询条件,并且支持多表关联查询。示例代码如下: ``` public interface UserMapper extends BaseMapper<User> { @Select("select * from t_user u " + "left join t_role r on r.id = u.role_id " + "where u.id = #{id}") UserVO selectUserWithRole(Long id); @Select("select * from t_user u " + "left join t_role r on r.id = u.role_id " + "${ew.customSqlSegment}") List<UserVO> selectUserListWithRole(@Param(Constants.WRAPPER) Wrapper wrapper); } ``` 3.使用@Result注解映射查询结果 在使用Mapper中的方法进行多表关联查询时,我们可以使用@Result注解对查询结果进行映射,这样可以更方便地获取查询结果。示例代码如下: ``` public interface UserMapper extends BaseMapper<User> { @Select("select u.*, r.name as roleName from t_user u " + "left join t_role r on r.id = u.role_id " + "where u.id = #{id}") @Results({ @Result(column = "roleName", property = "roleName") }) UserVO selectUserWithRole(Long id); } ``` 总之,MyBatis-Plus多表关联查询使用起来非常方便,只需要在实体类中指定表名,使用Mapper中的方法进行查询,并使用@Result注解对查询结果进行映射即可。需要注意的是,在进行多表关联查询时,要确保关联的字段在两个表中是唯一的,并且要注意查询效率和查询结果的正确性。 ### 回答3: Mybatis-Plus是一个优秀的基于Mybatis的ORM框架,它极大地简化了开发人员的开发工作。在实际开发中,多表关联查询是常见的需求,Mybatis-Plus提供了多种方式支持多表关联查询。以下是几种常见的多表关联查询方式: 1.通过Join方式查询 使用Join语句可以在一个查询中查询多张表,从而实现多表关联查询,如下: ``` SELECT t1.*, t2.* FROM t1 INNER JOIN t2 ON t1.id = t2.t1_id ``` 如果需要使用Join方式查询,需要使用Mybatis-Plus的Wrapper类实现多表关联查询。 2.通过关联查询实现多表查询 如果需要实现包含关联实体的复杂查询,可以使用Mybatis-Plus提供的lambdaQuery方法。例如: ``` List<User> userList = userMapper.selectList(Wrappers .lambdaQuery(User.class) .eq(User::getStatus, 1) .nested(i -> i.eq(User::getName, "Tom") .or() .eq(User::getName, "Jerry")) .orderByAsc(User::getAge) .select(User::getId, User::getName, User::getAge, User::getEmail) .leftJoin(User.class, User::getId, UserRole::getUserId) .leftJoin(UserRole.class, UserRole::getRoleId, Role::getId) .select(UserRole::getRoleId, Role::getName) ) ``` 3.通过XML mapper方式查询 使用XML mapper文件可以实现多表关联查询。通过XML可以方便地实现复杂的多表查询。如下: ``` <select id="getUserRoleList" resultMap="BaseResultMap"> select ur.*, r.name as roleName from user_role ur left join role r on ur.role_id = r.id where ur.user_id = #{userId} </select> ``` 更多关于Mybatis-Plus多表关联查询,可以参考Mybatis-Plus官方文档或者相关博客文章。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值