【发布时间】:2011-04-01 22:29:02
【问题描述】:
我一直在看各种hibernate教程和示例,对于它们的身份/主键属性,有些使用Java原始类型,有些使用包装类型,即;
private int id;
对
private Integer id;
我为什么以及何时将一个而不是另一个用于实体键?
【问题讨论】:
我一直在看各种hibernate教程和示例,对于它们的身份/主键属性,有些使用Java原始类型,有些使用包装类型,即;
private int id;
对
private Integer id;
我为什么以及何时将一个而不是另一个用于实体键?
【问题讨论】:
从 Hibernate 的角度来看,它不会改变任何东西,因为 Hibernate 使用相同的 Hibernate 类型来表示它们。
但是,正如 Bytecode Ninja 所指出的,您无法将原始 int 0 的默认值与分配的 0 区分开来,而 null (null id 总是意味着一个新实体),这就是为什么我更喜欢使用可为空的包装类型。
这是 Hibernate 的建议。来自参考文档:
4.1.2. Provide an identifier property (optional)
Cat 有一个名为 id 的属性。这 属性映射到主键 数据库表的列。这 属性可能已被调用 任何东西,它的类型可能是 任何原始类型,任何原始类型 “包装器”类型,java.lang.String 或 java.util.日期。如果你的遗产 数据库表有复合键,你 可以使用用户定义的类 这些类型的属性(参见 稍后关于复合标识符的部分 在章节中。)
标识符属性是严格的 可选的。你可以把它们关掉,然后 让 Hibernate 跟踪对象 内部标识符。我们不 不过推荐这个。
事实上,有些功能是 仅适用于声明的类 标识符属性:
- 分离对象的可传递重新附加(级联更新或级联 合并) - 见第 10.11 节, “传递持久性”
- Session.saveOrUpdate()
- Session.merge()
我们建议您声明 一致命名的标识符 持久类的属性和 您使用可空值(即 非原始)类型。
我实际上在我的基类中利用了这一点:
@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 列的值在实体的相应表中,这有时会导致难以查明错误。
但是使用包装器,id 的默认值将是 null,并且主键列不能有 null 值,因此您无法更新其 id 值未设置的实体具有应用程序逻辑的有效值。
【讨论】:
您可以将主键指定为原语或包装器。由于通常不需要 Integer 的优点,因此最好使用 int 保持简单。
更多信息请访问oracle.com。
【讨论】: