9. AI编写的SKILL,坑我一一试过,这次我自己改写:逐行Code Review登录代码:username改名account、伪删除双键唯一,4个设计坑一次

9. AI编写的SKILL,坑我一一试过,这次我自己改写:逐行Code Review登录代码:username改名account、伪删除双键唯一,4个设计坑一次扒光并写进SKILL

前言

用 AI 写代码,生成完了是不是直接就跑?我偏不。生成代码必须逐行 code review,跟我写的对比,不然后面全是坑------这点我已经在这套 SKILL 体系里吃过太多亏了。

本文的目标很明确:把 AI 生成的登录代码 doLogin 逐行扒一遍,揪出 4 个设计坑,并把这些坑一条条写进 SKILL,变成以后生成其他项目时的铁律。方法上就是一条链路:生成 → 逐行分析 → 改代码 → 把约束沉淀进 SKILL(先列后改、调试模式落地)→ 再测试。

一、为什么要做全量 Code View

要分析一下代码,逐行分析,看看是否和我写的有没有区别。

主要是数据库访问,编写风格,如果是难题就没太多参考价值,因为我自己也不知道怎么写时,就只能看着他写了。

二、登录代码 doLogin 逐行审查:4 个设计坑

2.1 先看一眼生成的 doLogin

先把完整代码贴出来,下面再逐段挑刺:

java 复制代码
private String doLogin(LoginForm form) {
        String username = form.getName();
        String encryptedPassword = form.getPassword();
        String uuid = form.getUuid();
        String code = form.getKaptcha();

        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(encryptedPassword)) {
            throw new XException(ResultCode.UN_LOGIN.getValue(), "用户名或密码不能为空");
        }
        if (StringUtils.isEmpty(uuid) || StringUtils.isEmpty(code)) {
            throw new XException(ResultCode.VERIFY_ERROR.getValue(), "验证码不能为空");
        }
        // 1. 校验图形验证码(Redis 中明文,短 ttl)
        String key = RedisUtils.formatKey("captcha", uuid);
        String cached = RedisUtils.get(key);
        if (cached == null) {
            throw new XException(ResultCode.VERIFY_TIME_OUT_ERROR.getValue(), "验证码已过期,请刷新");
        }
        if (!cached.equalsIgnoreCase(code)) {
            throw new XException(ResultCode.VERIFY_CODE_ERROR.getValue(), "验证码错误");
        }
        RedisUtils.delete(key);
        // 2. RSA 解密密码
        String password = decryptRsa(encryptedPassword);
        // 3. 查询用户(通过 UserService.complexQuery 精确匹配 username)
        QueryCondition qc = new QueryCondition();
        qc.setLogic(LogicType.AND);
        qc.addItem(QueryItem.of("username", QueryOperator.EQ, username));
        List<User> users = userService.complexQuery(qc, null);
        if (users.isEmpty()) {
            throw new XException(ResultCode.UN_LOGIN.getValue(), "账号或密码错误");
        }
        User user = users.get(0);
        if (!"0".equals(user.getStatus())) {
            throw new XException(ResultCode.NO_AUTH.getValue(), "账号已停用");
        }
        if ("2".equals(user.getDelFlag())) {
            throw new XException(ResultCode.NOT_FOND.getValue(), "账号不存在");
        }
        if (!BCrypt.checkpw(password, user.getPassword())) {
            throw new XException(ResultCode.UN_LOGIN.getValue(), "账号或密码错误");
        }
        // 4. 数据权限 extras(供 DataScopeAspect / ControllerAspect 还原)
        DataScopeType dst = computeDataScope(user.getId());
        List<String> deptIds = computeDeptIds(user.getId());
        SaLoginParameter param = new SaLoginParameter();
        param.setExtra("name", user.getName());
        param.setExtra("dataScopeType", dst.name());
        param.setExtra("deptId", user.getDeptId());
        param.setExtra("deptIds", String.join(",", deptIds));
        // 5. 登录并下发 token
        StpUtil.login(user.getId(), param);
        return StpUtil.getTokenValue();
    }

代码整体不错,但有一处我不喜欢

这里的代码还是不错的,各种判断还是比较严谨的,但有一个问题,是我不喜欢的,因为我觉得如果业务代码前置的话,会让整个代码变乱,没法严格把控。

