【问题标题】:Spring + JPA + H2 Strange behaviours of lazy fetch and bidirectional OneToManySpring + JPA + H2 延迟获取和双向 OneToMany 的奇怪行为
【发布时间】:2020-11-26 16:39:25
【问题描述】:

我在 JPA 上玩了很长时间,过去是通过 EJB,现在是 Spring。我最近注意到一些我很难解释的奇怪行为。

首先是双向 OneToMany 我的双向 OneToMany 已正确设置为 mappedBy。

@Entity
public class EntityOne {
    @Id @GeneratedValue
    private int id;
    @OneToMany(mappedBy = "one")
    private Set<EntityTwo> twos;
...


@Entity
public class EntityTwo {
    @Id @GeneratedValue
    private int id;
    @ManyToOne
    private EntityOne one;
...

那么这不会更新数据库:

@Transactional
public void firstWay(){
    EntityOne e1=em.find(EntityOne.class,1);
    EntityTwo e2=em.find(EntityTwo.class,1);
    e1.getTwos().add(e2);
}

虽然这样做:

@Transactional
public void secondWay(){
    EntityOne e1=em.find(EntityOne.class,1);
    EntityTwo e2=em.find(EntityTwo.class,1);
    e2.setOne(e1);
}

我很困惑……

然后是惰性抓取:

   // this is just a tool example...
     public void someFindBy() { 
        EntityOne e1=em.find(EntityOne.class,1);
        for (EntityTwo e2:e1.getTwos()) {
            System.out.println(e2);
        }
    }

导致 LazyExceptionError...我的“e1”实体不应该一直连接到方法结束并因此休眠解决提取(我使用默认持久性上下文,即事务范围。我也尝试过通过使用 @Transactional 注释方法来使方法具有事务性,但这并没有改变任何东西)。 所以,好吧,我可以使用 Entity Graph 或 Join Fetch,但是,我仍然想知道为什么它不能按原样工作......

这里是 Spring 配置文件:

@Configuration
@ComponentScan(basePackages = {"facade"})
@EnableTransactionManagement
public class ClientWebConfig extends WebMvcConfigurerAdapter {


    @Bean
    public DataSource dataSource() {
        EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
        EmbeddedDatabase db = builder
                .setType(EmbeddedDatabaseType.H2)
                .build();
        return db;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean em
                = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource());
        em.setPackagesToScan(new String[] { "model" });

        JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        em.setJpaProperties(additionalProperties());

        return em;
    }

    Properties additionalProperties() {
        Properties properties = new Properties();
        properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
        properties.setProperty(
                "hibernate.dialect", "org.hibernate.dialect.H2Dialect");
        properties.setProperty("hibernate.hbm2ddl.import_files" ,"insert-data.sql");
        return properties;
    }

    @Bean
    public PlatformTransactionManager transactionManager(
            EntityManagerFactory emf){
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(emf);

        return transactionManager;
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
        return new PersistenceExceptionTranslationPostProcessor();
    }

}

【问题讨论】:

  • 第一部分是正常行为,因为属性“one”是关系的所有者。
  • 懒惰的部分也是正常的,只要你的方法不是事务性的。
  • 好吧,几个月后回到这个问题和我的代码,它发生了lazyexception已经消失了......(我什至不需要添加级联,也不需要孤儿删除,也不需要在OneToMany 标签...)。发生了什么我不知道,只是将我的 jdk 更改为 14 并且无法弄清楚它是如何得到它的......

标签: spring jpa lazy-loading h2 one-to-many


【解决方案1】:

修复此实体。

cascade,fetch必须设置为update。

@Entity
public class EntityOne {
    @Id @GeneratedValue
    private int id;

    **@OneToMany(mappedBy = "one", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)**
    private Set<EntityTwo> twos;

【讨论】:

    猜你喜欢
    • 2021-05-06
    • 2016-01-09
    • 1970-01-01
    • 2016-02-18
    • 1970-01-01
    • 1970-01-01
    • 2014-07-29
    • 1970-01-01
    • 2011-09-04
    相关资源
    最近更新 更多