web-dev-qa-db-fra.com

Utilisation de la classe Integer wrapper ou de la primitive int dans la mise en veille prolongée

Dans l'entreprise pour laquelle je travaille, nous avons cette discussion majeure sur l'opportunité d'utiliser des classes wrapping pour les primitives (Java.lang.Integer, Java.lang.Long) ou s'il faut utiliser les types primitifs directement dans les POJO qui mappent Entités aux tables dans Hibernate.

L'idée est que nous voulons que ces valeurs ne soient pas nulles dans la base de données.

Les arguments en faveur de l'utilisation de primitives:

  • La gestion de ces valeurs en int signifie qu'elles ne peuvent jamais être nulles, ce qui rend impossible d'obtenir par inadvertance une référence nulle sur le champ.
  • int = 32/64 bits de mémoire. Entier = 16 octets de mémoire et est également plus lent

Les arguments en faveur de l'utilisation d'objets wrapper:

  • Nous pouvons ajouter une contrainte au niveau de la base de données pour toujours empêcher les valeurs nulles d'y arriver
  • Nous pouvons nous retrouver avec des données trompeuses, nous pouvons avoir des 0 au lieu de null dans la base de données chaque fois que l'utilisateur ne définit pas de valeur et les données de buggy sont un problème difficile.
  • Les objets ont plus de pouvoir expressif que les primitifs. Nous avons des valeurs nulles et également des valeurs entières, nous pouvons donc les valider plus facilement en utilisant des annotations par exemple (javax.validation.constraints.NotNull).
38
vanvasquez

Utilisez des emballages, simplifiez-vous la vie.

Votre modèle de données devrait le dicter. Vous devez de toute façon appliquer la nullité dans la base de données.

S'ils peuvent être annulés dans la base de données, utilisez des wrappers. S'ils ne sont pas annulables et que vous utilisez des wrappers, vous obtiendrez une exception si vous essayez d'insérer un null dans la base de données.

Si votre modèle de données ne le dicte pas, optez pour une convention, utilisez des wrappers tout le temps. De cette façon, les gens n'ont pas à penser ou à décider qu'une valeur de 0 signifie null.

Je voudrais également interroger votre affirmation selon laquelle ce serait moins performant. L'avez-vous mesuré? Je veux dire vraiment mesuré? Lorsque vous parlez à une base de données, il y a beaucoup plus de considérations que la différence entre 16 bits et 32 ​​bits.

Utilisez simplement la solution simple et cohérente. Utilisez des wrappers partout, à moins que quelqu'un ne vous donne très une bonne raison (avec des statistiques précises) de faire autrement.

36
Matthew Farwell

J'ai pensé qu'il fallait le mentionner:

La recommandation Hibernate (section 4.1.2) utilisant des propriétés non primitives dans des classes persistantes fait en fait référence - comme intitulé - à propriétés d'identificateur:

4.1.2. Fournir une propriété d'identifiant

Le chat a une propriété appelée id. Cette propriété correspond aux colonnes de clé primaire d'une table de base de données. La propriété peut avoir été appelée n'importe quoi et son type peut être n'importe quel type primitif, n'importe quel type "wrapper" primitif, Java.lang.String ou Java.util.Date.

...

Nous vous recommandons de déclarer des propriétés d'identificateur à nom cohérent sur les classes persistantes et d'utiliser un type nullable (c'est-à-dire non primitif).

Néanmoins, les avantages des primitives ne sont pas forts:

  1. Avoir une valeur non nulle incohérente dans une propriété est pire que NullPointerException, car le bogue caché est plus difficile à suivre: plus de temps passera puisque le code est écrit jusqu'à ce qu'un problème soit détecté et il peut apparaître dans un contexte de code totalement différent de celui sa source.
  2. Concernant les performances: avant de tester le code - c'est généralement une considération prématurée. La sécurité doit venir en premier.
11
yair

La documentation Hibernate (juste la première version que j'ai trouvée) indique:

La propriété peut avoir été appelée n'importe quoi et son type peut être n'importe quel type primitif, n'importe quel type "wrapper" primitif, Java.lang.String ou Java.util.Date.

...

Nous vous recommandons de déclarer des propriétés d'identificateur à nom cohérent sur les classes persistantes et d'utiliser un type nullable (c'est-à-dire non primitif).

La "voix de l'expert" suggère donc d'utiliser Integer/Long... mais ce n'est pas décrit pourquoi c'est le Cas.

Je me demande si c'est pour qu'un objet qui n'a pas encore été persisté puisse être créé sans un identifiant (c'est-à-dire avec une valeur de propriété de null), le distinguant des entités persistantes.

5
Jon Skeet