休眠主键的基元或包装器
我一直在看各种休眠教程和示例,对于它们的标识/主键属性,有些使用Java基元类型,有些使用包装器类型,即;
private int id;
与
private Integer id;
为什么以及何时我会使用一个而不是另一个,作为实体键?
我一直在看各种休眠教程和示例,对于它们的标识/主键属性,有些使用Java基元类型,有些使用包装器类型,即;
private int id;
与
private Integer id;
为什么以及何时我会使用一个而不是另一个,作为实体键?
从Hibernate的角度来看,它不会改变任何东西,因为Hibernate使用相同的Hibernate类型来表示它们。
但是,正如Bytecode Ninja所指出的那样,您无法将原始int的默认值与赋值的值区分开来,而a(id总是意味着新实体)没有可能的歧义,这就是为什么我更喜欢使用可为空的包装器类型。0
0
null
null
这是Hibernate的建议。从参考文档:
4.1.2. 提供标识符属性(可选)
Cat 有一个名为 id 的属性。此属性映射到数据库表的主键列。该属性可能已被调用任何内容,其类型可能是任何基元类型,任何基元“包装器”类型,java.lang.String或java.util.Date。如果旧版数据库表具有复合键,则可以使用具有这些类型属性的用户定义类(请参阅本章后面有关复合标识符的部分)。
标识符属性是严格可选的。您可以关闭它们,让 Hibernate 在内部跟踪对象标识符。但是,我们不建议这样做。
实际上,某些功能仅适用于声明标识符属性的类:
- 分离对象的传递性重新附加(级联更新或级联合并)- 请参见第 10.11 节 “传递持久性”
- Session.saveOrUpdate()
- Session.merge()
我们建议您在持久类上声明一致命名的标识符属性,并使用可为 null(即非基元)的类型。
我实际上在我的基类中利用了这一点:
@MappedSuperclass
public class BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Transient
public boolean isNew() {
return (this.id == null);
}
}
我更喜欢使用包装器类型,因为否则,当我们使用基元类型时,主键将默认设置为,并且可能是实体的相应表中实际列的值,这有时会导致难以查明的错误。id
0
0
id
但是使用包装器时,默认值 will 是,主键列不能有值,因此您无法更新实体,因为应用程序逻辑未使用有效值设置其值。id
null
null
id