当前位置:   article > 正文

解决Ruoyi框架面对联合主键时,无法正常修改和添加操作的问题---保姆级教程_利用若依框架构建页面时,非自增主键无法显示

利用若依框架构建页面时,非自增主键无法显示

情景描述:Ruoyi框架自动生成的代码,对应的只按照一个主键来进行操作,在面临多个或联合主键时,会出现操作上的误解。

推荐解决方法:调整后端接口逻辑。

问题阐述:

1、打开管理员后台,在页面内进行新增操作。(假设对应的联合主键表为:A)

发现只是将对应的修改。

2、直接在数据库中添加2条数据。选择修改,报错。

3、删除时,会直接将同id下的数据全部删除

问题定位

1、查看前端页面:(此处以一般生成的代码为例)

(1)定位到对应的.vue文件,一般在ruoyi-ui模块的src目录,views下

比如我的:ruoyi-ui/src/views/user_fill_content/user_content/index.vue

(2)找到对应的修改和增加代码区域:定位到JS逻辑处理区

(3)定位到submitForm()函数,发现是form的值来进行操作的,而form的获取由按钮处理操作来获取。

(4)我们发现,按钮处理操作是按照一个单独的id来判断,并非是双主键,问题所在。

(5)删除同理:

2、定位后端接口:

(1)找到<script>开头的import,crtl+左键,点进去。找url,选中末尾,crtl+左键

(2)下面以删除为例:查看对应的mapper.xml

(3)定位到删除:发现如猜测一样,单主键进行操作。比如我的:

  1. <delete id="deleteUserFillContentBySpecificEventId" parameterType="Long">
  2. delete from user_fill_content where specific_event_id = #{specificEventId}
  3. </delete>
  4. <!--我的表中,还有个user_id,联合做主键-->

解决步骤

1、在Mapper.xml文件中:

(这是各层示意图)

重写sql(建议重命名,以便区分):完成查找和删除的操作。

  1. <!--查找:id可以随便起,需要和mapper.java类中方法一致,-->
  2. <!--这里我parameterType用的Map,方便接口传递多个主键,且更直观。-->
  3. <!--在where 语句里把主键属性补上即可,比如我这两个属性:specificEventId与userId-->
  4. <select id="selectUserFillContentBySpecificEventIdAndUserId" parameterType="java.util.Map"
  5. resultMap="UserFillContentResult">
  6. <include refid="selectUserFillContentVo"/>
  7. where specific_event_id = #{specificEventId} and user_id = #{userId}
  8. </select>
  9. <delete id="deleteUserFillContentBySpecificEventIdAndUserId" parameterType="java.util.Map"
  10. delete from user_fill_content
  11. where specific_event_id = #{specificEventId} and user_id = #{userId}
  12. </delete>

限制修改操作的属性,注意此处。业务规则:主键部分不让修改

  1. <update id="updateUserFillContent" parameterType="com.ruoyi.act.user_fill_content.domain.UserFillContent">
  2. update user_fill_content
  3. <trim prefix="SET" suffixOverrides=",">
  4. <if test="specificFillContent != null and specificFillContent != ''">specific_fill_content = #{specificFillContent},</if>
  5. <!-- 注释掉这个主键 <if test="userId != null">user_id = #{userId},</if>-->
  6. <if test="formId != null">form_id = #{formId},</if>
  7. </trim>
  8. where specific_event_id = #{specificEventId} and user_id=#{userId}
  9. <!-- 依据联合主键来定位-->
  10. </update>

2、修改mapper.java文件:

  1. public int deleteUserFillContentBySpecificEventIdAndUserId(Map usermap);
  2. //把方法名称换为你在xml写的id
  3. public UserFillContent selectUserFillContentBySpecificEventIdAndUserId(Map userMap);

3、返回service层,在接口中新增方法:

        比如我的:IUserFillContentService

直接把上文添加的复制过来就可以。名称可以自定义,但建议保持和上文一致,注释可以不写。

  1. /**
  2. * 依据具体事件编号和用户id查询用户填写内容
  3. *
  4. * @param specificEventId 用户填写内容主键
  5. * userId 填写者编号
  6. * @return 用户填写内容
  7. */
  8. public UserFillContent selectUserFillContentBySpecificEventIdAndUserId(Map userMap);
  9. /**
  10. * 依据具体事件编号和用户id删除用户填写内容
  11. *
  12. * @param usermap 用户填写内容主键
  13. * @return 结果
  14. */
  15. public int deleteUserFillContentBySpecificEventIdAndUserId(Map usermap);

4、在impl中实现方法

比如我的:UserFillContentServiceImpl文件

  1. //方法的返回值,就是对应的Mapper文件中,我们新增的方法的返回值。直接xxMapper.就行
  2. //注意;方法返回值要保持一致。方法参数一直是Map
  3. @Override
  4. public int deleteUserFillContentBySpecificEventIdAndUserId(Map usermap) {
  5. return userFillContentMapper.deleteUserFillContentBySpecificEventIdAndUserId(usermap);
  6. }
  7. }
  8. @Override
  9. public UserFillContent selectUserFillContentBySpecificEventIdAndUserId(Map userMap) {
  10. return userFillContentMapper.selectUserFillContentBySpecificEventIdAndUserId(userMap);
  11. }

5、返回Controller层,添加接口

