0%

数据库表字段的默认值

在设计表的时候,可以为一个字段指定默认值,这样这个字段在数据库中就不会为空。也有在insert或是update数据的时候,把表中的create_datemodified_date之类的时间字段在sql语句是使用now()来赋值,而不需要在代码中设置。还有一种是把默认值的管理交给代码控制,包括时间之类的全部在代码中使用new Date()等方法获取之后再传入到数据保存。本文就以一个时间字段的赋值时机来介绍下这两种方式的使用。

比如说有一个User表,表结果如下:

1
2
3
4
5
6
7
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(32) | YES | | NULL | |
| create_date | datetime | YES | | NULL | |
+-------------+-------------+------+-----+---------+----------------+

mybatis为例,如果想让数据库生成create_date值,插入一条用户记录时使用:

1
insert into User (name, create_date) values (#{name}, now());

在持久层的方法可能是这样的

1
int insert(User user);

此例中插入一条User记录可以用以下代码:

1
2
3
4
User user = new User();
user.setName("test01");
int count = insert(user);
int id = user.getId();

用此种方法可以返回影响的行数,还有就是新插入记录的id(需要在mybatis中添加其他语句实现,本文不讨论)。但是如果想得到新插入记录的create_date,那么就需要再根据返回的id再次进行查询。

另一种就是把所有变量的值在代码中都赋值好,再生成对应的sql语句,同样是插入用户记录的sql语句就变为:

1
insert into User (name, create_date) values (#{name}, #{createDate});

此时插入一条User记录的代码如下:

1
2
3
4
User user = new User();
user.setName("test01");
user.setCreateDate(new Date());
int count = insert(user);

由于所有的数据持久层都能在一次插入之后获取,所以此时的代码可以写成这样:

1
User insert(User user);

不是返回影响的行数,而是把新插入的记录返回回去,以方便使用。

所以这两种方式最大的不同就在于,在持久层或是服务层只需要知道插入操作影响的行数和id,还是需要把新插入的对象返回,供上一层使用。在第一种方式中,使用数据库生成的值,除主键外不会赋值到对象中,此时数据库中这些字段的值并不在对象中。使用第二种方式由于只有主键是数据库生成的(本例中是这样的,主键也可以先生成再传入到数据库),而且主键可以在插入后返回,其他属性在插入前都是已知的,这样插入完成之后,数据库中此记录的值与对象中的是完全一致的。

使用数据库赋值时间字段有一个好处,能保证多台应用服务器操作数据库时的时间上的准确性。使用代码赋值时间字段的话,取得的时间都是应用服务器的时间,如果A服务器的时间比B服务器晚1秒,A服务器先插入一条数据,紧接着B服务器也插入了一条,就会出现先插入数据的时间比后插入的时候还晚。使用数据库赋值的话,时间都以数据库服务器的为准,就不会出现这种问题。

其他字段的赋值时机的不同造成的影响和此例中时间字段的效果类似。