简体   繁体   中英

Error when Hibernate DB Object mapping using same ID

I am doing a practice project with Spring MVC and Hibernate. Knowing that Hibernate can use annotation to map the db row to a object, I try to use Query to get all the Account object from the db to a list, while when inserting them, they have some duplicated ID.

Code to get accounts

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

Now, when I use them in the views, the duplicated IDs produce rows with the same ID, name and balance (the names are not the same in the db). rows become the same

Is it because the mapping in Hibernate relies simply on the ID, if the ID is the same, it produces the same object.

AccountEntity class with annotations:

@Entity @Table(name="account") public class 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;
}

} What if I remove @Id here?

@Id annotation declare the primary key field in the entity. Each entity in hibernate should have a primary key. Why do you have duplicate entries in your table if accountNo is primary key column in database. If there is no primary key column in table, consider having a pseudo primary key column.

You will need the primary key to do any CRUD operations on the entity. You can choose to not display the primary key to user. For most of the relational databases you can set the primary key to be auto generated by the database. For example the following code will direct hibernate to rely on database for generation of id column.

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

For example in SQL Server you can define the column as: [ItemId] [int] IDENTITY(10000000,1) NOT NULL,

Hibernate caches objects by ID in its first level cache (the Hibernate session). Once it finds an object for an Id and caches it, it always returns the same object instance for the life of the Hibernate session. (This is a case of a pattern called "identity map", there's a good explanation given here ).

@Id marks the field mapped to the primary key of the table mapped to the entity class. Primary key values have to be unique, no two rows of the table can have the same Id value. Hibernate expects you to map to some kind of relational model, not just any random junk, and that means keys have to be unique.

BTW be aware that you shouldn't be catching exceptions as shown in your posted code, just let them be thrown. You can specify a component marked with @ControllerAdvice to handle exceptions thrown from the controller. The easiest and most straightforward approach is to use a transactional service layer separate from controllers for business logic and data access.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM