java 后台一次null值踩坑记

在一次业务逻辑中,因userId为null导致查询条件错误,通过赋值-1解决此问题,确保即使在userId为空的情况下也能正确执行查询。

不得不说代码中的null值,总是会在不经意间引起bug,也许看似低级,但是产生的问题还不小。记一下自己的踩坑过程,以此为鉴。

原始代码如下:

Long userId = UserUtil.getLoginUserId(request);
UserInterestUser userInterestUser = userService.queryOne(MapUtil.buildMap("userId", userId, "anotherUserId", 2L));
业务逻辑是根据用户的id和另一个用户的id查询该记录,mapper中的配置文件如下:

<sql id="Where_Sql">
    <if test="id != null"> AND id = #{id} </if>
    <if test="userId != null"> AND user_id = #{userId} </if>
    <if test="anotherUserId != null"> AND another_user_id = #{anotherUserId} </if>
 </sql>
所以当userId为null的时候,逻辑就变成了,仅根据anotherUserId的值查询记录。

根据问题原因对于userId为null赋值一个不存在的值,因为userId为非负整数,故选-1.修改后如下:

Long userId = UserUtil.getLoginUserId(request);
if(userId == null){
    userId = -1L;
}







你已经完成了 IDEA 中的后端开发,数据库使用 MySQL 8.0,现在要在 **微信开发者工具** 中调用后端接口。接下来我们详细完成: --- ## ✅ 步骤五:后台服务准备(完整实现) 目标是: 1. ✅ 创建 `POST /api/records` 接口 —— 接收小程序提交的用药录并保存到数据库 2. ✅ 创建 `GET /api/records` 接口 —— 查询所有用药录并返回 JSON 数组 我们将从实体类 → Repository → Service → Controller 全流程实现,并确保与微信小程序兼容。 --- ### 🧱 假设前提(请确认是否已有): | 组件 | 是否存在 | |------|----------| | 数据库表 `medication_record` | ✅ 已有(根据你之前的日志) | | 实体类 `MedicationRecord.java` | ✅ 应该已存在 | | 使用 Spring Boot + JPA + MySQL | ✅ 成立 | 如果没有,请先补全。 --- ## 🔧 第一步:完善实体类 `MedicationRecord` ```java // cn/njucm/dosepre/entity/MedicationRecord.java package cn.njucm.dosepre.entity; import javax.persistence.*; import java.time.LocalDateTime; @Entity @Table(name = "medication_record") public class MedicationRecord { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String drugName; // 药品名称 private String dosage; // 剂量 private String useDate; // 使用日期(格式:yyyy-MM-dd) private String useTime; // 使用时间(格式:HH:mm) private String remarks; // 备注 @Column(name = "create_time") private LocalDateTime createTime = LocalDateTime.now(); // 构造函数 public MedicationRecord() {} public MedicationRecord(String drugName, String dosage, String useDate, String useTime, String remarks) { this.drugName = drugName; this.dosage = dosage; this.useDate = useDate; this.useTime = useTime; this.remarks = remarks; } // Getter Setter public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getDrugName() { return drugName; } public void setDrugName(String drugName) { this.drugName = drugName; } public String getDosage() { return dosage; } public void setDosage(String dosage) { this.dosage = dosage; } public String getUseDate() { return useDate; } public void setUseDate(String useDate) { this.useDate = useDate; } public String getUseTime() { return useTime; } public void setUseTime(String useTime) { this.useTime = useTime; } public String getRemarks() { return remarks; } public void setRemarks(String remarks) { this.remarks = remarks; } public LocalDateTime getCreateTime() { return createTime; } public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; } } ``` > 💡 注意:`useDate` `useTime` 用 `String` 是为了方便前端传参(如 picker 选择),也可以改为 `LocalDate` + `LocalTime`,但需配置 Jackson 序列化。 --- ## 🔧 第二步:创建 Repository ```java // cn/njucm/dosepre/repository/MedicationRecordRepository.java package cn.njucm.dosepre.repository; import cn.njucm.dosepre.entity.MedicationRecord; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import java.util.List; @Repository public interface MedicationRecordRepository extends JpaRepository<MedicationRecord, Long> { // 可以添加自定义查询方法,例如按患者ID查 // List<MedicationRecord> findByPatientId(String patientId); } ``` --- ## 🔧 第三步:创建 Service 层(可选,简化可跳过) ```java // cn/njucm/dosepre/service/MedicationRecordService.java package cn.njucm.dosepre.service; import cn.njucm.dosepre.entity.MedicationRecord; import java.util.List; public interface MedicationRecordService { MedicationRecord saveRecord(MedicationRecord record); List<MedicationRecord> getAllRecords(); } ``` ```java // cn/njucm/dosepre/service/impl/MedicationRecordServiceImpl.java package cn.njucm.dosepre.service.impl; import cn.njucm.dosepre.entity.MedicationRecord; import cn.njucm.dosepre.repository.MedicationRecordRepository; import cn.njucm.dosepre.service.MedicationRecordService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class MedicationRecordServiceImpl implements MedicationRecordService { @Autowired private MedicationRecordRepository recordRepository; @Override public MedicationRecord saveRecord(MedicationRecord record) { return recordRepository.save(record); } @Override public List<MedicationRecord> getAllRecords() { return recordRepository.findAll(); } } ``` --- ## 🔧 第四步:创建 Controller 提供 REST API ```java // cn/njucm/dosepre/controller/RecordController.java package cn.njucm.dosepre.controller; import cn.njucm.dosepre.entity.MedicationRecord; import cn.njucm.dosepre.service.MedicationRecordService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/api/records") @CrossOrigin(origins = "*") // 小程序本地调试允许跨域 public class RecordController { @Autowired private MedicationRecordService recordService; /** * POST: 接收小程序发送的用药录 */ @PostMapping public ResponseEntity<String> addRecord(@RequestBody MedicationRecord record) { try { recordService.saveRecord(record); return ResponseEntity.ok("用药录保存成功!"); } catch (Exception e) { return ResponseEntity.status(500).body("保存失败:" + e.getMessage()); } } /** * GET: 返回所有用药录(JSON数组) */ @GetMapping public ResponseEntity<List<MedicationRecord>> getRecords() { try { List<MedicationRecord> records = recordService.getAllRecords(); return ResponseEntity.ok(records); } catch (Exception e) { return ResponseEntity.status(500).body(null); } } } ``` --- ## ✅ 后端测试建议(在 Postman 或 IDEA 中测试) ### 测试 1:POST 添加录 - URL: `http://localhost:8080/dosepre/api/records` - Method: `POST` - Headers: - `Content-Type: application/json` - Body (raw JSON): ```json { "drugName": "阿司匹林", "dosage": "10mg", "useDate": "2025-11-19", "useTime": "08:00", "remarks": "早餐后服用" } ``` ✅ 预期结果:返回 `"用药录保存成功!"`,数据库新增一条数据。 --- ### 测试 2:GET 获取所有录 - URL: `http://localhost:8080/dosepre/api/records` - Method: `GET` ✅ 预期结果:返回如下格式的 JSON 数组 ```json [ { "id": 1, "drugName": "布洛芬", "dosage": "200mg", "useDate": "2025-11-13", "useTime": "08:00", "remarks": "饭后", "createTime": "2025-11-19T21:45:00" }, { "id": 2, "drugName": "阿莫西林", "dosage": "500mg", "useDate": "2025-11-14", "useTime": "09:30", "remarks": "", "createTime": "2025-11-19T21:46:00" } ] ``` --- ## 📱 微信小程序端调用示例(WXML + JS) ### WXML 示例(简单按钮触发) ```xml <!-- pages/index/index.wxml --> <button bindtap="addRecord">添加用药录</button> <button bindtap="getRecords">获取用药录</button> <view wx:for="{{records}}" wx:key="id"> {{item.drugName}} - {{item.useDate}} {{item.useTime}} </view> ``` ### JavaScript 调用代码 ```javascript // pages/index/index.js Page({ data: { records: [] }, // 添加录 addRecord() { wx.request({ url: 'http://localhost:8080/dosepre/api/records', method: 'POST', data: { drugName: '对乙酰氨基酚', dosage: '500mg', useDate: '2025-11-20', useTime: '12:00', remarks: '中午' }, header: { 'Content-Type': 'application/json' }, success(res) { console.log('添加成功:', res.data); wx.showToast({ title: '添加成功' }); }, fail(err) { console.error('请求失败:', err); wx.showToast({ icon: 'error', title: '网络错误' }); } }); }, // 获取录 getRecords() { wx.request({ url: 'http://localhost:8080/dosepre/api/records', method: 'GET', success: (res) => { if (res.statusCode === 200) { this.setData({ records: res.data }); } }, fail: (err) => { console.error(err); } }); } }); ``` --- ## ⚠️ 注意事项(关键!避免) | 问题 | 解决方案 | |------|----------| | 小程序无法连接本地后端 | 确保电脑手机在同一 WiFi 下,且防火墙开放 8080 端口;或使用内网穿透工具(如 ngrok) | | 显示“跨域错误” | 后端加 `@CrossOrigin(origins = "*")` 或使用 Nginx 代理 | | 请求超时 | 检查 IP 地址是否正确,不要用 `127.0.0.1`,要用本机局域网 IP(如 `192.168.x.x`) | | HTTPS 限制 | 开发阶段可在小程序管理后台关闭“不校验合法域名”选项 | --- ## 🌐 最终访问地址(小程序中使用的 URL) 假设你的电脑局域网 IP 是 `192.168.31.100`,则: ```js const baseUrl = 'http://192.168.31.100:8080/dosepre'; ``` 而不是 `localhost`! --- ## ✅ 总结:你现在已完成步骤五 | 功能 | 完成情况 | |------|---------| | ✅ POST 接口接收 JSON 数据 | ✔️ | | ✅ 保存到 MySQL 数据库 | ✔️ | | ✅ GET 接口返回 JSON 数组 | ✔️ | | ✅ 支持微信小程序调用 | ✔️ | | ✅ 跨域处理、异常处理 | ✔️ | 🎉 后台服务已为小程序完全准备好! ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值