使用相同ID的Hibernate DB Object映射时出错

时间:2018-06-08 01:11:32

标签: java hibernate spring-mvc

我正在使用Spring MVC和Hibernate进行练习项目。知道Hibernate可以使用注释将db行映射到对象,我尝试使用Query将所有Account对象从db获取到列表,而在插入它们时,它们有一些重复的ID。

获取帐户的代码

@Override
public List<Account> getAccounts() {
    List<Account> list = new ArrayList<>();
    try {
        Session session = sessionFactory.getCurrentSession();
        Query<AccountEntity> query = session.createQuery("From AccountEntity", AccountEntity.class);
        List<AccountEntity> accounts = query.getResultList();
        for (int i = 0; i < accounts.size(); i++) {
            AccountEntity accountEntity = (AccountEntity) accounts.get(i);
            Account account = new Account();
            account.setAccountNo(accountEntity.getAccNo());
            account.setAccountHolderName(accountEntity.getAccHolderName());
            account.setBalance(accountEntity.getBalance());
            account.setAccountType(accountEntity.getAccountType());
            account.setPsCode(accountEntity.getPsCode());
            account.setDateOfBirth(accountEntity.getDateOfBirth());
            System.out.println("#: " + account.getAccountNo() + ", name: " + account.getAccountHolderName());
            list.add(account);
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return list;
}

现在,当我在视图中使用它们时,重复的ID会产生具有相同ID,名称和平衡的行(数据库中的名称不同)。rows become the same

是因为Hibernate中的映射只依赖于ID,如果ID相同,它会生成相同的对象。

带注释的AccountEntity类:

@Entity    @table(名称= “帐户”) 公共类AccountEntity {

@Id
@Column(name="accountNo")
private int accNo;

@Column(name="accountHolderName")
private String accHolderName;

@Column(name="balance")
private int balance;

@Column(name="accountType")
private String accountType;

@Column(name="dateOfBirth")
private Date dateOfBirth;

@Column(name="psCode")
private String psCode;

public AccountEntity() {
}

public int getAccNo() {
    return accNo;
}

public void setAccNo(int accNo) {
    this.accNo = accNo;
}

public String getAccHolderName() {
    return accHolderName;
}

public void setAccHolderName(String accHolderName) {
    this.accHolderName = accHolderName;
}

public int getBalance() {
    return balance;
}

public void setBalance(int balance) {
    this.balance = balance;
}

public String getAccountType() {
    return accountType;
}

public void setAccountType(String accountType) {
    this.accountType = accountType;
}

public Date getDateOfBirth() {
    return dateOfBirth;
}

public void setDateOfBirth(Date dateOfBirth) {
    this.dateOfBirth = dateOfBirth;
}

public String getPsCode() {
    return psCode;
}

public void setPsCode(String psCode) {
    this.psCode = psCode;
}

} 如果我在这里删除@Id怎么办?

2 个答案:

答案 0 :(得分:0)

@Id注释声明实体中的主键字段。休眠中的每个实体都应该有一个主键。如果accountNo是数据库中的主键列,为什么表中有重复的条目。如果表中没有主键列,请考虑使用伪主键列。

您需要使用主键对实体执行任何CRUD操作。您可以选择不向用户显示主键。对于大多数关系数据库,您可以将主键设置为由数据库自动生成。例如,以下代码将指示hibernate依赖数据库生成id列。

    @Id
    @GeneratedValue
    @Column(name = "ItemId", unique = true, nullable = false)
    private Integer                     Id;

例如,在SQL Server中,您可以将列定义为: [ItemId] [int] IDENTITY(10000000,1)NOT NULL,

答案 1 :(得分:0)

Hibernate在其第一级缓存(Hibernate会话)中通过ID缓存对象。一旦找到Id的对象并缓存它,它总是在Hibernate会话的生命周期内返回相同的对象实例。 (这是一种称为&#34;身份地图&#34;的模式,给出here给出了一个很好的解释。

@Id标记映射到映射到实体类的表的主键的字段。主键值必须是唯一的,表中没有两行可以具有相同的Id值。 Hibernate希望你映射到某种关系模型,而不仅仅是任何随机垃圾,这意味着密钥必须是唯一的。

顺便说一句,请注意,您不应该捕获已发布代码中显示的异常,只是让它们被抛出。您可以指定标有@ControllerAdvice的组件来处理从控制器抛出的异常。最简单,最直接的方法是使用与控制器分开的事务服务层来实现业务逻辑和数据访问。