有时你会遇到 PO 类和数据库表字段不一致的情况,并且又没办法将它俩调整成一致。这种情况下,你就要显示地在你的 PO 类的属性上添加 @TableField 注解,并通过它的 value 属性指定该属性所对应的数据库字段。
@TableField(value = "location")
private String xxx;
默认情况下,在属性名和数据库字段一致的情况下,@TableField 注解可以偷懒省略掉,不写。但是这种不一致的情况下,你就没法再偷懒了。
有可能你的数据库字段有 N 个,但是与之对应的 PO 类的属性有 N + 1 个,PO 类属性比数据库字段要多。
警告
个人觉得不应该出现这种情况。出现这种情况的唯一原因就是:有人偷了懒。本应该再创建一个 JavaBean 的(可能是 DTO,也可能是 Domain),但是偷懒没有。在原本应该使用 DTO 或 Domain 的地方使用 PO ,而 DTO 和 Domain 本身和数据库表结构又不是严格意义对应的,进而导致你要在你的 PO 类中加属性。
PO 类中一加属性,那它还是 PO 吗?它和数据库表还是严格一一对应吗?
通过 @TableField 注解的 exist 属性赋值为 false
,要求 MP 不要管这个属性:在新增/修改操作时,MP 不会把这个属性的值 insert/update 到数据库的表中;在查询操作时,MP 也不会(也不能)用数据库中的某个字段为它赋值。
@TableField(exist = false)
private String xxx;
有时无意中给表名和列名起名字时会和 SQL 语法中的关键字同名。最典型的例子就是 order
。
提示
如果你是手动执行 SQL 语句建表,通常不会出现这种情况。因为在执行建表语句时,就会出错。通常都是大家通过客户端软件,在界面上点点点地建表,从而忽略掉了这个问题。
这种情况下,你需要在你的 PO 类中用上『反单引号(`
)』将表名和列名引起来。其实,本质上本来就是需要的,只不过在不冲突的情况下,我们可以省略。现在无非是加回去了而已。
@TableName("`department`")
public class DepartmentPo implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "`id`", type = IdType.AUTO)
private Long id;
@TableField(value = "`name`")
private String name;
@TableField(value = "`location`")
private String location;
}
从上帝视角看,有 3 方可以为数据库中的数据的 ID 负责:程序员、MP 和数据库自己。
『程序员负责』指的是我们在编码过程中,在代码层面为即将 insert 进数据库中的数据准备好 ID 。即,在 insert 到数据库之前,这条数据就已经有了 ID 了。
『MP 负责』指的是虽然我们没有决定数据的 ID ,但是由于数据是经由 MP 去执行 insert SQL 语句的,MP 可以为这条数据生成 ID 。也就是说,在 insert 到数据库之前,这条数据已经有 ID 了。
由『数据库自己负责』这种情况大家已经很熟悉了,数据库在收到要 insert 的数据时,数据是没有 ID 的,数据库自己来决定这条数据的 ID 。
ID 生成策略指的就是你准备让谁来负责为新数据生成 ID 这个事:
@TableId(type = IdType.AUTO)
这就是数据库负责,利用数据库的主键 ID 自增功能。这种情况下,我们在新增数据时不需要考虑为新数据的 ID 赋值。
@TableId(type = IdType.INPUT)
这就是程序员负责。这种情况下我们在代码中要为新数据的 ID 属性赋值,并且要保证它是非空且唯一的。
ASSIGN_ID
和 ASSIGN_UUID
都表示由 MP 负责。对于 ID 为 null 的数据,MP 会使用 uuid 或雪花 id 来为它们赋值,然后再使用 insert SQL 添加到数据库中。