背景:在博主做项目过程中遇到这样一个问题。
数据库建表模型:
如图可以看到,用户表泛化为住户与服务人员,泛化后根据自己的特性,生成独立的表。在建表过程中,用户表只用作登录处理,将与用户相关的属性等分别放置在住户表和服务人员表中,例如:真实姓名,电话号码等。
数据库建表如下:
用户表(登录表):
住户表:
服务人员表:
依据数据结构设计原则,将外键放置在住户表,服务人员表中=>(userId)。
需求要求后端界面要能够维护用户信息,其中要数据列表截图如下:
将住户数据与服务人员数据分别查询出来,然后再services层中合并成一个List集合返回给前端进行数据渲染。
创建VO类进行数据映射:
public class UserManagerVO {
//用户id
private Integer userId;
//用户名
private String userName;
//角色名称
private String roleName;
//真实姓名
private String realName;
//电话号码
private String telNum;
//注册时间
private Date registerTime;
//上次登录时间
private Date loginTime;
//上次退出时间
private Date logoutTime;
//用户状态
private String userState;
private Integer delState;
....//get、set方法
}
sql语句如下:
-- 查询服务人员表中满足情况的数据
SELECT
s.staffName realName,
s.telNum telNum,
u.userId userId,
u.userName userName,
u.registTime registerTime,
u.loginTime loginTime,
u.logoutTime logoutTime,
u.userState userState,
r.roleName roleName,
u.deleteState deleteState
FROM
t_staff s
JOIN t_user u ON s.userId = u.userId
JOIN r_user_role ur ON u.userId = ur.userId
JOIN t_role r ON r.roleId = ur.roleId
WHERE
u.deleteState = 1
-- 查询住户表中满足情况的数据
SELECT
i.inhabitantName realName,
i.telNum telnum,
u.userId userId,
u.userName userName,
u.registTime registerTime,
u.loginTime loginTime,
u.logoutTime logoutTime,
u.userState userState,
u.deleteState deleteState,
r.roleName roleName
FROM
t_inhabitant i
JOIN t_user u ON i.userId = u.userId
JOIN r_user_role ur ON u.userId = ur.userId
JOIN t_role r ON r.roleId = ur.roleId
WHERE
u.deleteState = 1
在Java的UserManagerVO的services层实现类中,分别调用mybatis中的db查询语句,将查询到的结果合并到一个List中,最后将这个List集合返回给前端进行渲染。(模糊查询等也用类似方法映射)
遇到问题:在进行分页查询的时候,数据查询并正确响应困难。使用上述方法时,会通过分页条件,分别查询,若前端要显示5条数据,则后端会响应10条,且若一方不足5条(<5)前端总条数不能处理。
问题思考:
创建视图:
CREATE VIEW view_userManager AS SELECT
u.userId userId,
u.userName userName,
u.registTime registerTime,
u.loginTime loginTime,
u.logoutTime logoutTime,
u.userState userState,
u.deleteState delState,
s.staffName realName,
s.telNum telNum,
r.roleName roleName
FROM
t_staff s
JOIN t_user u ON s.userId = u.userId
JOIN r_user_role ur ON u.userId = ur.userId
JOIN t_role r ON r.roleId = ur.roleId UNION all
SELECT
u.userId userId,
u.userName userName,
u.registTime registerTime,
u.loginTime loginTime,
u.logoutTime logoutTime,
u.userState userState,
u.deleteState delState,
i.inhabitantName realName,
i.telNum telNum ,
r.roleName roleName
FROM
t_inhabitant i
JOIN t_user u ON i.userId = u.userId
JOIN r_user_role ur ON u.userId = ur.userId
JOIN t_role r ON r.roleId = ur.roleId
注:在取别名的时候,需要将冲突的列名字段取别名为其他的字段。例如:三个表当中都有deleteState字段,名称相同,需要将查询的u.deleteState 命名为delState。
在mybatis的mapper映射文件中,使用视图进行查询以及分页操作:
<select id="selectUserManagerByLike" resultMap="userManagerVOMap">
select userId,userName,registerTime,loginTime
,logoutTime,userState,delState,realName,telNum
,roleName from view_userManager
where delState=1
<if test="telNum != null">
and telNum like concat('%',#{telNum},'%')
if>
<if test="realName != null">
and realName like concat('%',#{realName},'%')
if>
<if test="userState != null">
and userState like concat('%',#{userState},'%')
if>
<if test="roleName != null">
and roleName like concat('%',#{roleName},'%')
if>
<if test="pageIndex!=null and pageSize!=null">
limit #{pageIndex} , #{pageSize}
if>
select>
特别注意:
若视图是可更新的,则可以在诸如UPDATE、DELETE或INSERT等语句中使用它们,以更新基表的内容。对于可更新的视图,在视图中的行和基表中的行之间必须具有一对一的关系。
但在下述几种情况下,视图是不可更新的:
另外,若视图是基于多个表使用联接操作而导出的,且不满足上述条件,那么对这个视图执行更新操作时,每次只能影响其中的一个表,否则,更新操作也不能执行。
至此,博主遇到的问题解决。大家有更好的解决方案,欢迎留言栏交流。