使用Hibernate来表示表关系是否是个好主意? [英] Is it a good idea to use Hibernate for representing table relations?
问题描述
我正在尝试使用hibernate连接到java的mysql数据库。我试图了解是否真的值得使用ORM(如hibernate)作为关系。特别是与注释的特别关系似乎让我感到非常恼火。因此,对于友谊表,我希望通过使用用户表中的外键来查看特定用户的友谊请求。
在用于helper table的hibernate类中,保存了一个表示主表的字段。因此,不要将关系保持为简单的 int
,它将
我把我为两个表,用户和UserFriendRequests。这是代表下列两个表格的最佳方法吗?我觉得代表这样的基本表格太过于夸张。我宁愿使用Hibernate来连接并单独表示表,并手动处理关系。你会推荐这种方法吗?如果您可以分享您的想法和有关最佳实践的文档,我将不胜感激。
用户表格包含以下列:
UserFriendRequests表包含以下列:
用户表示table
@Entity
@Table(name =Users,catalog =example_schema,, uniqueConstraints = {
@UniqueConstraint(columnNames =userId),
@UniqueConstraint(columnNames =facebookId)})
public class User实现Serializable {
@I $
@GeneratedValue(st rategy = IDENTITY)
@Column(name =userId,unique = true,nullable = false)
private int userId;
@Column(name =facebookId,unique = true,nullable = false)
private String facebookId;
@Column(name =userName,nullable = false)
private String userName;
@Column(name =createdAt,nullable = false)
@Temporal(javax.persistence.TemporalType.DATE)
私有日期createdAt;
@Column(name =lastLogin)
@Temporal(javax.persistence.TemporalType.DATE)
私有日期lastLogin;
@Column(name =lastNotifiedAt)
@Temporal(javax.persistence.TemporalType.DATE)
private lastNotifiedAt;
@OneToMany(fetch = FetchType.LAZY,mappedBy =id.firstUser)//我希望手动填写这些关系
private List< UserFriendRequest> userFriendRequests = Lists.newArrayList();
@Transient
private boolean newUser;
public User(){
this.createdAt = new Date();
this.newUser = false;
}
public User(int userId){
this();
this.userId = userId;
$ b $ public User(String facebookId,String userName){
this();
this.facebookId = facebookId;
this.userName = userName;
$ b $ public User(int userId,String facebookId,String userName){
this(facebookId,userName);
this.userId = userId;
}
public int getUserId(){
return userId;
}
public void setUserId(int userId){
this.userId = userId;
}
public String getFacebookId(){
return facebookId;
}
public void setFacebookId(String facebookId){
this.facebookId = facebookId;
}
public boolean isNewUser(){
return newUser;
}
public void setNewUser(boolean newUser){
this.newUser = newUser;
}
public String getUserName(){
return userName;
}
public void setUserName(String userName){
this.userName = userName;
}
public Date getCreatedAt(){
return createdAt;
}
public void setCreatedAt(Date createdAt){
this.createdAt = createdAt;
}
public Date getLastLogin(){
return lastLogin;
}
public void setLastLogin(Date lastLogin){
this.lastLogin = lastLogin;
}
public Date getLastNotifiedAt(){
return lastNotifiedAt;
}
public void setLastNotifiedAt(Date lastNotifiedAt){
this.lastNotifiedAt = lastNotifiedAt;
}
公共列表< UserFriendRequest> getUserFriendRequests(){
返回userFriendRequests;
}
public void setUserFriendRequests(List< UserFriendRequest> userFriendRequests){
this.userFriendRequests = userFriendRequests;
}
@Override
public int hashCode(){
int hash = 7;
hash = 53 * hash + this.userId;
返回散列;
$ b @Override
public boolean equals(Object obj){
if(obj == null){
return false;
}
if(getClass()!= obj.getClass()){
return false;
}
最终用户其他=(用户)obj;
if(this.userId!= other.userId){
return false;
}
返回true;
@Override
public String toString(){
return ToStringBuilder.reflectionToString(this,ToStringStyle.MULTI_LINE_STYLE);
$ p $ User $ UserRequests表的表示
@Entity
@Table(name =UserFriendRequests,catalog =example_schema)
public class UserFriendRequest implements Serializable {
@Embeddable
public static class UserFriendRequestKey implements Serializable {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn( name =firstUser,nullable = false)
//而不是用户类我宁愿只保留int字段。如果我需要用户对象,我会自己处理它。
私人用户firstUser;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name =secondUser,nullable = false)
private User secondUser;
$ b $ public UserFriendRequestKey(){
}
public UserFriendRequestKey(User firstUser,User secondUser){
this.firstUser = firstUser;
this.secondUser = secondUser;
}
public User getFirstUser(){
return firstUser;
}
public void setFirstUser(User firstUser){
this.firstUser = firstUser;
}
public User getSecondUser(){
return secondUser;
}
public void setSecondUser(User secondUser){
this.secondUser = secondUser;
}
@Override
public int hashCode(){
int hash = 7;
hash = 89 * hash + Objects.hashCode(this.firstUser);
hash = 89 * hash + Objects.hashCode(this.secondUser);
返回散列;
$ b @Override
public boolean equals(Object obj){
if(obj == null){
return false;
}
if(getClass()!= obj.getClass()){
return false;
}
final UserFriendRequestKey other =(UserFriendRequestKey)obj;
if(!Objects.equals(this.firstUser,other.firstUser)){
return false;
if(!Objects.equals(this.secondUser,other.secondUser)){
return false;
}
返回true;
@Override
public String toString(){
return ToStringBuilder.reflectionToString(this,ToStringStyle.MULTI_LINE_STYLE);
}
}
@Id
private UserFriendRequestKey id;
@Column(name =requestedAt,nullable = false)
@Temporal(javax.persistence.TemporalType.DATE)
私人日期requestedAt;
$ b $ public UserFriendRequest(){
}
public UserFriendRequest(UserFriendRequestKey id){
this.id = id;
this.requestedAt = new Date();
}
public UserFriendRequestKey getId(){
return id;
}
public void setId(UserFriendRequestKey id){
this.id = id;
}
public Date getRequestedAt(){
return requestedAt;
}
public void setRequestedAt(Date requestedAt){
this.requestedAt = requestedAt;
@Override
public String toString(){
return ToStringBuilder.reflectionToString(this,ToStringStyle.MULTI_LINE_STYLE);
$解析方案
Hibernate有一个陡峭的学习曲线,但它也有以下优点:$ b
$ b
- 由于脏检查,插入/更新更容易。一旦你有了服务,你可以轻松地添加新的领域,而无需改变服务中的一行。您只需添加新列并填充这些列,并且Hibernate将负责持久化部分。
- Hibernate可以解决丢失更新问题,因为它是乐观锁定并发控制。 为您的内存数据库(HSQLDB,H2,Derby)自动生成架构
- 它具有缓存插件支持(通过第三方第二级缓存提供者),一些提供者允许您
- 它具有内置的AUDIT支持(Envers)
$ /
$
所以它不是一个'默认'持久性解决方案,因为有数百万个PHP应用程序编写,没有ORM框架,并且已经在生产环境中成功运行。
我认为Hibernate对企业应用程序w有更多的意义这里的缓存,审计,并发可靠性是强制性的非功能性要求。
I am trying to connect to a mysql db from java using hibernate. I am trying to understand whether it really worth using an ORM such as hibernate for relations or not. Especially specfying relationships with annotations seems quite irritating to me. So for a friendship table I would like to see the friendship requests of a particular user by using the foreign key from a users table.
In hibernate classes for helper table holds a field which represents the main table too. So instead of keeping the relation with a simple
int
, it holds aUser
class as a primary field. This might be useful, if you need to access the user object but in some cases you only need the foreign key id.I put the sample code I have written for two tables, Users and UserFriendRequests. Is this the best approach to represent the following two tables? I feel like this is quite overkill for representing such basic tables. I would prefer using Hibernate just for connection and representing tables individually and handle relations manually. Would you recommend this approach? I would appreciate if you can share your ideas and documents about best practices.
Users table have the following columns
- userId primary, auto increment
- facebookId unique
- username
- createdAt date
- lastLogin date
- lastNotifiedAt date
UserFriendRequests table have the following columns:
- firstUser foreignkey of userId from Users table
- secondUser foreignkey of userId from Users table
- PrimaryKey(firstUser, secondUser)
Representation of User table
@Entity @Table(name = "Users", catalog = "example_schema", uniqueConstraints = { @UniqueConstraint(columnNames = "userId"), @UniqueConstraint(columnNames = "facebookId")}) public class User implements Serializable { @Id @GeneratedValue(strategy = IDENTITY) @Column(name = "userId", unique = true, nullable = false) private int userId; @Column(name = "facebookId", unique = true, nullable = false) private String facebookId; @Column(name = "userName", nullable = false) private String userName; @Column(name = "createdAt", nullable = false) @Temporal(javax.persistence.TemporalType.DATE) private Date createdAt; @Column(name = "lastLogin") @Temporal(javax.persistence.TemporalType.DATE) private Date lastLogin; @Column(name = "lastNotifiedAt") @Temporal(javax.persistence.TemporalType.DATE) private Date lastNotifiedAt; @OneToMany(fetch = FetchType.LAZY, mappedBy = "id.firstUser") // I would prefer to fill these relations manually private List<UserFriendRequest> userFriendRequests = Lists.newArrayList(); @Transient private boolean newUser; public User() { this.createdAt = new Date(); this.newUser = false; } public User(int userId) { this(); this.userId = userId; } public User(String facebookId, String userName) { this(); this.facebookId = facebookId; this.userName = userName; } public User(int userId, String facebookId, String userName) { this(facebookId, userName); this.userId = userId; } public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } public String getFacebookId() { return facebookId; } public void setFacebookId(String facebookId) { this.facebookId = facebookId; } public boolean isNewUser() { return newUser; } public void setNewUser(boolean newUser) { this.newUser = newUser; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public Date getCreatedAt() { return createdAt; } public void setCreatedAt(Date createdAt) { this.createdAt = createdAt; } public Date getLastLogin() { return lastLogin; } public void setLastLogin(Date lastLogin) { this.lastLogin = lastLogin; } public Date getLastNotifiedAt() { return lastNotifiedAt; } public void setLastNotifiedAt(Date lastNotifiedAt) { this.lastNotifiedAt = lastNotifiedAt; } public List<UserFriendRequest> getUserFriendRequests() { return userFriendRequests; } public void setUserFriendRequests(List<UserFriendRequest> userFriendRequests) { this.userFriendRequests = userFriendRequests; } @Override public int hashCode() { int hash = 7; hash = 53 * hash + this.userId; return hash; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final User other = (User) obj; if (this.userId != other.userId) { return false; } return true; } @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); } }
Representation of UserFriendRequests table
@Entity @Table(name = "UserFriendRequests", catalog = "example_schema") public class UserFriendRequest implements Serializable { @Embeddable public static class UserFriendRequestKey implements Serializable { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "firstUser", nullable = false) //Instead of user class I would prefer to keep only the int field. If I would need the user object I would handle it myself. private User firstUser; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "secondUser", nullable = false) private User secondUser; public UserFriendRequestKey() { } public UserFriendRequestKey(User firstUser, User secondUser) { this.firstUser = firstUser; this.secondUser = secondUser; } public User getFirstUser() { return firstUser; } public void setFirstUser(User firstUser) { this.firstUser = firstUser; } public User getSecondUser() { return secondUser; } public void setSecondUser(User secondUser) { this.secondUser = secondUser; } @Override public int hashCode() { int hash = 7; hash = 89 * hash + Objects.hashCode(this.firstUser); hash = 89 * hash + Objects.hashCode(this.secondUser); return hash; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final UserFriendRequestKey other = (UserFriendRequestKey) obj; if (!Objects.equals(this.firstUser, other.firstUser)) { return false; } if (!Objects.equals(this.secondUser, other.secondUser)) { return false; } return true; } @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); } } @Id private UserFriendRequestKey id; @Column(name = "requestedAt", nullable = false) @Temporal(javax.persistence.TemporalType.DATE) private Date requestedAt; public UserFriendRequest() { } public UserFriendRequest(UserFriendRequestKey id) { this.id = id; this.requestedAt = new Date(); } public UserFriendRequestKey getId() { return id; } public void setId(UserFriendRequestKey id) { this.id = id; } public Date getRequestedAt() { return requestedAt; } public void setRequestedAt(Date requestedAt) { this.requestedAt = requestedAt; } @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); } }
解决方案Hibernate has a steep learning curve but it also has the following advantages:
- Insert/Updates are easier due to "dirty checking". Once you have the service in place, you can easily add new fields without changing a line in your service. You just need to add new columns and populate those and Hibernate will take care of the persistence part.
- Hibernate can solve the "lost update" problem because of it's optimistic locking concurrency control.
- Integration testing is easier, since you can generate the schema automatically for your in-memory database (HSQLDB, H2, Derby)
- It has a caching plug-in support (through third party 2nd level caching providers), some providers allowing you to have both "transactional" and "clustered" caches.
- It has a built-in AUDIT support (Envers)
So it's not a 'default' persistence solution, since there are millions of web apps written in PHP with no ORM framework that are successfully running in production.
I think Hibernate has much more sense for enterprise applications where caching, auditing, concurrency reliability are mandatory non-functional requirements.
这篇关于使用Hibernate来表示表关系是否是个好主意?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!