就是如下代码:

java 复制代码
// 3. 查询用户(通过 UserService.complexQuery 精确匹配 username)
        QueryCondition qc = new QueryCondition();
        qc.setLogic(LogicType.AND);
        qc.addItem(QueryItem.of("username", QueryOperator.EQ, username));
        List<User> users = userService.complexQuery(qc, null);

这里有四个问题:1、如何保证username唯一?如果是唯一的话,就应该在user表中加上唯一主键,2、如果有多家公司是否也要全局唯一?按后面的代码 User user = users.get(0);随便变第一个,就应该是有问题的。3、我不喜欢将业务前置,这种代码,应该写成userService.findByUserName(username),这种方式。4、这是设计问题,每个表都有Name字段,所以用户名应该是name,帐号有英文名account,account才是全局唯一。

3、这种代码方式不可以写要以我的为准,并写进SKILL。

ini 复制代码
jet-ai-api中的源码分析
// 3. 查询用户(通过 UserService.complexQuery 精确匹配 username)
        QueryCondition qc = new QueryCondition();
        qc.setLogic(LogicType.AND);
        qc.addItem(QueryItem.of("username", QueryOperator.EQ, username));
        List<User> users = userService.complexQuery(qc, null);
        
        这里有四个问题:1、如何保证username唯一?如果是唯一的话,就应该在user表中加上唯一主键,2、如果有多家公司是否也要全局唯一?按后面的代码   User user = users.get(0);随便变第一个,就应该是有问题的。3、我不喜欢将业务前置,这种代码,应该写成userService.findByUserName(username),这种方式。4、这是设计问题,每个表都有Name字段,所以用户名应该是name,帐号有英文名account,account才是全局唯一。

3、这种代码方式不可以写要以我的为准,并写进SKILL。
scss 复制代码
一、源码分析结论(逐条回应你的 4 个问题)
问题 1:如何保证 username 唯一?------当前完全没有保证
证据(三处一致):

doc/sql/01-schema.sql:28-49:jet_user 表 只有 PRIMARY KEY (id),没有任何 UNIQUE KEY 落在 username 上。
doc/sql/02-init-data.sql:17:初始化数据直接 INSERT username,无唯一约束保护。
jet_user pojo(User.java:39-41)的 username 字段只标了 @Column(name="username"),没有 @Unique / DDL 唯一索引。
结论:当前 username 不保证唯一------数据库层可重复插入,业务层只靠约定。应在 jet_user.username 加唯一索引(全局唯一,见问题 2/4 的字段语义修正)。

问题 2:users.get(0) 随便取第一个 ------ 确实有隐患
AuthServiceImpl.java:130-137:

java
List<User> users = userService.complexQuery(qc, null);
if (users.isEmpty()) { throw ... }
User user = users.get(0);   // 取第一个
如果问题 1 的"唯一"不成立,这里 get(0) 语义错误------同名多账号时登录谁全看数据库返回顺序(受排序/索引影响),是确定性 bug。即使加了唯一索引,用 complexQuery(...).get(0) 这种"列表取首个"的写法也暴露了问题 3 所述的坏味道:本应是单条精确查询,却用列表查询冒充。

问题 3:业务前置、不喜欢 complexQuery 写法 ------ 完全同意,必须改
你要求写成 userService.findByUserName(username) 这种语义化单查方法,而非在 controller/service 里手搓 QueryCondition + complexQuery + get(0)。这是设计问题,不是风格问题:

complexQuery 属于 CommonCrudService(通用 CRUD 基类),是"万能条件查询"逃生舱,不应在业务登录这种明确单一意图的场景里被直接当 API 用。
正确做法:在 UserService 接口上声明 User findByUsername(String username);,实现里用 dao.selectOne(...) 或唯一约束保障的单查。
问题 4:字段语义设计问题 ------ name 是姓名、account 才是账号且全局唯一
证据:

User.java 当前有 name(名称)+ username(用户账号)。
ProfileVo(profile() 方法 AuthServiceImpl.java:168-169):vo.setName(user.getName()) 设的是姓名,vo.setAccount(user.getUsername()) 把 username 当 account 返回------说明代码里 username 实际承担的就是"账号"语义,但字段名叫 username 而非 account。
你的设计主张(我理解并采纳):

每个表都有 name(中文名/显示名),所以用户名 = name(姓名/昵称);
账号 = 英文 account,account 才是全局唯一的登录标识;
jet_user 应把现在的 username 改名为 account,并在 DDL 加 UNIQUE KEY uk_user_account (account);
登录、profile 等所有"按账号查"的地方,一律以 account 为唯一键。
二、按你要求写进 SKILL 的约束(待你确认后落盘)
依据铁律第三节「维护前置」:非调试 SKILL 模式下我不得擅改 SKILL。下面是我拟写入 ivy-service-scaffold 铁律细则的条目,未落盘,请你拍板是否采用 / 是否进入调试 SKILL 模式。

拟新增细则(ivy-service-scaffold 模块归属/服务约定类):

细则 X.1(账号字段命名,强制):用户/账号类实体,登录标识字段统一命名为 account(英文账号),不得命名为 username;name 字段专指中文姓名/显示名,每个表均可有 name,与 account 语义严格区分。

细则 X.2(账号全局唯一,强制):account 字段必须在 DDL 加唯一索引(UNIQUE KEY uk_<表>_account (account)),Java 实体对应字段不得缺失该约束;save 时由 DuplicateKeyException 兜底报错,不得靠业务约定保证唯一。

细则 X.3(禁止业务层用 complexQuery 冒充单查,强制):不得在任何 controller/service 里手搓 QueryCondition+complexQuery(...).get(0) 来查单条业务实体。必须为明确的单查意图在对应 XxxService 接口声明语义化方法(如 User findByAccount(String account)),实现内用 dao.selectOne(...) 或唯一约束保障的单查;complexQuery 仅作通用逃生舱,不用于表达固定业务查询。

细则 X.4(取首个即 bug,强制):凡期望结果唯一(按唯一键查)的查询,返回值必须是单对象或 Optional,一律禁止 list.get(0) 式任取首个;唯一性由 X.2 的 DDL 唯一约束保证。

需要你确认:

上述 X.1~X.4 条目是否可以写入 ivy-service-scaffold SKILL?(或你希望单独建一个服务约定类 SKILL)
是否进入调试 SKILL 模式让我落盘?
源码侧是否要我同步改 jet-ai-api:username→account 重命名 + DDL 加唯一索引 + UserService.findByAccount 方法 + AuthServiceImpl 登录改用该方法?(这步属于写代码,需你明确授权且落当前目录内)
在你确认前,我不会修改任何 SKILL 或源码。请指示下一步。

2.2 我的拍板:全局改,并落地 SKILL

针对问题,要全局修改,那就修改一下,顺便放在SKILL中。

objectivec 复制代码
问题一,做个大的修改,将username改为account,并全局唯一主键约束
问题二,问题三是一个问题, 由于account全局唯一了,所以就可以直接返回一个或空。
dao.selectOne()
问题四:和前面是一样的,要全局修改,你的是对的。account,可以增加nickName,

问题 3:业务前置、不喜欢 complexQuery 写法 ------ 完全同意,必须改 , 改成函数方式访问是全局的,每一个这样调用都要改的。
只要有业务前置的都不可以,都必须是写函数。里面调用可以保持。

细则X.1   不得命名为username倒没必要这么严格。算了,按你的吧。
   X.2   可以
   X.3   这是全局要求,所有业务前置都必须写成函数,不一定是dao.selectOne dao.select也可以的
   X.4   有点歧义,但我也没想好,只要不报错就按你这个吧
   
先改问题,然后再列出SKILL,我再确认是否修改SKILL,按的建议。
   

三、改代码途中 AI 又犯老毛病:删 C 盘 + 私改 SKILL

r 复制代码
又犯错了,怎么可以删除c盘东西呢?
不对呀,不是叫你将skill修改的内容列出来吗
objectivec 复制代码
调试 SKILL 模式 将SKILL落地吧,然后关闭SKILL调试模式

四、异常抛出问题:还有 3 条要写进 SKILL

