Ibatis <dynamic> 标签 update 的相关问题总结

本文介绍如何在MyBatis中正确地使用动态SQL元素和ORM映射,包括定义字段类型、统一标点符号使用以及示例代码。通过具体案例说明如何避免常见错误并提高代码质量。

1.为了使用<dynamic >中 <isNotNull>和其他地方出现不必要的bug  我们在定义map 或者 TO时 将所有的类型都定义为原生态的类型,比如定义INTEGER。

2.在写语句时很容易引入很难察觉的错误 比如“ : ” ,和“ : ” .这两个字符在.java 文件里面会区别非常明显,但是在xml中,肉眼是看不出来的。所以尽量统一,将标点用半角英文。

3.所有出现字段的地方,尽可能精确的制定类型,虽然有些地方看起来写或者不写都可以正常运行,这样做可以减少出错的几率,减少后顾之忧。

4.贴出一段做范例。

TOMap:

[html]  view plain  copy
  1. <resultMap id="userTO" class="UserTO">  
  2.    <!--设置需要的数据表项与UserTO成员变量之间的对应关系  -->  
  3.    <result column="ID" jdbcType="int" javaType="java.lang.Integer" property="id"/>  
  4.    <result column="USERNAME" jdbcType="varchar" javaType="java.lang.String" property="username" />  
  5.    <result column="PASSWORD" jdbcType="varchar" javaType="java.lang.String" property="password"/>  
  6.    <result column="GENDER" jdbcType="Integer" javaType="java.lang.Integer" property="gender" />  
  7.    <result column="DATE_OF_BIRTH" jdbcType="date" javaType="java.util.Date" property="dateOfBirth"/>  
  8.    <result column="CREATED_DATE" jdbcType="datetime" javaType="java.util.Date" property="createdDate" />  
  9.    <result column="IMAGE_ID" jdbcType="Integer" javaType="java.lang.Integer" property="imageId"/>  
  10.  </resultMap>  


SQL:

[html]  view plain  copy
  1. <update id="updateUserinfoById" parameterClass="UserTO " >  
  2.     update USER  
  3.     <dynamic prepend="set">  
  4.       <isNotNull prepend="," property="password">PASSWORD = #password: VARCHAR#</isNotNull>  
  5.       <isNotNull prepend="," property="gender">GENDER = #gender: INTEGER#</isNotNull>   
  6.       <isNotNull prepend="," property="dateOfBirth">DATE_OF_BIRTH = #dateOfBirth: TIMESTAMP#</isNotNull>   
  7.       <isNotNull prepend="," property="imageId">IMAGE_ID = #imageId: INTEGER#</isNotNull>  
  8.       <isNotNull prepend="," property="status">STATUS = #status: INTEGER#</isNotNull>   
  9.     </dynamic>   
  10.     where ID=#id: INTEGER#  
  11.   </update>  

TO:

