3
votes

Kotlin: déclaration de propriété dans le modèle Hibernate

Nous avons beaucoup d'applications java et essayons d'implémenter notre première dans Kotlin. La question est: quelle est la meilleure façon d'initialiser les propriétés d'un modèle de mise en veille prolongée simple?

Prenons l'exemple suivant en Java:

var number: Long = -1

Supposons maintenant que le id et le nombre dans la base de données ne peuvent jamais être nuls. Donc, une fois la mise en veille prolongée terminée, le modèle aura toujours une valeur dans le champ id et une valeur dans le champ numérique.

Comment puis-je faire cela dans Kotlin? Je ne peux pas les initialiser avec null car je dois déclarer ces champs comme Nullable, ce qu'ils ne devraient pas être. Je ne peux pas utiliser lateinit car les deux champs sont des types longs primitifs.

La seule façon que je vois pour éviter de les définir comme nullables est de les initialiser avec une valeur par défaut erronée. Quelque chose comme

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

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

    @Column
    protected Long number;
}

Mais cela me semble faux.

Existe-t-il une sorte de bonne pratique pour faire quelque chose comme ça dans Kotlin?

Merci d'avance!


0 commentaires

3 Réponses :


0
votes

J'utilise 0 , false , "" & c pour les champs non nullables (et null pour nullables ones) - celle qui a le plus de sens comme valeur «par défaut».

(Je ne sais pas si c'est la meilleure pratique, mais c'est la meilleure option que j'ai vue jusqu'à présent!)

La valeur sera écrasée lors du chargement d'entités existantes, bien sûr - mais elle peut être utilisée lors de la création de nouvelles, pour les champs que vous ne définissez pas manuellement. Cela peut donc éclairer votre choix.


1 commentaires

J'ai pensé aux mêmes valeurs par défaut, mais je pense que c'est une sorte de connaissance implicite. Je l'aime plus explicite mais je ne sais toujours pas si cela est possible.



-2
votes

J'ai eu le même problème que vous, et je l'ai évité en définissant la variable a nullable, puis ajoutez l'annotation @Column (nullable = false) , afin que vous sachiez que votre entité aura toujours un identifiant dans la base de données. Voici un exemple de ce que vous pourriez avoir:

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

Je ne sais pas si c'est la meilleure solution, mais j'espère que cela vous a aidé.


10 commentaires

J'ai pensé à ça mais je veux empêcher le tout? et !! dans le code lorsque j'accède à ces propriétés. Définir nullable comme false pour la mise en veille prolongée n'aiderait pas pour cela: /


Mmm. Il y a aussi le risque que les champs soient toujours nuls lors de la tentative de sauvegarde; et l'utilisateur de la classe d'entité ne sait pas si null est autorisé ou non.


Si le champ est toujours nul lors de la tentative d'enregistrement, c'est parce que hibernate n'a pas réussi à mettre une valeur dans cette variable, donc le problème se trouvera ailleurs. Je veux dire, si l'hibernation fonctionne correctement, il n'y a aucun moyen d'avoir un identifiant nul, non?


Techniquement oui. Mais vous devez toujours effectuer toutes les opérations de vérification des nuls. Par exemple, vous ne pouvez pas faire quelque chose comme var test: Long = myBaseEntity.id même si l'id ne peut techniquement pas être nul. Ce que je veux, c'est que vous puissiez faire exactement cela. Ma solution possible ci-dessus devrait résoudre ce problème pour toutes les propriétés à l'exception de l'ID. Je cherche toujours une meilleure solution pour le problème d'identité: D


@Materno, bien sûr, j'ai compris quel est votre problème, je viens de répondre à gidds. ;) Je suppose que votre seule solution est d'initialiser vos variables avec des valeurs par défaut, mais si vous trouvez un meilleur moyen d'éviter le problème, veuillez poster une nouvelle réponse, cela m'aidera à coup sûr!


J'ai déjà posté une réponse, celle-là avec la classe de données ci-dessous :) Je ne sais toujours pas si c'est bien ou assez bien: D N'hésitez pas à poster ce que vous en pensez :)


J'ai choisi d'utiliser des classes traditionnelles pour mon projet, mais je ne me souviens pas pourquoi, mais je pense avoir lu quelque part qu'elles étaient parfois boguées avec la mise en veille prolongée. Je ne sais pas si c'est vrai, et peut-être que c'était le cas, mais JetBrain l'a corrigé, je ne sais pas. Mais je pense que si vous pouvez utiliser des classes de données, vous devriez le faire, car elles sont conçues pour représenter des données, et c'est exactement ce que nous voulons faire ici.


Pourquoi votre solution de classe de données résout-elle le problème? Votre constructeur principal est toujours accessible et vous devez toujours vérifier si id est nul ou non lorsque vous souhaitez l'utiliser. Je veux dire, id est toujours un attribut nullable. Donc votre problème est toujours là, non? Ou peut-être ai-je manqué quelque chose?


L'identité a toujours le problème, c'est vrai. Mais je pense (corrigez-moi si je me trompe) que ce n'est pas un gros problème car chaque entité que je crée n'a tout simplement pas d'identifiant avant que je la persiste avec la mise en veille prolongée. Donc, techniquement et logiquement, l'ID peut être nul. La grande amélioration pour moi semble être que tous les autres champs n'ont pas à être nullable comme le "champ numérique" dans mon exemple d'entité. Ils doivent simplement être affectés via le constructeur. Je n'ai pas à le déclarer comme nullable et je n'ai pas à le déclarer avec une sorte de valeur "par défaut" comme dans l'autre réponse.


Vous aurez le même résultat que si vous utilisiez ma solution, je suppose que c'est une question de goût. Mais après avoir lu toutes ces solutions, la vôtre semble être plus propre, car il n'y a pas de «conflit» entre ce qui est écrit dans l'annotation d'hibernation et la façon dont la variable est déclarée, comme dans la mienne, et vous n'avez pas à attribuer une fausse valeur à l'attribut id, comme le suggère gidds. Si vous rencontrez des difficultés en raison de l'utilisation de classes de données, veuillez me le faire savoir dans la section commentaires de votre réponse, je serai curieux de voir s'il y a quelque chose qui ne va pas avec Hibernate et les classes de données. Je vous remercie ;)



-1
votes

Une autre solution que j'ai trouvée sont les classes de données kotlins mais je ne suis toujours pas sûr que ce soit un bon moyen.

La version Kotlin de la classe Java dans ma question ressemblerait à ceci:

@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)
}

L'ID est toujours nullable car sinon, hibernate peut avoir des conflits avec des entités existantes avec les mêmes ID. La seule autre option serait 0 comme valeur mais je pense que pour une entité non persistée, null est plus expactable que 0.

J'ai ajouté le constructeur secondaire pour éviter de passer null pour l'ID.

Que pensez-vous de cela?


0 commentaires