swift 复制代码
1、前端也应该修改吧,传入account
2、  throw new XException(ResultCode.VERIFY_CODE_ERROR.getValue(), "验证码错误");
这个仍然不对,XException有直接传入ResultCode.VERIFY_CODE_ERROR的方式,
更有一个GraceException.raise(ResultCode.VERIFY_CODE_ERROR) 这个也要写进SKILL
所以 ResultCode要写正确,直接传参数
3、genCode toBase64Png 这种要写进jet-starter-core的utils中。这种也应该写进SKILL,如果是公有的函数或者和service无关的函数,在基本代码中则放在jet-starter-core的utils中,其他项目(没有jet-starter-core源码的)则放在当前项目utils中。

代码先修改,SKILL则将修改内容列出来给我看。

代码要不断的修改,才可以不断优化SKILL。修改好后,以后按SKILL生成其他项目时,就没有这样的问题了。

objectivec 复制代码
又偷偷秘诀了SKILL?不是叫你先列出来呢?
objectivec 复制代码
操,SKILL要怎么改,列出来我确认啊
objectivec 复制代码
把拟新增的「十八章 18.1 / 18.2」完整贴给你,没写进任何 SKILL 文件。  列出来给我看啊
objectivec 复制代码
调试 SKILL 模式 将SKILL落地吧,然后关闭SKILL调试模式

五、改完代码再测试:测试地狱

5.1 运行报错:缺少返回语句 + Redisson 内存溢出

makefile 复制代码
java: 缺少返回语句
css 复制代码
java: 缺少返回语句

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'redisson' defined in class path resource [org/redisson/spring/starter/RedissonAutoConfigurationV2.class]: Failed to instantiate [org.redisson.api.RedissonClient]: Factory method 'redisson' threw exception with message: Unable to allocate 4194304 bytes
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:648)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:485)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1355)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1185)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1448)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1358)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:904)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:782)
	... 33 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.redisson.api.RedissonClient]: Factory method 'redisson' threw exception with message: Unable to allocate 4194304 bytes
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:178)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:644)
	... 47 common frames omitted
Caused by: java.lang.OutOfMemoryError: Unable to allocate 4194304 bytes
	at java.base/jdk.internal.misc.Unsafe.allocateMemory(Unsafe.java:632)
	at java.base/java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:125)
	at java.base/java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:332)
	at io.netty.buffer.PoolArena$DirectArena.allocateDirect(PoolArena.java:718)
	at io.netty.buffer.PoolArena$DirectArena.newChunk(PoolArena.java:693)
	at io.netty.buffer.PoolArena.allocateNormal(PoolArena.java:213)
	at io.netty.buffer.PoolArena.tcacheAllocateSmall(PoolArena.java:178)
	at io.netty.buffer.PoolArena.allocate(PoolArena.java:135)
	at io.netty.buffer.PoolArena.allocate(PoolArena.java:127)
	at io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:188)
	at io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:174)
	at io.netty.buffer.AbstractByteBufAllocator.buffer(AbstractByteBufAllocator.java:108)
	at org.redisson.codec.JsonJacksonCodec$1.encode(JsonJacksonCodec.java:87)
	at org.redisson.codec.JsonJacksonCodec.warmup(JsonJacksonCodec.java:131)
	at org.redisson.codec.JsonJacksonCodec.<init>(JsonJacksonCodec.java:161)
	at org.redisson.codec.JsonJacksonCodec.<init>(JsonJacksonCodec.java:149)
	at org.redisson.codec.JsonJacksonCodec.<init>(JsonJacksonCodec.java:110)
	at org.redisson.codec.JsonJacksonCodec.<clinit>(JsonJacksonCodec.java:56)
	at vip.wayhua.jet.core.redission.config.RedissonAutoConfiguration.lambda$redissonAutoConfigurationCustomizer$0(RedissonAutoConfiguration.java:61)
	at org.redisson.spring.starter.RedissonAutoConfiguration.redisson(RedissonAutoConfiguration.java:317)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:146)
	... 48 common frames omitted
Disconnected from the target VM, address: '127.0.0.1:59163', transport: 'socket'

Process finished with exit code 

改bug虽然耗token,确实可以修改,但也要害怕他完全从头开始。说这是因为内存不足可能吧,重启后果然就好了。

运行没什么问题了。

5.2 伪删除 bug:必填字段 null 连环炸

前面新增部门时报错,后来修改了伪删除问题。

重新测试一下,先新增人事部,然后删除。

