我在帐户(一个)之间有一个简单的一对多双向关联交易(许多)
@Entity
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...
@OneToMany(mappedBy = "account")
private List<Transaction> transactions = new ArrayList<>();
@Entity
public class Transaction {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...
@ManyToOne
@JoinColumn(name = "ACCOUNT_ID")
private Account account;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Transaction that = (Transaction) o;
return Objects.equals(id, that.id);
}
@Override
public int hashCode() {
return 31;
}
}
帐户(ID = 1)已进行过一笔交易。而且,我要添加向该帐户添加另一笔交易。代码块在事务的上下文中运行。所有断言都通过:
execute(entityManager -> {
Account account = entityManager.find(Account.class, 1L);
//assertThat(account.getTransactions().size(), is(1));
Transaction t1 = new Transaction();
t1.setTitle("Buy veggies");
t1.setAmount(100);
account.getTransactions().add(t1); // ###
t1.setAccount(account);
entityManager.persist(t1);
//assertThat(account.getTransactions().size(), is(2));
});
请注意标记为###的行,在该行中加载了集合的许多方面。我希望Hibernate在'Transaction'实体上发出SELECT,但没有。我包括以下日志:
Hibernate:
select
account0_.id as id1_0_0_,
account0_.initial_balance as initial_2_0_0_,
...
from
account account0_
where
account0_.id=?
17:06:22.970 [main] TRACE o.h.type.descriptor.sql.BasicBinder - binding parameter [1] as [BIGINT] - [1]
Hibernate:
insert
into
transaction
(id, account_id, amount, title)
values
(null, ?, ?, ?)
17:06:22.973 [main] TRACE o.h.type.descriptor.sql.BasicBinder - binding parameter [1] as [BIGINT] - [1]
17:06:22.973 [main] TRACE o.h.type.descriptor.sql.BasicBinder - binding parameter [2] as [DOUBLE] - [100.0]
17:06:22.973 [main] TRACE o.h.type.descriptor.sql.BasicBinder - binding parameter [3] as [VARCHAR] - [Buy veggies]
在交易结束时,我验证了数据的完整性,并且一切正常。传递了以下断言(运行新的事务上下文):
execute(entityManager -> {
Account account = entityManager.find(Account.class, 1L);
assertThat(account.getTransactions().size(), is(2));
});
有人可以解释为什么account.getTransactions()。add(t1)没有触发SQL SELECT吗?这是Hibernate的优化还是我缺少任何东西?
为了增加混乱,我将集合更改为Set(其他所有内容与以前一样)。
@OneToMany(mappedBy = "account")
private Set<Transaction> transactions = new HashSet<>();
现在,我注意到了日志中的预期-在调用account.getTransactions()。add(t1)时确实发出了sql SELECT:
Hibernate:
select
account0_.id as id1_0_0_,
account0_.initial_balance as initial_2_0_0_,
...
from
account account0_
where
account0_.id=?
17:09:23.056 [main] TRACE o.h.type.descriptor.sql.BasicBinder - binding parameter [1] as [BIGINT] - [1]
Hibernate:
select
transactio0_.account_id as account_4_6_0_,
transactio0_.id as id1_6_0_,
transactio0_.id as id1_6_1_,
transactio0_.account_id as account_4_6_1_,
transactio0_.amount as amount2_6_1_,
transactio0_.title as title3_6_1_
from
transaction transactio0_
where
transactio0_.account_id=?
17:09:23.057 [main] TRACE o.h.type.descriptor.sql.BasicBinder - binding parameter [1] as [BIGINT] - [1]
Hibernate:
insert
into
transaction
(id, account_id, amount, title)
values
(null, ?, ?, ?)
17:09:23.059 [main] TRACE o.h.type.descriptor.sql.BasicBinder - binding parameter [1] as [BIGINT] - [1]
17:09:23.059 [main] TRACE o.h.type.descriptor.sql.BasicBinder - binding parameter [2] as [DOUBLE] - [100.0]
17:09:23.059 [main] TRACE o.h.type.descriptor.sql.BasicBinder - binding parameter [3] as [VARCHAR] - [Buy veggies]
hibernate-core 5.4.12.Final in spring-boot 2.2.5.RELEASE