【问题标题】:How do I get "no cascading"-behaviour using spring-boot, spring-data-jpa and hibernate?如何使用 spring-boot、spring-data-jpa 和 hibernate 获得“无级联”行为?
【发布时间】:2018-01-20 16:17:31
【问题描述】:

我正在使用上述库并希望保留一个简单的对象,该对象与另一个对象具有一对一的关系,但不保留关联的对象。这听起来很简单,因为它应该是默认行为。但是,就我而言,出于某种原因,它似乎不是。

我正在使用通过此代码配置的 entityManager:

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, Environment env) {
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    vendorAdapter.setDatabase(Database.POSTGRESQL);

    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setJpaVendorAdapter(vendorAdapter);
    factory.setDataSource(dataSource);

    return factory;
}

@Bean
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory);
    return transactionManager;
}

这是我的实体类:

@Entity
@Table(name = "`Table_A`", schema = "public")
public class ClassA {
    @Id
    @Column(name = "a_id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "value")
    private String value;

    @Column(name = "time")
    private LocalDateTime time;

    @OneToOne(targetEntity = ClassB.class, fetch = FetchType.EAGER)
    @JoinColumn(nullable = false, name = "b_id_ref")
    private ClassB b;

    // getters and setters
}

@Entity
@Table(name = "`Table_B`", schema = "public")
public class ClassB {
    @Id
    @Column(name = "b_id")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;

    @Column(name = "value")
    private String value;

    // getters and setters
}

我不希望 bClassA 引用的对象被持久化。但是,如果我在 ClassA 的实例中更改 value 并在 ClassB 的相应实例中更改 value。我写了一个小测试来演示程序流程:

@Autowired
private ClassARepository repository;

@PersistenceContext
private EntityManager em;

@Test
public void testCascading() {
    Session hibernateSession = em.unwrap(Session.class);
    String newValueA = "Sissi";
    String newValueB = "Franzl";
    ClassA a = createTestInstance();
    ClassB b = a.getB();
    String oldValueA = token.getTokenValue();
    String oldValueB = user.getFirstname();

    a.setValue(newValueA);
    b.setValue(newValueB);
    repository.save(a);
    em.flush();
    hibernateSession.evict(a);
    hibernateSession.evict(b);

    ClassA loadedA = repository.findById(1L);
    assertThat(loadedA.getB().getValue(), equalTo(oldValueB));
    assertThat(loadedA.getValue(), equalTo(newValueA));
}

我检查了“现实世界”中的行为是否相同。正如here 所说,save-操作不应级联。我必须在这里错过一些东西。是否有可能改变默认行为的全局设置?我可以做些什么来实现所需的行为?

【问题讨论】:

  • 您的测试是事务性的,对吗?因此,您将获得一个 managed B,并更改其中一个字段的值。所以改变是持久的。您对 save() 和 flush() 的调用是无用的。 JPA 的全部意义在于,当实体被管理 时,它们的状态会自动 持久化。这是一项功能,而不是错误。
  • 啊,我明白了。事实上,测试是事务性的,我用来测试行为的“真实世界”方法也是如此。愚蠢的我,我应该有足够的经验不会犯那个错误^^。我很乐意接受你的评论作为答案,如果你做出来的话。

标签: java spring hibernate jpa


【解决方案1】:

您的测试是事务性的。因此,您将获得一个 managed B,并更改其中一个字段的值。因此,这种变化是持久的。

顺便说一句,您对save()flush() 的呼叫毫无用处。 JPA 的全部意义在于,当管理实体时,它们的状态会自动持久化。这是一项功能,而不是错误。

【讨论】:

    猜你喜欢
    • 2017-07-09
    • 1970-01-01
    • 2021-01-18
    • 2017-02-24
    • 1970-01-01
    • 2019-07-20
    • 1970-01-01
    • 2019-01-22
    • 2015-04-04
    相关资源
    最近更新 更多