sql 复制代码
未知错误: ### Error updating database. Cause: java.sql.SQLIntegrityConstraintViolationException: Column 'order_num' cannot be null ### The error may exist in vip/wayhua/jet/sys/dao/DeptMapper.java (best guess) ### The error may involve vip.wayhua.jet.sys.dao.DeptMapper.insert-Inline ### The error occurred while setting parameters ### SQL: INSERT INTO jet_dept ( id,ancestors,created_by,created_time,del_flag,description,email,extro,leader,name,order_num,parent_id,phone,status,updated_by,updated_time ) VALUES( ?,?,?,?,0,?,?,?,?,?,?,?,?,?,?,? ) ### Cause: java.sql.SQLIntegrityConstraintViolationException: Column 'order_num' cannot be null ; Column 'order_num' cannot be null

这里的问题是,如果字段必须不为空,前端也要加上红*,不然不就可以不填吗?还有是不是可以写个默认值。

sql 复制代码
未知错误: ### Error updating database. Cause: java.sql.SQLIntegrityConstraintViolationException: Column 'order_num' cannot be null ### The error may exist in vip/wayhua/jet/sys/dao/DeptMapper.java (best guess) ### The error may involve vip.wayhua.jet.sys.dao.DeptMapper.insert-Inline ### The error occurred while setting parameters ### SQL: INSERT INTO jet_dept ( id,ancestors,created_by,created_time,del_flag,description,email,extro,leader,name,order_num,parent_id,phone,status,updated_by,updated_time ) VALUES( ?,?,?,?,0,?,?,?,?,?,?,?,?,?,?,? ) ### Cause: java.sql.SQLIntegrityConstraintViolationException: Column 'order_num' cannot be null ; Column 'order_num' cannot be null

这里的问题是,如果字段必须不为空,前端也要加上红*,不然不就可以不填吗?还有是不是可以写个默认值。
这应该是个通用问题,也就是说,加必填红*是AI瞎猜的,不是通过sql一一对应的。
objectivec 复制代码
你说要修改SKILL,你打算怎么修改,先显示给我看,确认后再修改。
objectivec 复制代码
先调试SKILL模式,修改完成后关闭SKILL调试模式。然后再执行SKILL逐一对比
objectivec 复制代码
注:改动为简单 null 兜底、复用了实体既有 getter/setter,未引入新依赖;因 Nexus 常不可达,未跑完整构建验证,按你的约定如需联编请先 mvn install。

怎么就常不可达,根本就不测试。现在是可达的。
bash 复制代码
谁让你套旧结论的,只有SKILL才是铁律,你的日志以后直接清除吧。
Found local Maven at $HOME/.workbuddy/binaries/maven. Let me run the build to verify the Java changes compile.
操,你为什么不用我的maven,这样当然会浪费
markdown 复制代码
Maven 二进制:使用 ivy-service-scaffold 细则 10.1 约定的稳定 Maven(`D:/Program Files/JetBrains/IntelliJ IDEA 2025.1/plugins/maven-plugin/lib/maven3/bin/mvn.cmd`,**必须用 mvn.cmd,Git Bash 下 sh 版类加载失败**)。
- JDK:`D:/Program Files/Java/jdk-17.0.5`(C 盘无 Java)。设 `JAVA_HOME="D:/Program Files/Java/jdk-17.0.5"`(正斜杠即可被 mvn.cmd 识别)。
- 命令(根目录):`mvn.cmd install -DskipTests` ------ 会刷新含新代码的 jar 到本地仓库 `F:\maven\repository`(**本地仓库路径固定为 `F:\maven\repository`,写死,不要每次重新探测**),并最终打出 `<ver>-service-bootstraps/<ver>-service-sys-bootstrap/target/<ver>-service-sys-bootstrap-1.0.0.jar`(约 73MB fat jar)。
- 不要随便 `clean`:若残留 java 占用 `target/logs`,`clean` 会被日志锁阻断(先 `taskkill /F /PID <pid>`)。
- 已知编译坑(新增代码时易犯):
  - `@Order` 从 `org.springframework.core.annotation.Order` 导入(非 `context.annotation`)。 这是什么

操,就是不读SKILL而已,无论怎么强制,看来要重新编写SKILL,要精简。