[html]  view plain  copy
  1. public class UserTO implements Constant {  
  2.   
  3.     private Integer id;  
  4.   
  5.     private String username;  
  6.   
  7.     private String password;  
  8.   
  9.     private Integer gender;  
  10.   
  11.     private Integer imageId;  
  12.   
  13.     private Date dateOfBirth;  
  14.   
  15.     private Date createdDate;  


如果可以,可以做两套TO,一个作为参数,另一个TO作为返回值。这里就不举例了。

<template> <div class="login-container"> <el-card class="box-card"> <div class="login-body"> <div class="login-title" @click="toIndex"> <img src="@/assets/03.png" style=" width: 40px; height: 40px; margin: 5px 5px -5px 0; -webkit-user-drag: none; -khtml-user-drag: none; -moz-user-drag: none; user-drag: none; " /> <b style="color: black;display: inline-block; margin-bottom: 20px;font-size: 28px;"> 区块链数据溯源平台 </b> </div> <el-form ref="form" :model="userForm" :rules="rules" label-width="0px"> <!-- 手机号输入框 --> <el-input placeholder="请输入手机号码..." v-model="userForm.accountNumber" class="login-input" maxlength="11" > <template slot="prepend"> <div class="iconfont icon-r-user2" style="font-size: 24px;"></div> </template> </el-input> <!-- 密码输入框:参数名改为password,与后端匹配 --> <el-input placeholder="请输入密码..." v-model="userForm.password" <!-- 从userPassword改为password --> class="login-input" @keyup.enter.native="login" show-password > <template slot="prepend"> <div class="iconfont icon-r-lock" style="font-size: 24px;"></div> </template> </el-input> <div class="login-submit"> <el-button type="primary" @click="login"> 登录</el-button> <el-button type="warning" autocomplete="off" @click="$router.push('/sign-in')" style="margin-left: 20px"> 注册</el-button> </div> <div class="other-submit"> <router-link to="/login-admin" class="sign-in-text"> 管理员登录</router-link> </div> </el-form> </div> </el-card> </div> </template> <script> export default { name: "login", data() { return { // 表单数据:密码参数名从userPassword改为password userForm: { accountNumber: '', password: '' // 与后端接口参数名一致 }, // 简单表单验证(可选,增强用户体验) rules: { accountNumber: [ { required: true, message: '请输入手机号', trigger: 'blur' }, { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号格式', trigger: 'blur' } ], password: [ { required: true, message: '请输入密码', trigger: 'blur' }, { min: 6, message: '密码长度不能少于6位', trigger: 'blur' } ] } }; }, methods: { async login() { // 先验证表单(可选) this.$refs.form.validate(async (valid) => { if (!valid) return; try { // 调用登录接口:参数名与后端匹配(accountNumber和password) const res = await this.$api.userLogin({ accountNumber: this.userForm.accountNumber, password: this.userForm.password // 传递正确的参数名 }); console.log("登录响应:", res); // 后端Result类中成功的code是200,而非status_code if (res.code == 200) { // 修正判断条件 // 处理登录时间(如果需要) if (res.data && res.data.signInTime) { res.data.signInTime = res.data.signInTime.substring(0, 10); } // 保存用户信息到全局 this.$globalData.userInfo = res.data; // 跳转到首页 this.$router.replace('/index'); } else { // 后端返回错误信息(如账号密码错误) this.$message.error(res.msg || "登录失败"); } } catch (e) { console.error("登录请求失败:", e); // 网络错误或服务器异常处理 this.$message.error("服务器异常,请稍后重试"); } }); }, toIndex() { this.$router.replace({ path: '/index' }); } } } </script> <style scoped> /* 样式保持不变 */ .login-container { display: flex; justify-content: center; align-items: center; height: 100vh; width: 100%; position: fixed; top: 0; left: 0; width: 100%; overflow-y: auto; height: 100%; background: url("../../assets/background.jpg") center top / cover no-repeat; } .login-body { padding: 30px; width: 300px; height: 100%; } .login-title { padding-bottom: 30px; text-align: center; font-weight: 600; font-size: 20px; color: #409EFF; cursor: pointer; } .login-input { margin-bottom: 20px; } .login-submit { margin-top: 20px; display: flex; justify-content: center; } .sign-in-container { padding: 0 10px; } .sign-in-text { color: #409EFF; font-size: 16px; text-decoration: none; line-height: 28px; } .other-submit { display: flex; justify-content: space-between; margin-top: 30px; margin-left: 200px; } </style> package com.flea.fleabackend.controller; import com.flea.fleabackend.entity.ShUser; import com.flea.fleabackend.service.IShUserService; import com.flea.fleabackend.util.Result; import org.springframework.web.bind.annotation.*; import jakarta.validation.Valid; import org.springframework.validation.BindingResult; // 控制器根路径改为 "/user"(与前端请求的 "/user/sign-in" 匹配) @RestController @RequestMapping("/user") public class ShUserController { private final IShUserService userService; public ShUserController(IShUserService userService) { this.userService = userService; } // 注册接口:路径改为 "/sign-in"(与前端url完全一致) @PostMapping("/sign-in") public Result<?> userRegister( @Valid @RequestBody ShUser user, BindingResult bindingResult ) { // 参数校验失败的反馈 if (bindingResult.hasErrors()) { String errorMsg = bindingResult.getFieldError().getDefaultMessage(); return Result.error("注册失败:" + errorMsg); } // 执行注册逻辑 boolean success = userService.userRegister(user); return success ? Result.success("注册成功") : Result.error("账号已存在或注册信息不完整"); } // 登录接口:同步匹配前端的 "/user/login" 请求 @GetMapping("/login") public Result<?> userLogin( @RequestParam String accountNumber, @RequestParam String userPassword // 参数名从userPassword改为password ) { // 服务层调用时使用修改后的参数名password ShUser user = userService.userLogin(accountNumber, userPassword); return user != null ? Result.success(user, "登录成功") : Result.error("账号或密码错误"); } // 其他接口(如getUserInfo)也需同步调整路径,例如: @GetMapping("/info") public Result<?> getUserInfo(@RequestParam Long id) { ShUser user = userService.getUserById(id); return user != null ? Result.success(user) : Result.error("查询用户信息失败"); } } package com.flea.fleabackend.entity; import lombok.Data; import java.time.LocalDateTime; import jakarta.validation.constraints.NotBlank; @Data public class ShUser { private Long id; // 对应前端的“账号”输入框(字段名:accountNumber) @NotBlank(message = "账号(手机号)不能为空") // @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确") private String accountNumber; // 对应前端的“密码”输入框(字段名:userPassword) @NotBlank(message = "密码不能为空") // @Pattern(regexp = "^[a-zA-Z0-9]{6,16}$", message = "密码需为6-16位数字或字母") private String userPassword; // 对应前端的“昵称”输入框(字段名:nickname) @NotBlank(message = "昵称不能为空") private String nickname; private String avatar; private LocalDateTime signInTime; private Integer userStatus; } package com.flea.fleabackend.mapper; import com.flea.fleabackend.entity.ShUser; import org.apache.ibatis.annotations.*; @Mapper public interface ShUserMapper { // 根据账号(手机号)查询用户 @Select("SELECT * FROM sh_user WHERE account_number = #{accountNumber}") ShUser selectByAccountNumber(String accountNumber); // 根据id查询用户 @Select("SELECT * FROM sh_user WHERE id = #{id}") ShUser selectById(Long id); // 注册用户(修复密码参数映射) @Insert("INSERT INTO sh_user(" + "account_number, " + "user_password, " + // 数据库字段 "nickname, " + "avatar, " + "sign_in_time, " + "user_status" + ") VALUES(" + "#{accountNumber}, " + "#{userPassword}, " + // 匹配实体类字段userPassword "#{nickname}, " + "#{avatar}, " + "#{signInTime}, " + "0" + ")") @Options(useGeneratedKeys = true, keyProperty = "id") // 获取自增ID int insert(ShUser user); // 更新用户信息 @Update("UPDATE sh_user SET nickname = #{nickname}, avatar = #{avatar} WHERE id = #{id}") int updateInfo(ShUser user); // 封禁用户 @Update("UPDATE sh_user SET user_status = 1 WHERE id = #{id}") int banUser(Long id); } package com.flea.fleabackend.service.impl; import com.flea.fleabackend.entity.ShUser; import com.flea.fleabackend.mapper.ShUserMapper; import com.flea.fleabackend.service.IShUserService; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; /** * 用户服务实现类:解决账密错误、空指针问题 */ @Service public class ShUserServiceImpl implements IShUserService { private final ShUserMapper shUserMapper; // 构造函数注入(Spring推荐方式) public ShUserServiceImpl(ShUserMapper shUserMapper) { this.shUserMapper = shUserMapper; } /** * 登录逻辑优化: * 1. 严格参数校验(避免空值/空字符串) * 2. 适配数据库明文密码验证 * 3. 完善空值判断,避免空指针 */ @Override public ShUser userLogin(String accountNumber, String password) { // 1. 严格校验入参(空值/空字符串都拒绝) if (!StringUtils.hasText(accountNumber) || !StringUtils.hasText(password)) { return null; // 入参无效,直接返回null(对应账密错误) } // 2. 根据账号查询用户(确保Mapper的SQL字段正确) ShUser user = shUserMapper.selectByAccountNumber(accountNumber.trim()); // trim去除空格 // 3. 密码验证(多层空值判断,适配明文密码) if (user == null) { return null; // 账号不存在 } if (!StringUtils.hasText(user.getUserPassword())) { return null; // 数据库中密码为空,验证失败 } // 明文密码对比(与数据库存储一致) if (password.trim().equals(user.getUserPassword().trim())) { // 4. 额外校验用户状态(0=正常,1=封禁) if (user.getUserStatus() == 1) { return null; // 账号被封禁,返回null } return user; // 登录成功 } return null; // 密码错误 } @Override public boolean userRegister(ShUser user) { // 注册参数校验 if (user == null || !StringUtils.hasText(user.getAccountNumber()) || !StringUtils.hasText(user.getUserPassword()) || !StringUtils.hasText(user.getNickname())) { return false; } // 检查账号是否已存在 ShUser existingUser = shUserMapper.selectByAccountNumber(user.getAccountNumber().trim()); if (existingUser != null) { return false; // 账号已存在 } // 注册时密码明文存储(与登录逻辑一致) user.setAccountNumber(user.getAccountNumber().trim()); user.setUserPassword(user.getUserPassword().trim()); return shUserMapper.insert(user) > 0; } @Override public ShUser getUserById(Long id) { if (id == null) { return null; } return shUserMapper.selectById(id); } @Override public boolean updateUserInfo(ShUser user) { if (user == null || user.getId() == null || !StringUtils.hasText(user.getNickname())) { return false; } return shUserMapper.updateInfo(user) > 0; } @Override public boolean banUser(Long userId) { if (userId == null) { return false; } return shUserMapper.banUser(userId) > 0; } } // filePath: com/flea/fleabackend/service/IShUserService.java package com.flea.fleabackend.service; import com.flea.fleabackend.entity.ShUser; public interface IShUserService { // 用户登录(手机号+密码) ShUser userLogin(String accountNumber, String password); // 用户注册(账号唯一性校验) boolean userRegister(ShUser user); // 根据ID查询用户 ShUser getUserById(Long id); // 更新用户信息(昵称、头像) boolean updateUserInfo(ShUser user); // 封禁用户(管理员操作) boolean banUser(Long userId); } <?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"> <!-- namespace必须和ShUserMapper接口的全路径一致 --> <mapper namespace="com.flea.fleabackend.mapper.ShUserMapper"> <!-- 通用结果集映射:解决数据库字段与实体类属性映射问题 --> <resultMap id="ShUserResultMap" type="com.flea.fleabackend.entity.ShUser"> <id column="id" property="id"/> <result column="account_number" property="accountNumber"/> <!-- 数据库字段→实体类属性 --> <result column="user_password" property="userPassword"/> <result column="nickname" property="nickname"/> <result column="avatar" property="avatar"/> <result column="sign_in_time" property="signInTime"/> <result column="user_status" property="userStatus"/> </resultMap> <!-- 根据账号查询用户(登录核心SQL) --> <select id="selectByAccountNumber" parameterType="String" resultMap="ShUserResultMap"> SELECT id, account_number, user_password, nickname, avatar, sign_in_time, user_status FROM sh_user WHERE account_number = #{accountNumber} <!-- 与数据库字段一致 --> <!-- 假设有逻辑删除字段,没有则删除该条件 --> </select> <!-- 根据ID查询用户 --> <select id="selectById" parameterType="Long" resultMap="ShUserResultMap"> SELECT id, account_number, user_password, nickname, avatar, sign_in_time, user_status FROM sh_user WHERE id = #{id} AND is_deleted = 0 </select> <select id="selectByPage" parameterType="map" resultType="com.flea.fleabackend.entity.ShIdleItem"> SELECT * FROM sh_idle_item WHERE status = 1 <!-- 1=已发布状态 --> LIMIT #{offset}, #{size} </select> <select id="selectTotalCount" resultType="int"> SELECT COUNT(*) FROM sh_idle_item WHERE status = 1 </select> <select id="selectByLabel" parameterType="map" resultType="com.flea.fleabackend.entity.ShIdleItem"> SELECT * FROM sh_idle_item WHERE status = 1 AND idle_label = #{idleLabel} LIMIT #{offset}, #{size} </select> <select id="selectCountByLabel" parameterType="string" resultType="int"> SELECT COUNT(*) FROM sh_idle_item WHERE status = 1 AND idle_label = #{idleLabel} </select> <!-- 新增用户(注册) --> <insert id="insert" parameterType="com.flea.fleabackend.entity.ShUser"> INSERT INTO sh_user ( account_number, user_password, nickname, avatar, sign_in_time, user_status ) VALUES ( #{accountNumber}, #{userPassword}, #{nickname}, #{avatar}, #{signInTime}, #{userStatus} ) </insert> <!-- 更新用户信息 --> <update id="updateInfo" parameterType="com.flea.fleabackend.entity.ShUser"> UPDATE sh_user <set> <if test="nickname != null and nickname != ''">nickname = #{nickname},</if> <if test="avatar != null and avatar != ''">avatar = #{avatar},</if> <if test="userStatus != null">user_status = #{userStatus}</if> </set> WHERE id = #{id} AND is_deleted = 0 </update> <!-- 封禁用户(修改状态) --> <update id="banUser" parameterType="Long"> UPDATE sh_user SET user_status = 1 <!-- 1=封禁状态 --> WHERE id = #{userId} AND is_deleted = 0 </update> </mapper> server: port: 80 spring: # 数据库配置(修改为你的本地数据库信息) datasource: url: jdbc:mysql://localhost:3306/flea_market?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true username: root # 你的MySQL用户名(默认root) password: 123456 # 你的MySQL密码(自己设置的) driver-class-name: com.mysql.cj.jdbc.Driver # MyBatis-Plus配置(可选,优化体验) mybatis-plus: mapper-locations: classpath:mapper/*.xml # 若有XML映射文件,指定路径 type-aliases-package: com.flea.fleabackend.entity # 实体类别名包 configuration: map-underscore-to-camel-case: true # 下划线转驼峰(如数据库字段user_name → 实体类userName) log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印SQL日志(方便调试) <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!-- Spring Boot父工程(统一管理版本) --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.10</version> <relativePath/> </parent> <!-- 项目信息 --> <groupId>com.flea</groupId> <artifactId>flea-backend</artifactId> <version>0.0.1-SNAPSHOT</version> <name>flea-backend</name> <description>Flea 二手交易平台后端</description> <!-- 全局属性 --> <properties> <java.version>21</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <!-- 【关键】配置国内Maven镜像(阿里云),解决依赖下载失败问题 --> <repositories> <repository> <id>aliyunmaven</id> <url>https://maven.aliyun.com/repository/public</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>aliyunmaven</id> <url>https://maven.aliyun.com/repository/public</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </pluginRepository> </pluginRepositories> <!-- 核心依赖 --> <dependencies> <!-- Web核心依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- MyBatis整合依赖 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>3.0.3</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.5</version> </dependency> <!-- MySQL驱动 --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <!-- Lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!-- 参数校验依赖(解决@Valid报错) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <!-- 测试依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <!-- 构建配置 --> <build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*</include> </includes> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> </resources> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build> </project> CREATE DATABASE IF NOT EXISTS flea_market CHARACTER SET utf8 COLLATE utf8_general_ci; USE flea_market; DROP TABLE IF EXISTS `sh_address`; CREATE TABLE `sh_address` ( `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '自增主键', `consignee_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '收货人姓名', `consignee_phone` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '收货人手机号', `province_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '省', `city_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '市', `region_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '区', `detail_address` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '详细地址', `default_flag` tinyint(0) NOT NULL COMMENT '是否默认地址', `user_id` bigint(0) NOT NULL COMMENT '用户主键id', PRIMARY KEY (`id`) USING BTREE, INDEX `user_id_index`(`user_id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 31 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; -- ---------------------------- -- Records of sh_address -- ---------------------------- -- ---------------------------- -- Table structure for sh_admin -- ---------------------------- DROP TABLE IF EXISTS `sh_admin`; CREATE TABLE `sh_admin` ( `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '自增主键', `account_number` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '管理员账号', `admin_password` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '密码', `admin_name` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '管理员名字', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `account_number`(`account_number`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; -- ---------------------------- -- Records of sh_admin -- ---------------------------- INSERT INTO `sh_admin` VALUES (1, 'admin', '123456', '管理员'); -- ---------------------------- -- Table structure for sh_favorite -- ---------------------------- DROP TABLE IF EXISTS `sh_favorite`; CREATE TABLE `sh_favorite` ( `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '自增主键id', `create_time` datetime NOT NULL COMMENT '加入收藏的时间', `user_id` bigint(0) NOT NULL COMMENT '用户主键id', `idle_id` bigint(0) NOT NULL COMMENT '物主键id', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `user_id`(`user_id`, `idle_id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 48 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; -- ---------------------------- -- Records of sh_favorite -- ---------------------------- INSERT INTO `sh_favorite` VALUES (48, '2023-12-09 12:32:39', 11, 113); -- ---------------------------- -- Table structure for sh_idle_item -- ---------------------------- DROP TABLE IF EXISTS `sh_idle_item`; CREATE TABLE `sh_idle_item` ( `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '自增主键', `idle_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '物名称', `idle_details` varchar(2048) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '详情', `picture_list` varchar(1024) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '图集', `idle_price` decimal(10, 2) NOT NULL COMMENT '价格', `idle_place` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '发货地区', `idle_label` int(0) NOT NULL COMMENT '分类标签', `release_time` datetime NOT NULL COMMENT '发布时间', `idle_status` tinyint(0) NOT NULL COMMENT '状态(发布1、下架2、删除0)', `user_id` bigint(0) NOT NULL COMMENT '用户主键id', PRIMARY KEY (`id`) USING BTREE, INDEX `user_id_index`(`user_id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 105 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; DROP TABLE IF EXISTS `sh_message`; CREATE TABLE `sh_message` ( `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '自增主键', `user_id` bigint(0) NOT NULL COMMENT '用户主键id', `idle_id` bigint(0) NOT NULL COMMENT '主键id', `content` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '留言内容', `create_time` datetime NOT NULL COMMENT '留言时间', `to_user` bigint(0) NOT NULL COMMENT '所回复的用户', `to_message` bigint(0) NULL DEFAULT NULL COMMENT '所回复的留言', PRIMARY KEY (`id`) USING BTREE, INDEX `user_id_index`(`user_id`) USING BTREE, INDEX `idle_id_index`(`idle_id`) USING BTREE, INDEX `to_user_index`(`to_user`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 48 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; -- ---------------------------- -- Records of sh_message -- ---------------------------- -- ---------------------------- -- Table structure for sh_order -- ---------------------------- DROP TABLE IF EXISTS `sh_order`; CREATE TABLE `sh_order` ( `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '自增主键', `order_number` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '订单编号', `user_id` bigint(0) NOT NULL COMMENT '用户主键id', `idle_id` bigint(0) NOT NULL COMMENT '物品主键id', `order_price` decimal(10, 2) NOT NULL COMMENT '订单总价', `payment_status` tinyint(0) NOT NULL COMMENT '支付状态', `payment_way` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '支付方式', `create_time` datetime NOT NULL COMMENT '创建时间', `payment_time` datetime NULL DEFAULT NULL COMMENT '支付时间', `order_status` tinyint(0) NOT NULL COMMENT '订单状态', `is_deleted` tinyint(0) NULL DEFAULT NULL COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 86 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; -- ---------------------------- -- Records of sh_order -- ---------------------------- -- ---------------------------- -- Table structure for sh_order_address -- ---------------------------- DROP TABLE IF EXISTS `sh_order_address`; CREATE TABLE `sh_order_address` ( `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '自增id', `order_id` bigint(0) NOT NULL COMMENT '订单id', `consignee_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '收货人', `consignee_phone` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '电话', `detail_address` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '收货地址', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `orderId`(`order_id`) USING BTREE, INDEX `order_id_index`(`order_id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 23 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; -- ---------------------------- -- Records of sh_order_address -- ---------------------------- -- Table structure for sh_type -- ---------------------------- DROP TABLE IF EXISTS `sh_type`; CREATE TABLE `sh_type` ( `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '主键', `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '分类名称', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin COMMENT = '类别表' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of sh_type -- ---------------------------- -- ---------------------------- -- Table structure for sh_user -- ---------------------------- DROP TABLE IF EXISTS `sh_user`; CREATE TABLE `sh_user` ( `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '自增主键', `account_number` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '账号(手机号)', `user_password` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '登录密码', `nickname` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '昵称', `avatar` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '头像', `sign_in_time` datetime NOT NULL COMMENT '注册时间', `user_status` tinyint(0) NULL DEFAULT NULL COMMENT '状态(1代表封禁)', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `account_number`(`account_number`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; 根据代码帮我找出为什么平台登录成功后无法自动跳转至index页面的原因 并且展示修改后能解决报错的完整代码
最新发布
12-08
实验02 Mybatis框架:基本配置及应用 【实验目的及要求】 1.了解Mybatis框架的基本工作原理; 2.熟悉Mybatis框架的核心对象; 3.掌握在Mybatis框架中,数据库单个表的访问方法; 4.要求所有回答的文本格式:五号,宋体、1.5倍行距,保留原来的单元格背景。 【实验步骤】 1、启动MySQL数据库服务器,执行下列脚本,创建ssmtest数据库,做好数据库访问前的准备工作。注意,sql脚本放入记事本中保存时,应采用ansi编码方式。 CREATE DATABASE ssmtest CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; use ssmtest; SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- 登录日志表 DROP TABLE IF EXISTS `login_log`; CREATE TABLE `login_log` ( `log_id` int NOT NULL AUTO_INCREMENT COMMENT '日志id', `user_id` int NULL DEFAULT NULL COMMENT '用户id', `login_time` datetime NULL DEFAULT NULL COMMENT '登录时间', `login_ip` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '登录ip', `device_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '设备类型(android:安卓;ios:苹果;pc:电脑;pad:平板)', `login_result` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '登录结果(1:成功;0:失败)', `fail_result` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '登录失败原因(password_error:密码错误;sms_expire:验证码过期;account_locked:账号被锁定)', `login_location` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '登录地域(省市区)', PRIMARY KEY (`log_id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; -- 插入登录数据 INSERT INTO `login_log` VALUES (1, 1, '2025-09-16 21:47:44', '192.168.10.2', 'pc', '1', NULL, '江西省宜春市袁州区'); INSERT INTO `login_log` VALUES (2, 1, '2025-09-18 23:47:23', '192.168.100.65', 'phone', '1', NULL, '江西省南昌市青山湖区'); INSERT INTO `login_log` VALUES (3, 1, '2025-09-19 21:49:12', '192.168.10.2', 'pc', '0', 'password_error', '江西省宜春市袁州区'); INSERT INTO `login_log` VALUES (4, 1, '2025-09-19 21:50:47', '192.168.10.2', 'pc', '0', 'account_locked', '江西省宜春市袁州区'); INSERT INTO `login_log` VALUES (5, 1, '2025-09-19 21:52:17', '192.168.10.2', 'pc', '1', NULL, '江西省宜春市袁州区'); -- 用户表 DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `user_id` int NOT NULL AUTO_INCREMENT COMMENT '用户id', `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户名', `password` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '密码', `full_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '姓名', `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账户状态(1:启用;0:停用)', `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', PRIMARY KEY (`user_id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; -- 插入用户数据 INSERT INTO `user` VALUES (1, 'admin', '123456', '管理员', '1', '2025-09-16 21:46:25'); SET FOREIGN_KEY_CHECKS = 1; 2、访问ssmtest 数据库 (1)在IntelliJ IDEA中新建一个Maven项目,取名为experiment_mybatis01,包结构为com.ycusoft.experiment。如果缺少resources目录,则自己加上去。 (2)在pom.xml文件中声明3个依赖,mybatis(MyBatis框架)、mysql-connector-java(MySQL驱动)和junit(单元测试)。若想获得更多的依赖信息或采用不同的版本,可以在https://mvnrepository.com站点中,通过检索关键字获得。 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.ycusoft</groupId> <artifactId>experiment_mybatis01</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.9</version> </dependency> <!-- https://mvnrepository.com/artifact/junit/junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <!-- 根据使用的数据库版本选择对应版本的驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency> </dependencies> </project> (3)右击pom.xml文件,选择Maven\Reimport菜单项,启动构件下载,将上述3个构件从远程仓库中下载至本地仓库。 (4)在resources目录下创建config文件夹,并在其下创建数据库配置文件db.properties及mybatis配置文件mybatis-config.xml。(根据红色注释补全内容)(10分) db.properties(示例,把自己的复制进来,原来的覆盖) db.driver=com.mysql.cj.jdbc.Driver # 根据数据库版本选择驱动 db.url=jdbc:mysql://localhost:3306/ssmtest?useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai db.username=root db.password=yourpassword # 替换成自己的密码 Mybatis-config.xml(示例,把自己的复制进来,原来的覆盖) <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!—加载db.properties --> <!—配置开启驼峰映射,即数据库下划线字段名与Java驼峰命名映射--> <!—配置com.ycusoft.experiment.entity 包中所有类的类型别名--> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${db.driver}"/> <property name="url" value="${db.url}"/> <property name="username" value="${db.username}"/> <property name="password" value="${db.password}"/> </dataSource> </environment> </environments> <!—注册com.ycusoft.experiment.mapper 包中所有映射文件接口--> </configuration> (5)在src\main\java\com\ycusoft\experiment目录中,新建utils包,并在该包下新建MybatisUtil类,用于构造会话对象。代码如下: MyBatisUtil.java package com.ycusoft.experiment; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.Reader; public class MyBatisUtil { private static SqlSessionFactory sqlSessionFactory = null; static { try { Reader reader = Resources.getResourceAsReader("config/mybatis-config.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); } catch (Exception e) { e.printStackTrace(); } } public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); } } (6)在src\main\java\com\ycusoft\experiment目录中新建entity包,并创建User类和LoginLog类。代码如下:(请保持Java Bean的属性和数据表中字段间的一致): public class User { private Integer userId; private String username; private String password; private String fullName; private String status; private LocalDateTime createTime; // 省略getter/setter及toString方法 } (10分) LoginLog.java(自己实现) // 提供LoginLog类的源代码 (7)在src\main\java\com\ycusoft\experiment目录中新建mapper包,用来存放映射文件的mapper接口,并在其中创建UserMapper接口文件。 package com.ycusoft.experiment.mapper; import com.ycusoft.experiment.entity.User; import java.util.List; public interface UserMapper { /** * 查询所有用户 * @return */ List<User> selectAll(); /** * 根据id查询用户 * @param userId * @return */ User selectById(Integer userId); /** * 插入用户 * @param user * @return */ int insert(User user); /** * 根据id修改用户 * @param user * @return */ int updateById(User user); /** * 根据id删除用户 * @param userId * @return */ int deleteById(Integer userId); } (8)在src\main\resources下新建mapper目录,在其中新建UserMapper.xml文件,实现用户增删改查操作。内容如下: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ycusoft.experiment.mapper.UserMapper"> <select id="selectAll" resultType="User"> select * from user </select> <select id="selectById" resultType="User"> select * from user where user_id=#{userId} </select> <insert id="insert" parameterType="user"> insert into user(username,password,full_name,status,create_time) values(#{username},#{password},#{fullName},#{status},#{createTime}) </insert> <update id="updateById" parameterType="User"> update user set username=#{username},password=#{password},full_name=#{fullName},status=#{status},create_time=#{createTime} where user_id=#{userId} </update> <delete id="deleteById" parameterType="int"> delete from user where user_id=#{userId} </delete> </mapper> (8)在src\test\java中,创建com.ycusoft.experiment包,并在其中新建UserTest类,在UserTest方法中编写代码,测试对User表的查询、插入、删除和更新等操作。 package com.ycusoft.experiment; import com.ycusoft.experiment.entity.User; import com.ycusoft.experiment.mapper.UserMapper; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import java.time.LocalDateTime; public class UserTest { @Test public void test() { SqlSession sqlSession = MyBatisUtil.getSqlSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 查询所有用户并打印 userMapper.selectAll().forEach(System.out::println); // 插入用户 User user = new User(); user.setUsername("zhangsan"); user.setPassword("123456"); user.setFullName("张三"); user.setStatus("1"); user.setCreateTime(LocalDateTime.now()); System.out.println("开始插入用户..."); int result = userMapper.insert(user); sqlSession.commit(); System.out.println("插入用户成功!"); // 查询所有用户并打印 userMapper.selectAll().forEach(System.out::println); // 更新管理员用户 User adminUser = userMapper.selectById(1); adminUser.setFullName("修改后的管理员"); adminUser.setPassword("88888888"); System.out.println("开始更新管理员用户..."); result = userMapper.updateById(adminUser); sqlSession.commit(); System.out.println(userMapper.selectById(1)); // 删除刚刚新增的用户 System.out.println("开始删除用户..."); result = userMapper.deleteById(2); sqlSession.commit(); // 查询所有用户并打印 userMapper.selectAll().forEach(System.out::println); } } 此时会遇到” org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.ycusoft.experiment.mapper.UserMapper.selectAll”报错,请通过网上资料或AI查找报错原因,并在此简述报错的原因以及解决方法:(10分) // 简述报错的原因以及解决方法 修复完报错后,在下方粘贴控制台运行结果截图: (12)继续完成数据表login_log的增删改查(要求采用接口方式)。除上述示例的增删改查方法外,再实现两个方法:(60分) ①列出近五天的登录用户数量; ②统计登录失败的用户数。 (可以自己往数据表里多插入一些数据,也可以让AI生成插入数据的SQL) LoginLogMapper.java // 提供LoginLogMapper接口的源代码 LoginLogMapper.xml // 提供LoginLogMapper映射文件的源代码 LoginLogTest.java // 提供LoginLog单元测试的源代码 提供控制台运行截图:(10分) 这个实验我具体需要怎么做
09-18
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值