使用Hibernate来表示表关系是否是个好主意? [英] Is it a good idea to use Hibernate for representing table relations?

查看:89
本文介绍了使用Hibernate来表示表关系是否是个好主意?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用hibernate连接到java的mysql数据库。我试图了解是否真的值得使用ORM(如hibernate)作为关系。特别是与注释的特别关系似乎让我感到非常恼火。因此,对于友谊表,我希望通过使用用户表中的外键来查看特定用户的友谊请求。

在用于helper table的hibernate类中,保存了一个表示主表的字段。因此,不要将关系保持为简单的 int ,它将 User 类作为主字段。这可能是有用的,如果你需要访问用户对象,但在某些情况下,你只需要外键ID。



我把我为两个表,用户和UserFriendRequests。这是代表下列两个表格的最佳方法吗?我觉得代表这样的基本表格太过于夸张。我宁愿使用Hibernate来连接并单独表示表,并手动处理关系。你会推荐这种方法吗?如果您可以分享您的想法和有关最佳实践的文档,我将不胜感激。

用户表格包含以下列:


  • userId主要,自动增量

  • facebookId唯一

  • 用户名

  • createdAt日期

  • lastLogin日期<​​/ li>
  • lastNotifiedAt日期



UserFriendRequests表包含以下列:


  • firstUser来自Users表的userId的外键

  • secondUser外键userId from Users table

  • PrimaryKey(firstUser,secondUser)



用户表示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


  1. 由于脏检查,插入/更新更容易。一旦你有了服务,你可以轻松地添加新的领域,而无需改变服务中的一行。您只需添加新列并填充这些列,并且Hibernate将负责持久化部分。

  2. Hibernate可以解决丢失更新问题,因为它是乐观锁定并发控制。 为您的内存数据库(HSQLDB,H2,Derby)自动生成架构

  3. 它具有缓存插件支持(通过第三方第二级缓存提供者),一些提供者允许您
  4. 它具有内置的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 a User 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:

    1. 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.
    2. Hibernate can solve the "lost update" problem because of it's optimistic locking concurrency control.
    3. Integration testing is easier, since you can generate the schema automatically for your in-memory database (HSQLDB, H2, Derby)
    4. 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.
    5. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