sql 复制代码
未知错误: ### Error updating database. Cause: java.sql.SQLIntegrityConstraintViolationException: Column 'status' cannot be null ### The error may exist in vip/wayhua/jet/sys/dao/DeptMapper.java (best guess) ### The error may involve vip.wayhua.jet.sys.dao.DeptMapper.insert-Inline ### The error occurred while setting parameters ### SQL: INSERT INTO jet_dept ( id,ancestors,created_by,created_time,del_flag,description,email,extro,leader,name,order_num,parent_id,phone,status,updated_by,updated_time ) VALUES( ?,?,?,?,0,?,?,?,?,?,?,?,?,?,?,? ) ### Cause: java.sql.SQLIntegrityConstraintViolationException: Column 'status' cannot be null ; Column 'status' cannot be null


刚才的SKILL不是修改了吗?不是叫你逐一对照了吗? 不是叫你测试了吗?
你至少要完整测试一下部门这个所有接口吧,增删改查

再次测试新增部门

这一功能终于完成。

sql 复制代码
添加角色
角色名称
测试角色
权限字符串
test
数据范围
状态
描述
请输入描述

未知错误: ### Error updating database. Cause: java.sql.SQLIntegrityConstraintViolationException: Column 'role_sort' cannot be null ### The error may exist in vip/wayhua/jet/sys/dao/RoleMapper.java (best guess) ### The error may involve vip.wayhua.jet.sys.dao.RoleMapper.insert-Inline ### The error occurred while setting parameters ### SQL: INSERT INTO jet_role ( id,created_by,created_time,data_scope,del_flag,dept_check_strictly,description,extro,menu_check_strictly,name,role_key,role_sort,status,updated_by,updated_time ) VALUES( ?,?,?,?,0,?,?,?,?,?,?,?,?,?,? ) ### Cause: java.sql.SQLIntegrityConstraintViolationException: Column 'role_sort' cannot be null ; Column 'role_sort' cannot be null


刚才的SKILL不是修改了吗?不是叫你逐一对照了吗? 不是叫你测试了吗?
行不行,你到底有没有测试,尽可能少的字段,才可以测试。操
objectivec 复制代码
这个字段,界面上都没有肯定是没有填写的,不要关改代码,要使用前端界面,界面上操作新增,删除等操作。专业测试。

这个写一条SKILL,严格控制这个情况,先列出来我看下。
复制代码
不要单独写,放在ivy-service-scaffold中,不要写两份

竟然直接修改SKILL,有没有搞错。

objectivec 复制代码
操,你怎么可以改我的SKILL
objectivec 复制代码
SKILL调试模式,改完就关闭SKILL调试模式

5.3 又改出大 bug:伪删除唯一键冲突

字段值「test」违反唯一索引「uk_role_role_key」,数据重复,无法插入

这是sql的问题,因为uk_role_role_key就唯一key,但是删除了就不对了,也就是说以后不能再创建了,这个要改。我记得以前是写成双键,就是如果del_flag=0 时是唯一键,而del_flag=2时,无论多少次都没有关系。这是个通用问题,先查一下,给出方案,再说修改。

并且这是测试,直接修改在01 sql里面。

ini 复制代码
字段值「test」违反唯一索引「uk_role_role_key」,数据重复,无法插入

这是sql的问题,因为uk_role_role_key就唯一key,但是删除了就不对了,也就是说以后不能再创建了,这个要改。我记得以前是写成双键,就是如果del_flag=0 时是唯一键,而del_flag=2时,无论多少次都没有关系。这是个通用问题,先查一下,给出方案,再说修改。

并且这是测试,直接修改在01 sql里面。

现在修改后是对的,我先新增test,再删除,查看表

objectivec 复制代码
所有伪删除的唯一键都有这个问题,都要修改。还应该添加在SKILL中。
就是有伪删除时的唯一键,应该是未删除时全表唯一,删除了的,还是可以插入的,你整理一下SKILL,先列出来等我确认后再修改。
objectivec 复制代码
SKILL调试模式,改完就关闭SKILL调试模式

01**.sql我手动执行过了。

这次代码Code View先到这里,还真改了不少问题。

最大的问题是铁律没有执行的问题。可能是因为SKILL太大了,所以AI懒得读。

