微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Kotlin Spring Data JPA - 声明的非空类型为 NULL

如何解决Kotlin Spring Data JPA - 声明的非空类型为 NULL

使用 Kotlin、Spring Data JPA 和 Hibernate。 考虑以下 JPA 实体:

@Entity
@Table(name = "applications")
class Application(

    @Column(name = "name",nullable = false)
    var name: String,@Column(name = "version",nullable = false)
    var version: String,) {

    @Id
    @SequenceGenerator(name = "seq_gen_application_id",sequenceName = "seq_application_id")
    @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "seq_gen_application_id")
    @Column(name = "id",unique = true,nullable = false)
    var id: Long? = null

    @Embedded
    var/val k8s: K8s = K8s()

    @Embeddable
    class K8s {
        @Column(name = "k8s_image")
        var image: String? = null
    }
}

从语言级别的角度来看,Application.k8s 属性永远不会为空。因此,在不进行任何空检查的情况下访问 k8s 属性应该是安全的。

例如,使用经典 findAll() 中的 CrudRepository 函数

@Repository
interface ApplicationRepository : CrudRepository<Application,Long>

我会得到一个 Application 实例列表,其中非空的 k8s 属性 is null(如果 k8s.image 为空) .

当您访问属性 NullPointerException 时,这将在运行时导致 k8s,即使它不应该(感谢 Kotlin 的空安全机制)。所以它非常令人困惑,并可能导致意想不到的错误。我猜这可能是由一些 Hibernate 互操作性问题引起的? Hibernate 发现 embeddable 类中的所有字段都是空的,所以它使用反射将其设置为空?

解决方案 1:

声明 k8s 属性(和其他嵌入的实体)始终可以为空,这将强制进行额外的空检查。

解决方案 2:

@Embedded
var k8s: K8s = K8s()
   get() = if (field == null) K8s() else field

这也令人困惑,因为对不可空类型进行了空检查。所以它会生成一个编译器警告: Condition 'field == null' is always 'false'

解决方案 3: 声明一个带有虚拟属性的辅助类,以确保总有一些东西永远不会为空。

@Embeddable
@MappedSuperclass
open class NonNullEmbeddable {
    @Formula("0")
    private var internalNonNullProperty: Int = 0
}

用法

class K8s : NonNullEmbeddable() {
    @Column(name = "k8s_image")
    var image: String? = null
}

有什么想法吗?这是错误还是预期行为?

我会理解 Application 实体是否来自 Java 代码 (https://kotlinlang.org/docs/java-interop.html#null-safety-and-platform-types)。但是由于 Application 被声明为 Kotlin 类,所以感觉是错误的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。