java - 使用 Hibernate 表示表关系是个好主意吗?

标签 java mysql sql hibernate jpa

我正在尝试使用 hibernate 从 java 连接到 mysql 数据库。我试图了解是否真的值得使用诸如 hibernate 之类的 ORM 来处理关系。尤其是与注释的指定关系对我来说似乎很烦人。因此,对于友谊表,我想通过使用用户表中的外键来查看特定用户的友谊请求。

在 hibernate 类中,帮助表也包含一个代表主表的字段。因此,它不是保持与简单 int 的关系,而是将 User 类作为主要字段。如果您需要访问用户对象但在某些情况下您只需要外键 ID,这可能很有用。

我将我为两个表 Users 和 UserFriendRequests 编写的示例代码放在一起。这是表示以下两个表的最佳方法吗?我觉得这对于表示这样的基本表来说太过分了。我更喜欢将 Hibernate 仅用于连接和单独表示表并手动处理关系。你会推荐这种方法吗?如果您能分享关于最佳实践的想法和文档,我将不胜感激。

用户表有以下列

  • userId primary,自增
  • facebookId 唯一
  • 用户名
  • 创建日期
  • 上次登录日期
  • 上次通知时间

UserFriendRequests 表有以下列:

  • 用户表中 userId 的 firstUser 外键
  • Users 表中 userId 的 secondUser 外键
  • 主键(第一个用户,第二个用户)

用户表的表示

@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);
}
}

UserFriendRequests 表的表示

@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 的学习曲线很陡峭,但它也有以下优点:

  1. 由于“脏检查”,插入/更新更容易。服务就绪后,您可以轻松添加新字段,而无需更改服务中的一行。您只需添加新列并填充这些列,Hibernate 就会处理持久性部分。
  2. Hibernate 可以解决 "lost update"问题是因为它是乐观锁定并发控制。
  3. 集成测试更容易,因为您可以为内存数据库(HSQLDB、H2、Derby)自动生成模式
  4. 它有缓存插件支持(通过第三方二级缓存提供商),一些提供商允许您同时拥有“事务”和“集群”缓存。
  5. 它具有内置的 AUDIT 支持 (Envers)

所以它不是“默认”持久性解决方案,因为有数百万用 PHP 编写的没有 ORM 框架的 Web 应用程序在生产环境中成功运行。

我认为 Hibernate 对于缓存、审计、并发可靠性是强制性非功能性要求的企业应用程序更有意义。

关于java - 使用 Hibernate 表示表关系是个好主意吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23930151/

相关文章:

java - Spring JavaMailSender、Tomcat、JNDI

mysql - 如何获得总和(具体)

mysql - 如何让mysql和php协同工作而不显示数据库密码

sql - 将 SQL 用于 rails 参数/值

php - MySQL INNER JOIN 首先按多个匹配排序

java - 为什么列表< map <?扩展号码,? extends Number>> 不适用于 List<Map<Integer,Double>>

java - 列表如何在 RTF 中工作

php - 将产品详细信息插入 'product' 表,并将产品图像插入 'image' 表

sql - 使用动态透视/逆透视来正确显示

java - 如何从sqlite数据库android获取一个值?