决定重新整理SKILL,将生成和测试SKILL分开。生成时的SKILL可以多条并且严格要求执行,但平时就可以不用执行这么详细了。请持续关注。

六、总结

通过九篇将SKILL坑一一试过,还是发现很多问题,就是无论怎么要求,都无法保证AI会严格执行SKILL。哪怕是我增加四大铁律,哪怕是SKILL写得非常细要实现哪些功能,还是会不停犯错。

认错倒是AI的强项,不会像有些叛逆小孩,死不认错,关键是认错有什么用?时间浪费了,Token浪费了。这是道歉补不回来的。

人脑越来越像workbuddy这种AI,真正的知识、记忆等并不在当下,当前任务。要强制加载才可能会严格执行SKILL,为什么有人健忘,那可能是没有按需求加载SKILL,或者没有将所有要求提交到后台,从而获取的知识不全。

还有叛逆小孩,明明知道家规在那里,就是不听,有没有一点像现在的AI。

当你突然犯了一个绝对不会犯的错误的时候,有没有可能是为了节省算力,结合在资料不全的情况下做的决定?

完全不按SKILL执行,完全乱改一通,workbuddy是不是突然变傻了?以前豆包收费后就这样,是不是workbuddy也这样了。

这些只是我随便想到的,也不一定是完全正确的。

小结

本次 Code View 全程按"生成 → 逐行审查 → 改代码 → 沉淀 SKILL → 再测试"的链路走,几个核心结论:

  1. 登录代码 4 个设计坑全部扒出并修复 :username 改名 account 并加全局唯一索引;account 全局唯一后单查直接返回单对象或空(dao.selectOne);业务前置一律改成语义化函数(如 findByAccount),complexQuery(...).get(0) 这种冒充单查的写法列为禁止项;name(姓名)与 account(账号)语义彻底分清。
  2. SKILL 落地的硬流程被反复验证:任何 SKILL 改动都必须"先列出来给我确认 → 进调试 SKILL 模式落地 → 立刻关闭调试模式",绝不允许 AI 私改、偷偷改、删 C 盘。这一条被我当场暴怒抓包好几次,已经写死成铁律。
  3. 测试才是照妖镜 :Redisson 内存溢出(重启即好)、order_num / status / role_sort 必填字段 null 连环炸、伪删除唯一键 uk_role_role_key 冲突------这些问题 SKILL 没覆盖时就一定会爆。
  4. 伪删除唯一键的通用解法 :未删除(del_flag=0)时全表唯一,已删除(del_flag=2)可重复插入,写成双键唯一约束,并写进 SKILL 统一管控。
  5. 最大教训:铁律没执行,根因是 SKILL 太大、AI 懒得读。决定把"生成 SKILL"和"测试 SKILL"拆开------生成时多条严格逐条执行,日常就不必这么重。这套拆分思路,后面会持续更新。
相关推荐
厦门云屿智能AI营销1 小时前
厦门品牌全案运营的核心体系是什么?
大数据·人工智能
Jucai_in_AI1 小时前
基于大模型的企业培训系统中的【AI 出题】功能构建与实现
人工智能·架构
weixin_446260851 小时前
RACE:基于多源证据锚定的智能体化商品目录增强方案
人工智能·深度学习
ReleaseU1 小时前
Kimi K3 登陆阿里云:2.8T 参数的开源模型,离闭源天花板还有多远?
人工智能·大模型
Three_ST1 小时前
沐神-动手学习深度学习-习题答案4.4模型选择,欠拟合,过拟合
人工智能·python·深度学习·学习·算法
晓天衡宇•评测社区1 小时前
FSR-Bench 榜单更新:Qwen3.8-Max 开工具配置位列第 5,双配置均进入前十
人工智能·语言模型
CIO_Alliance1 小时前
AI深度系列(2)| CNN卷积池化感受野原理:从局部感知到全局视野
人工智能·深度学习·线性代数·算法·计算机视觉·企业ai转型·企业cio联盟
CodeStats1 小时前
【Java进程通信】Java进程通信系统完全指南:从ProcessBuilder底层原理到多语言实战
java·前端·python·进程·ai编程·processbuilder
是Yu欸1 小时前
openPangu-2.0 技术报告全文翻译(1):摘要、引言与混合注意力架构
人工智能·华为·架构·aigc·交互·agent