Kotlin:休眠模型中的 属性 声明

Kotlin: property declaration in hibernate model

我们有很多 java 应用程序,并且正在尝试在 Kotlin 中实现我们的第一个应用程序。问题是:初始化简单休眠模型属性的最佳方法是什么?

让我们以Java中的以下示例为例:

@Entity
@Table(name = "Session_Ids")
public class SessionId() {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected Long id;

    @Column
    protected Long number;
}

现在假设数据库中的id 和number 永远不能为null。所以在 hibernate 完成所有事情之后,模型将始终在 id 字段中有一个值,在 number 字段中有一个值。

我如何在 Kotlin 中做到这一点? 我不能用 null 初始化它们,因为我必须将这些字段声明为 Nullable 而它们不应该是。我不能使用 lateinit,因为这两个字段都是原始 long 类型。

我认为防止将它们定义为可为空的唯一方法是使用一些错误的默认值初始化它们。像

var number: Long = -1

但我觉得不对。

在 Kotlin 中做这样的事情有什么最佳实践吗?

提前致谢!

我将 0false"" &c 用于不可为 null 的字段(并且 null 用于可空字段)——以最有意义的为准 '默认值。

(我不确定这是否是最佳做法,但这是我迄今为止看到的最佳选择!)

当然,当加载现有实体时,该值将被覆盖 — 但它可能会在创建新实体时用于您未手动设置的字段。所以这可能会影响您的选择。

我和你有同样的问题,我通过定义变量可以为空来避免它,然后添加注释 @Column(nullable = false),这样你就知道你的实体在数据库中总是有一个 id。这是您可以拥有的示例:

class BaseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(unique = true, nullable = false)
    val id: Long? = null
}

不知道是不是最好的解决办法,希望对你有帮助。

我找到的另一个解决方案是 kotlins 数据 classes 但我仍然不确定这是否是一个好方法。

我问题中 Java class 的 Kotlin 版本如下所示:

@Entity
@Table(name = "Session_Ids")
data class SessionId(

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id: Long?,

    @Column
    var number: Long,
){
    constructor(userId: Long): this(null, userId)
}

id 仍然可以为 null,否则 hibernate 可能会与具有相同 ID 的现有实体发生冲突。唯一的其他选项是 0 作为值,但我认为对于非持久化实体,null 比 0 更可扩展。

我添加了辅助构造函数以防止为 ID 传递 null。

你怎么看?

问题 1 是您的 @Column var number: Long。如果此字段不为空,应移至构造函数并在那里初始化:

class Session(
    @Column
    var number: Long
) 

对所有其他非空字段也应该这样做,它们应该在对象创建期间初始化。

问题 2 是惰性 ID,它始终不为 null,但在对象创建期间不知道,并且在插入时由 Hibernate 填充。这种情况在kotlin中似乎没有解决。作为一种变通方法,我使用 java-base class 来处理 ID 为 属性 的实体:

@MappedSuperclass
public class BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @NonNull
    protected Long id;

}

如果你使用 javax.annotation.Nonnull 或 kotlin 识别的其他非空注释,这个字段将被视为在 kotlin 中声明为非空,你将能够避免在任何地方写 !! .

问题3是父子关系,需要插入两个实体,然后在关系中相互设置,我们希望在两个表中都存储相关的ID以供查询。这在 java 中是可能的,但在 kotlin 中不行,因为它需要在一侧声明一个字段可为空,并强制在所有地方使用 !!,而从业务案例的角度来看,该字段不应为空.在这种情况下,我使用以下解决方法:

@Entity class UserAccount(

    // user can have multiple accounts
    @field:[
        NotNull
        ManyToOne
    ]
    val user: User,

)

@Entity class User {

    // but has always one main account
    @field:[
        OneToOne
        JoinColumn(table = TABLE, name = "main_account_id")
    ]
    private var _mainAccount: UserAccount? = null

    override var mainAccount: UserAccount
        get() = _mainAccount!!
        set(value) {
            _mainAccount = value
        }

}