首页 > 解决方案 > 我如何让 JPA 的多对多关系与 kotlin 一起工作?延迟初始化异常

问题描述

我只是无法绕过它。我已经阅读了所有要阅读的内容,但我无法让它工作。这是一个非常简单的 SQL 结构:

我得到了下表

create table currencies
(
    id INT auto_increment,
    isoAlpha VARCHAR(3) not null,
    isoNumeric VARCHAR(3) not null,
    name VARCHAR(100) not null,
    constraint currencies_pk
        primary key (id)
);

然后

create table countries
(
    id INT auto_increment,
    isoAlpha VARCHAR(3) not null,
    isoNumeric VARCHAR(3) not null,
    name VARCHAR(100) not null,
    constraint countries_pk
        primary key (id)
);

最后是连接这两者的 mm 表:

create table mm_currency_country
(
    currency INT not null,
    country INT not null
);

在我的 Kotlin 代码中,我将实体定义如下:

@Entity
@Table(name = "currencies")
data class Currency (

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Int,

    @Column(nullable = false)
    val isoAlpha: String,

    @Column(nullable = false)
    val isoNumeric: Int,

    @Column(nullable = false)
    val name: String,

    @ManyToMany
    @JoinTable(name = "mm_currency_country",
        joinColumns = [JoinColumn(name = "currency", referencedColumnName = "id")],
        inverseJoinColumns = [JoinColumn(name = "country", referencedColumnName = "id")])
    val countries: Set<Country>
)

和另一个

@Entity
@Table(name="countries")
data class Country (
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Int,

    @Column(nullable = false)
    val isoAlpha: String,

    @Column(nullable = false)
    val isoNumeric: Int,

    @Column(nullable = false)
    val name: String,

    @ManyToMany(mappedBy = "countries")
    val currencies: Set<Currency>
)

我正在使用一个简单的 CrudRepository 来获取货币数据

@Repository
interface RepoCurrencies: CrudRepository<Currency,Int>

当我使用该findAll()功能时,我会获得所有注册货币,但国家列表(在调试器视图中)仅填充有LazyInitializationException错误。看来我需要某种方法EntityGraph才能使它起作用……但是到目前为止,我所有实现此功能的尝试都失败了。有人可以通过这个给我一些指导吗?每个多对多关系总是抛出这个错误还是只是运气问题?!这看起来很基本,hibernate 无法开箱即用地处理它。

标签: hibernatekotlinjpamany-to-manylazy-initialization

解决方案


@ManyToMany默认情况下,关系是延迟获取的,这意味着您的货币对象持有国家属性的代理,当您访问它们时,这些代理会从数据库中加载国家,例如通过迭代集合。为此,您需要一个活动会话。尝试用 注释调用findAll()和访问国家属性的方法@Transactional


推荐阅读