hibernate 在saveAndFlush之后使用spring数据jpa同步@ManyToOne关系

aydmsdu9  于 2023-01-17  发布在  Spring
关注(0)|答案(2)|浏览(203)

我在一个spring Boot 项目中有这个实体。在很多情况下,insertable/updatable为false是有用的,但是在保存实体时会出现问题。下面是代码。

@Entity
@Table(name = "BOOK", schema = "DIST")
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID", nullable = false)
    private Integer id;

    @ManyToOne
    @JoinColumn(name = "AUTHOR_ID", insertable = false, updatable = false)
    private Author author;

    @Column(name = "AUTHOR_ID")
    private Integer authorId;

这种保存新书的方法

@Transational
public void test() {

    Book book = new Book();
    book.setAuthorId(1);

    book = bookRepository.saveAndFlush(book);

    book.getAuthor().getName(); //author is null

}

getAuthor()关系在保存后总是空的,我想知道是否有一种方法可以获取它。换句话说,我希望能够强制填充ManyToOne关系,但我找不到一种干净的方法来完成它。
这种方法行不通。

@Transational
public void test() {

    Book book = new Book();
    book.setAuthorId(1);

    book = bookRepository.saveAndFlush(book);
    book = bookRepository.findById(book.getId());

    book.getAuthor().getName(); //author is still null

}

这个似乎是一个选项,但我不喜欢它。

@Transational
public void test() {

    Book book = new Book();
    book.setAuthorId(1);

    book = bookRepository.saveAndFlush(book);
    entityManager.clear()
    book = bookRepository.findById(book.getId());

    book.getAuthor().getName(); //author is NOT null

}

有什么线索吗?

ckx4rj1h

ckx4rj1h1#

我碰巧也在研究如何解决这个问题。
我们的数据模型/用例还要求我们将外键字段显式定义为一个数字,并包含引用的对象,以便能够轻松地访问其属性。
JPA似乎希望我们在调用保存之前物理地填充嵌套对象。Web上的大多数示例只有多对一字段,而没有单独的数字ID列字段
将缓存隔离注解添加到Book:

@Entity
@Table(name = "BOOK", schema = "DIST")
@Cache(isolation = CacheIsolationType.ISOLATED)
public class Book {

似乎是一个解决方案,但在我看来,这比显式调用EntityManager.clear()更简单。但仍然需要在保存后显式调用getById。在我的场景中,我已经定义了用于解决其他问题的隔离,因此添加额外的get不是一个大问题。添加该高速缓存隔离注解后,您给出的代码示例应该可以正常工作:

@Transational
public void test() {

    Book book = new Book();
    book.setAuthorId(1);

    book = bookRepository.saveAndFlush(book);
    book = bookRepository.findById(book.getId());

    book.getAuthor().getName();

}

我还没能找到更好的解决办法。我会继续关注这个问题,看看是否有人能提供一个。

hgc7kmma

hgc7kmma2#

您可以尝试从EntityManagerSession刷新对象
示例:

import javax.persistence.EntityManager;

@Transational
public void test() {

    Book book = new Book();
    book.setAuthorId(1);

    book = bookRepository.saveAndFlush(book);

    // this will re-read the state of give object 
    // from underlying database
    entityManager.refresh(book);
   

    book.getAuthor().getName(); //author is NOT null

}

相关问题