JPA / Hibernate-一对多列表与集合优化

问题描述 投票:0回答:1

我在帐户(一个)之间有一个简单的一对多双向关联交易(许多)

@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

list hibernate jpa set one-to-many
1个回答
0
投票
© www.soinside.com 2019 - 2024. All rights reserved.