比如我的:UserFillContentController文件

  1. @ApiOperation("依据具体事件编号和用户id删除用户填写内容")
  2. //这是权限验证,可以注释掉不管@PreAuthorize("@ss.hasPermi('user_fill_content:user_content:remove')")
  3. @Log(title = "用户填写内容", businessType = BusinessType.DELETE)
  4. //日志相关
  5. @DeleteMapping("/{specificEventId}/{userId}")
  6. //写你的接口使用形式,这里直接对应的传递所有主键即可,比如我的specificEventId、userId
  7. //removeBySpeId_UserId为自定义名称
  8. public AjaxResult removeBySpeId_UserId(@PathVariable Long specificEventId,@PathVariable Long userId)
  9. //@PathVariable说明需要的参数,一共两个
  10. {
  11. HashMap<String, Object> userMap = new HashMap<>();
  12. userMap.put("specificEventId",specificEventId);
  13. userMap.put("userId",userId);
  14. //以map的形式存储,从而接收所有主键。
  15. return toAjax(userFillContentService.deleteUserFillContentBySpecificEventIdAndUserId(userMap));
  16. }
  17. @ApiOperation("依据具体事件编号和用户id获取用户填写内容详细信息")
  18. //@PreAuthorize("@ss.hasPermi('user_fill_content:user_content:query')")
  19. @GetMapping(value = "/{specificEventId}/{userId}")
  20. public AjaxResult getInfoBySpeId_UserId(@PathVariable("specificEventId") Long specificEventId,@PathVariable("userId") Long userId)
  21. {
  22. HashMap<String, Object> userMap = new HashMap<>();
  23. userMap.put("specificEventId",specificEventId);
  24. userMap.put("userId",userId);
  25. return success(userFillContentService.selectUserFillContentBySpecificEventIdAndUserId(userMap));
  26. }

6、在前端的src/api文件夹中,新增我们添加的接口

比如我的:user_content.js文件

  1. //依据具体事件编号和用户id获取用户填写内容详细信息
  2. export function getInfoBySpeId_UserId(specificEventId,userId) {
  3. return request({
  4. url: '/user_fill_content/user_content/' + specificEventId + '/' +userId,
  5. method: 'get'
  6. })
  7. }
  8. //这一步就是把上一步写的复制下
  9. //把名字和参数替换为你的即可
  10. // 依据具体事件编号和用户id删除用户填写内容
  11. export function removeBySpeId_UserId(specificEventId,userId) {
  12. return request({
  13. url: '/user_fill_content/user_content/' + specificEventId+ '/' +userId,
  14. method: 'delete'
  15. })
  16. }

7、返回前端vue文件中,修改相关逻辑

(1)引入新添加的接口,import导入:

import {removeBySpeId_UserId,  getInfoBySpeId_UserId} from  "@/api/user_fill_content/user_content";

(2)修改按钮操作的处理逻辑:

在data内定义一个数组,存储选择的id

  1. //在data内定义一个数组,用于选中时定位id
  2. data() {
  3. return {
  4. userIds: [], //定义的id
  5. }
  6. }

找到:handleSelectionChange()方法:进行userIds的数据获取

  1. // 多选框选中数据
  2. handleSelectionChange(selection) {
  3. this.ids = selection.map(item => item.specificEventId)
  4. this.userIds = selection.map(item => item.userId) //新增方法,和上一行类似
  5. this.single = selection.length !== 1
  6. this.multiple = !selection.length
  7. },

声明一个对象,用于存储另一个主键。同时更改接口的使用。

  1. /** 修改按钮操作 */
  2. handleUpdate(row) {
  3. this.reset();
  4. const specificEventId = row.specificEventId || this.ids
  5. const userId = row.userId || this.userIds //这是新添加的
  6. //将接口换为你写的get,比如我的为:getInfoBySpeId_UserId,获取准确的内容
  7. getInfoBySpeId_UserId(specificEventId, userId).then(res => {
  8. this.form = res.data;
  9. this.open = true;
  10. this.title = "修改用户填写内容";
  11. });

(3)修改删除逻辑:

  1. /** 删除按钮操作 */
  2. handleDelete(row) {
  3. const specificEventId = row.specificEventId || this.ids;
  4. const userId = row.userId || this.userIds;//这是新添加的
  5. this.$modal.confirm('是否确认删除用户填写内容编号为"' + specificEventId +'用户编号为:'+ userId + '"的数据项?').then(function () {
  6. //将接口换为你写的delete,比如我的为:removeBySpeId_UserId,定位准确的内容
  7. return removeBySpeId_UserId(specificEventId,userId);
  8. }).then(() => {
  9. this.getList();
  10. this.$modal.msgSuccess("删除成功");
  11. }).catch(() => {
  12. });
  13. },

(4)建议分开添加或修改用户填写内容对话框:

  1. v-if="title==='修改用户填写内容'"
  2. //在<el-dialog>标签内,替换为你的对应的操作title

对应的@click也更改下,一个添加、一个修改。

(5)完善添加、修改逻辑

  1. /** 添加按钮 */
  2. submitForm_add() {
  3. this.$refs["form"].validate(valid => {
  4. if (valid) {
  5. addUser_content(this.form).then(response => {
  6. this.$modal.msgSuccess("新增成功");
  7. this.open = false;
  8. this.getList();
  9. });
  10. }
  11. });
  12. },
  13. /** 修改按钮 */
  14. submitForm_update() {
  15. this.$refs["form"].validate(valid => {
  16. if (valid)) {
  17. updateUser_content(this.form).then(response => {
  18. this.$modal.msgSuccess("修改成功");
  19. this.open = false;
  20. this.getList();
  21. });
  22. }
  23. });
  24. },

8、保存后,刷新前后端,重新运行。

验证:

1、新增:

(1)添加前:

(2)添加后:

2、修改:

(1)选择修改

(2)修改之后

3、删除:

(1)选择删除

(2)删除后

验证完毕,整体符合正常使用的逻辑。因为整体书写花费时间比较长,可能有些地方存在遗漏,欢迎补充。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号