我是Hibernate,Spring,JPA框架的初学者。暂时,我正在尝试用Spring 3.1.1创建一个简单的架构 - 带有Hibernate 4实现的JPA。
目前,为了不依赖于我的数据库,我使用TableGenerator创建了一些ID:
@Id
@Column(name = "AIR_ID", unique = true, nullable = false)
@TableGenerator(name="aircraftSeqStore",
table="T_S_APP_SEQ_STORE_AST",
pkColumnName="AST_SEQ_NAME",
valueColumnName = "AST_SEQ_VALUE",
pkColumnValue = "T_R_AIRCRAFT_AIR.AIR_ID",
allocationSize=1)
@GeneratedValue(strategy=GenerationType.TABLE,
generator="aircraftSeqStore")
private Integer id;
在我的研究之后,在阅读了“不要让我自己偷了 - 偷你的身份”这篇文章之后,我真的不明白如何管理我的ID。
我是否应该修改我的实体以用指定的值替换它们(如何在JPA中执行?)并且我应该生成一个UUID来直接在创建瞬态对象时影响id吗?
在许多表中,我有一些简单的数据(id,name)。我以为我可以在名称属性上管理hashcode和equals方法,这些方法是唯一的,但是在创建对象时也没有受到影响....(所以我认为同样的pb,id为null?)。
有关信息,我有一个代表多连接表的实体(此连接表中为3 FK)。
那你对我有什么建议? 为性能生成UUID是不是很糟糕?
编辑:
这个实体是否可行?
@Id
@Column(name = "AIR_ID", unique = true, nullable = false)
@TableGenerator(name="aircraftSeqStore",
table="T_S_APP_SEQ_STORE_AST",
pkColumnName="AST_SEQ_NAME",
valueColumnName = "AST_SEQ_VALUE",
pkColumnValue = "T_R_AIRCRAFT_AIR.AIR_ID",
allocationSize=1)
@GeneratedValue(strategy=GenerationType.TABLE,
generator="aircraftSeqStore")
private Integer id;
@Column(name = "AIR_BUSINESS_ID", unique = true, nullable = false)
private String uuid = IdGenerator.createId();
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || !(o instanceof Aircraft))
return false;
Aircraft other = (Aircraft)o;
if (uuid == null) return false;
return uuid .equals(other.getUuid ());
}
public int hashCode() {
if (uuid != null) {
return uuid .hashCode();
} else {
return super.hashCode();
}
}
谢谢。
答案 0 :(得分:3)
与每个问题一样,完整但很少有用的答案是:它取决于。
更有用的变体是:
我大部分时间都使用GenerationType.Auto,并且不实现equals和hashcode。
结果是:
只要它们位于同一个会话中,您就可以很好地比较实体对象,因为hibernate将确保每个数据库行由每个会话的单个实例表示。
equals和hashcode随着时间的推移会保持稳定,因此您可以将对象放在HashSet中,更改对象并再次将它们取出。
如果要处理来自不同Sessions的对象,则必须显式比较id或id + hashcode或某些业务键,可能是通过实现Comparator。决定使用和实现它的额外努力将提醒你,你实际上正在做一些违背Hibernate的事情。
关于性能:根据数据库和用例,UUID具有较高的性价比,因为它们相当大或获得性能,因为它们可以在客户端上创建,从而节省数据库往返。大多数情况下,应用程序中的其他故障(特别是在使用Hibernate时)比ID生成的任何影响要大。
答案 1 :(得分:0)
通常我使用:
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id
让持久性提供者选择正确的。 希望这能帮到你
答案 2 :(得分:0)
我最近问了一个问题,探讨了通常模式的替代方案:Are there any gotchas with this JPA "cached hashCode" pattern?
我提供了一个我通常用@Entity
类做的例子 - 在构造时生成UUID
。 UUID
碰撞的概率很小,你最好担心宇宙射线。有些人不喜欢UUID
,因为他们觉得有性能损失。我没有看到性能与Integer
相比有任何变化,但我认为Integer
碰撞的可能性很小,足以引起关注。
@Id
private UUID id = UUID.randomUUID();
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!(obj instanceof MY_CLASS) || id == null)
return false;
MY_CLASS other = (MY_CLASS) obj;
return id.equals(other.id);
}
@Override
public int hashCode() {
Preconditions.checkNotNull(id, "id must be set before @Entity.hashCode can be called");
return id.hashCode();
}
有时我想检查实际数据本身是否匹配,在这种情况下我创建一个这样的方法:
public boolean hasSameProperties(Note other) {
Preconditions.checkNotNull(other);
if (this == other)
return true;
return Objects.equal(source, other.source)
&& Objects.equal(title, other.title)
&& Objects.equal(tags, other.tags)
&& Objects.equal(contents, other.contents);
}