修改double类型字段Setter定义未生效的技术问题咨询
嘿,我来帮你分析下这个问题——你修改了marks字段的Setter方法,想通过BigDecimal处理精度,但发现没生效对吧?结合你的场景(Oracle的number(30,8)对应Java的double),我整理了几个可能的原因和对应的解决办法:
1. ORM框架直接操作字段,跳过了Setter
如果你用的是MyBatis、Hibernate这类ORM框架,很多时候框架会直接通过反射访问实体类的私有字段,而不是调用Setter方法,这就导致你写的精度处理逻辑根本没被执行。
解决办法:
- MyBatis:检查你的配置文件,确保
useSetterGetter参数是true(默认是true,但如果被手动改成false就会出问题);或者在<resultMap>里明确指定字段对应Setter方法,比如:<resultMap id="StudentResultMap" type="com.example.Student"> <result property="studentId" column="STUDENT_ID"/> <result property="name" column="NAME"/> <result property="marks" column="MARKS"/> <!-- 这里会自动调用setMarks --> </resultMap> - Hibernate:检查实体类的字段注解,如果有
@Access(AccessType.FIELD),改成@Access(AccessType.PROPERTY),强制Hibernate通过Setter方法赋值。
2. Double本身的精度丢失让Setter成了“马后炮”
double类型本身就存在精度缺陷,比如数据库里的123.456789转成double时可能已经变成了123.45678899999999,这时候你再在Setter里用BigDecimal处理,也没法还原原本的精度了。
解决办法(最推荐):
把Java类里的double marks改成BigDecimal marks,直接用BigDecimal存储,完全匹配Oracle的number类型:
class Student { private String studentId; private String name; private BigDecimal marks; // studentId和name的getter/setter public BigDecimal getMarks() { return marks; } public void setMarks(BigDecimal marks) { // 在这里处理精度,比如保留6位小数 this.marks = marks.setScale(6, BigDecimal.ROUND_HALF_UP); } }
同时修改ORM映射的类型(MyBatis里用java.math.BigDecimal,Hibernate会自动适配),这样从数据库读取和写入时都不会有精度损失,Setter的逻辑也能正常生效。
3. 你可能直接操作了字段,没调用Setter
如果是手动创建Student对象时,你直接给私有字段赋值(比如student.marks = 95.5;)而不是调用setMarks(95.5),那你的Setter逻辑当然不会执行。
解决办法:
确保所有对marks的赋值操作都通过setMarks方法完成,不要直接操作私有字段。
4. BigDecimal构造器的小坑
你用了new BigDecimal(String.valueOf(marks)),但如果传入的double本身已经有精度问题(比如0.1在double里是0.1000000000000000055...),转成String再转BigDecimal也没法完全修复。所以最好的方式还是直接用BigDecimal接收值,而不是先转成double。
内容的提问来源于stack exchange,提问作者Dhwani Haria

