更新架构标准说明
This commit is contained in:
parent
dae47dd897
commit
02aca1c35c
|
|
@ -688,7 +688,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
where {entity}_id = #{{{entity}Id}}
|
where {entity}_id = #{{{entity}Id}}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<insert id="insert{Entity}" parameterType="com.ruoyi.{module}.mapper.entity.{Entity}Entity" useGeneratedKeys="true" keyProperty="{entity}Id">
|
<insert id="insert{Entity}" parameterType="com.ruoyi.{module}.mapper.entity.{Entity}Entity" useGeneratedKeys="true" keyProperty="{entity}Id" keyColumn="{entity}_id">
|
||||||
insert into {module}_{table}
|
insert into {module}_{table}
|
||||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||||
<if test="fieldName != null and fieldName != ''">field_name,</if>
|
<if test="fieldName != null and fieldName != ''">field_name,</if>
|
||||||
|
|
@ -734,6 +734,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
- 使用 `<sql>` 定义可复用的 SQL 片段
|
- 使用 `<sql>` 定义可复用的 SQL 片段
|
||||||
- 使用动态 SQL 标签:`<if>`, `<trim>`, `<foreach>`
|
- 使用动态 SQL 标签:`<if>`, `<trim>`, `<foreach>`
|
||||||
- 插入操作使用 `useGeneratedKeys="true"` 返回主键
|
- 插入操作使用 `useGeneratedKeys="true"` 返回主键
|
||||||
|
- **重要**:插入操作必须同时指定 `keyProperty` 和 `keyColumn` 属性
|
||||||
- 时间字段使用 `sysdate()` 函数
|
- 时间字段使用 `sysdate()` 函数
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -904,7 +905,10 @@ public class {Entity}DomainImpl implements I{Entity}Domain
|
||||||
public int insert{Entity}({Entity} {entity})
|
public int insert{Entity}({Entity} {entity})
|
||||||
{
|
{
|
||||||
{Entity}Entity entity = {Entity}DomainConvert.toEntity({entity});
|
{Entity}Entity entity = {Entity}DomainConvert.toEntity({entity});
|
||||||
return {entity}Mapper.insert{Entity}(entity);
|
int result = {entity}Mapper.insert{Entity}(entity);
|
||||||
|
// 【重要】MyBatis 会将自增主键回填到 entity 对象,需要同步回 model 对象
|
||||||
|
{entity}.set{Entity}Id(entity.get{Entity}Id());
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -933,6 +937,64 @@ public class {Entity}DomainImpl implements I{Entity}Domain
|
||||||
- 使用**构造器注入**(Constructor Injection)
|
- 使用**构造器注入**(Constructor Injection)
|
||||||
- 字段声明为 `private final`
|
- 字段声明为 `private final`
|
||||||
- 通过 Convert 类进行对象转换
|
- 通过 Convert 类进行对象转换
|
||||||
|
- **【关键】insert 方法必须将 Entity 的主键回填到 Model 对象**
|
||||||
|
|
||||||
|
**⚠️ MyBatis 主键回填注意事项:**
|
||||||
|
|
||||||
|
MyBatis 在执行 INSERT 操作后,会将数据库自动生成的主键值回填到 `Entity` 对象中,但**不会自动同步到传入的 `Model` 对象**。
|
||||||
|
|
||||||
|
**错误示例(会导致主键丢失):**
|
||||||
|
```java
|
||||||
|
@Override
|
||||||
|
public int insert{Entity}({Entity} {entity})
|
||||||
|
{
|
||||||
|
{Entity}Entity entity = {Entity}DomainConvert.toEntity({entity});
|
||||||
|
return {entity}Mapper.insert{Entity}(entity);
|
||||||
|
// ❌ 错误:entity 中的主键没有同步回 {entity} 对象
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**正确示例(主键正确回填):**
|
||||||
|
```java
|
||||||
|
@Override
|
||||||
|
public int insert{Entity}({Entity} {entity})
|
||||||
|
{
|
||||||
|
{Entity}Entity entity = {Entity}DomainConvert.toEntity({entity});
|
||||||
|
int result = {entity}Mapper.insert{Entity}(entity);
|
||||||
|
// ✅ 正确:将 entity 中的主键同步回 {entity} 对象
|
||||||
|
{entity}.set{Entity}Id(entity.get{Entity}Id());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**为什么需要手动同步主键?**
|
||||||
|
|
||||||
|
1. **对象转换导致的隔离**:`BeanUtils.copyProperties()` 只是属性拷贝,创建了新的 Entity 对象
|
||||||
|
2. **MyBatis 只回填 Entity**:MyBatis 的 `useGeneratedKeys` 只会将主键设置到 Mapper 方法参数(Entity)中
|
||||||
|
3. **Model 对象不会自动更新**:原始的 Model 对象与 Entity 对象是两个独立的对象,需要手动同步
|
||||||
|
|
||||||
|
**不同步主键的后果:**
|
||||||
|
|
||||||
|
如果不将主键同步回 Model 对象,会导致:
|
||||||
|
- Service 层无法获取新插入记录的主键 ID
|
||||||
|
- 后续依赖主键的业务逻辑会失败(如关联表插入)
|
||||||
|
- 可能产生重复数据或数据不一致问题
|
||||||
|
|
||||||
|
**示例场景:**
|
||||||
|
```java
|
||||||
|
// Service 层调用
|
||||||
|
Device device = new Device();
|
||||||
|
device.setDeviceName("测试设备");
|
||||||
|
deviceDomain.insertDevice(device);
|
||||||
|
|
||||||
|
// 如果没有主键回填,device.getDeviceId() 将返回 null
|
||||||
|
Long deviceId = device.getDeviceId(); // 期望得到新插入的 ID
|
||||||
|
|
||||||
|
// 后续业务逻辑依赖这个 ID
|
||||||
|
Dock dock = new Dock();
|
||||||
|
dock.setDeviceId(deviceId); // 如果 deviceId 为 null,会导致关联失败
|
||||||
|
dockDomain.insertDock(dock);
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### 5.4 Domain Convert 转换类规范
|
### 5.4 Domain Convert 转换类规范
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue