使用model的时候,字段的默认值问题是否有解决方案

很多时候,项目的数据设计上某些字段是有默认值的,比如说某些数字类型的字段的默认是0,有些表示状态的字段默认值是0,1等等。

当插入数据的时候,多数是先用new model方法,创建新数据记录的model对象,然后set入表单数据。但是new model生成的是一个attrs不带任何字段属性的,当然也不含有那些带默认值的字段

现在公司项目做的时候有个不太优雅的处理方案,就是model.save(),然后再model=dao.findById(id)重新获取一遍记录,这样就能够让model带上所有字段,也有默认值,方便后续业务处理。


不知道各位大大有没方案可以实现在new model的时候就能带上数据库各字段以及默认值


评论区

l745230

2019-07-02 14:12

创建表的时候就设置好默认值. new model().save() 的时候这些字段如果没传值,数据库会自动使用表设置的默认值

zeroabc

2019-07-02 14:22

@l745230 看第三段文字,"现在公司项目做的时候有个不太优雅的处理方案,就是model.save(),然后再model=dao.findById(id)重新获取一遍记录"

happyboy

2019-07-02 14:36

model new出来之后,如果你对某个字段不处理,save之后默认就是数据库默认值。一楼的意思你没能理解,其实根本不用额外处理。比如有个user表,性别字段设置了默认0。User user = new User();user.setName("张三");性别不处理,user.save()之后,数据库里性别就是0。你们的所谓优雅方案有点多此一举。

要输就输给追求

2019-07-02 15:08

@happyboy 他的意思是model.save()以后,model能点出数据库那些有默认值的字段的值。

要输就输给追求

2019-07-02 15:09

可以在model里面搞一个无参构造函数试试。在无参构造函数里面给有默认值的字段赋值

zeroabc

2019-07-02 15:11

@要输就输给追求 我说的不是save()的时候。。而是new 的时候就带上所有字段及默认值。

happyboy

2019-07-02 17:22

@zeroabc new对象是用来新建的,你的场景适合使用findbyid

zeroabc

2019-07-02 18:06

@happyboy 但是不先保存的话就没有id,然而业务上这条数据不一定保存,有可能是要废弃的,所以我才问能否在new model()的时候就获取到默认值

happyboy

2019-07-02 21:25

@zeroabc 能说下你们的场景吗,感觉不应该这种矛盾才对啊。我觉得没有必要纠结这个问题,如果你们的有默认值字段就那一两个,你手动附上值就完事了。就这么简单。实在不济,就用你说的先存,再findbyid,没有什么大不了。

blankkai

2019-07-03 09:34

@zeroabc 我觉得也是像 @要输就输给追求 说的,给model增加无参构造函数。
如果model是生成出来的,可以重写相关生成方法直接生成。
如果不是生成的,只好手动加了

zeroabc

2019-07-03 15:11

@blankkai 自动填充model默认值,其中一种比较好的实现思路就是ModelGenerator里面定制model的无参构造方法。我发帖是问有没有现成的代码实现。。。

Westwood

2019-10-30 10:25

@zeroabc 我也遇到了类似问题,就是:

· new了一个model
· set了必要的字段
· save()
· 想让剩下的字段按照database里的默认值(0之类)自动设好
· get那些字段,结果取出来的是null,影响后续业务

应该是这个意思吧?
目前只能save()之后,再重新从数据库里取一下

@JFinal 有其他解决方案吗?

JFinal

2019-10-30 11:03

@Westwood 在最终的 model 中,覆盖父类的 save() 方法,判断默认值是不是有,没有的话,设置一个,例如:
public MyModel extends Model {
public boolean save() {
if (get(xxx) == null) {
set(xxx, defaultXxx);
}

if (get(yyy) == null) {
set(yyy, defaultYyy);
}

return super.save();
}
}

当然如果希望更完美,可以先定义一些默认值的常量,例如:
public MyModel extends Model {
public static int STATUS_FAIL = 0;
public static int STATUS_OK = 1;

public boolean save() {
if (get("status") == null) {
set("status", STATUS_OK);
}

return super.save();
}
}

Westwood

2019-10-30 11:19

@JFinal 谢谢!
不过我目前的情况是
比如一条当日统计数据,可能只有两三个三五个字段有设定值,剩下一二十个字段都是(在数据库里)默认0
如果这么做的话,不可避免要写很长的重复性代码?

真的没有什么除了 “再取一次” 外的 简洁实现方法了麽 QAQ

JFinal

2019-10-30 11:33

@Westwood 最好的办法是数据库表的字段直接设置默认值

Westwood

2019-10-30 11:38

@JFinal 数据库表那边的字段都已经设置好了默认值了啊,但问题不是save()后直接裸调用原model的get方法,对这些字段取出来的仍然是null么

(还是我哪个地方理解错了?。)

JFinal

2019-10-30 13:26

@Westwood 可能你将 jfinal 的 model.save() 当成是 hibernate 去理解了

save() 方法只会去保存 set 过的值,其它的值不会改变它

如果你的代码由于某种原因调用了 model 的相关 set 方法,可以用下面两个方法来解决:
1:model.removeNullValueAttrs();
model.save();
remove 方法会去除 model 内的 null 值字段,然后你再 save() 就不会覆盖掉数据库的默认值了

2:model.remove(fiel1, fiel2, field3, ...);
model.save();
remove 方法会去除 model 内指定的字段,可同时指定多个,然后 save()

3:model.keep(fiel1, fiel2, field3, ...);
model.save()
如果要去除的字段很多,反而是需要保留的很少,可以使用 keep 方法指定要保留的字段值

jfinal 数据库操作早已解决了这方面问题

Westwood

2019-10-30 15:04

@JFinal 额,我不是这个需求… 麻烦看一下,新鲜出炉的栗子:

——这是数据表结构——

CREATE TABLE `test_table` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`a` bigint(11) NOT NULL DEFAULT '0',
`b` bigint(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


——这是测试用代码——

TestTable model = new TestTable();

model.setA((long) 1); // set a ,不 set b

model.removeNullValueAttrs(); // 这些 solution 解决不了问题
model.remove("b"); //
model.keep("id", "a"); //

model.save(); // save 成功后,数据库里的 a 为 1, b 为 0

System.out.println(model.getA()); // 输出 1
System.out.println(model.getB()); // 输出 null (问题所在,即使采用上述三种方法都不行)

model = model.findById(model.getId()); // 解决方案:重新取一次该 model (用dao也可以)

System.out.println(model.getA()); // 输出 1
System.out.println(model.getB()); // 输出 0


————

所以,我的需求是,有没有比 “重新取一次” 更好的方法,使 model.getB() 得出 0 而非 null _(:з」∠)_

JFinal

2019-10-30 19:31

@Westwood 我明白你的需求了,你是希望 save() 在往数据库插入一条数据以后,可以立即使用 model.getXxx() 来获取使用默认值生成的字段值

jfinal 目前只能满足这种需求的自增主键的获取,无法满足你在例子中的字段 b 的获取

自增主键的获取可以这样:
model.save();
model.getId();
也就是说自增主键在 save() 方法调用以后是自动从数据库获取到的

Westwood

2019-10-31 09:03

@JFinal 好的 明白了,谢谢!

zeroabc

2019-11-01 17:19

@Westwood 我们现在还是用这个不太优雅的方案做。model.save(),然后再model=dao.findById(id)重新获取一遍记录,这样就能够让model带上所有字段,也有默认值

doubuxingle

2020-05-26 17:27

public TestTable() {
_getAttrs().put("A", 0);
_getAttrs().put("B", 0);
_getAttrs().put("C", "default");
....
}

热门反馈

扫码入社