【发布时间】: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