web-dev-qa-db-fra.com

Encadré vs type primitif comme id d'entité

Dans JPA (implémentation Hibernate) Quel type est préférable d'utiliser comme identifiant d'entité: Type en boîte (par exemple Integer) ou type sans boîte (par exemple int)?

Un ami a dit que vous devriez utiliser des types Boxed, car lorsque vous créez une nouvelle entité dans votre programme, Hibernate voit que l'identifiant est null et comprend qu'il doit créer une nouvelle ligne dans la base de données (par contre si id n'est pas null Hibernate peut mettre à jour une ligne existante dans la base de données).

Mais l'identifiant de mes entités était int et cela a bien fonctionné sans erreur. Nous savons que la valeur par défaut des variables d'instance primitive est 0. Donc, il a dit que peut-être que Hibernate traite 0 comme spécial et suppose que l'objet est nouveau.

20
Mahozad

Eh bien, nous utilisons des non-primitifs et nous avons une forte raison à cela. Beaucoup de nos champs qui sont soit int/Integer, par exemple, ont une valeur commerciale absolue de zero pour être parfaitement valides. Pensez à un champ de dette par exemple - il est plus que OK si le champ est zero, ce qui signifie que vous n’avez aucune dette. 

Le problème est qu'avec les primitives, zéro est une valeur par défaut - vous pouvez donc oublier accidentellement de le définir, par exemple, via une variable setDebt, de sorte qu'il pourrait atteindre votre base de données avec une valeur que vous n'aviez jamais envisagée d'y aller. Pour cette raison, nous utilisons Integer avec certaines validations qui ne devraient jamais être nulles par exemple; mais même si nous oublions d’ajouter des validations appropriées, ce code va potentiellement rompre avec un NullPointerException (de préférence dans les tests) et j’aime mieux une exception que des valeurs incohérentes dans la base de données. 

7
Eugene

Semble Documentation actuellerecommande d’utiliser le type Boxed.

Nous vous recommandons de déclarer les attributs d'identifiant portant le même nom sur les classes persistantes et d'utiliser un type nullable (c'est-à-dire non primitif).

9
gtgaxiola

Il n'y a pas de différence entre primitive (par exemple, int) et son enveloppe (par exemple, Integer) pour l'identificateur d'entité. Les deux sont valides selon les spécifications JPA. Le fournisseur JPA est suffisamment intelligent pour suivre l'état et le cycle de vie d'une entité. Lorsque l'ID d'entité est égal à 0 (type primitif) ou à NULL (type d'enveloppe), le fournisseur JPA génère un identifiant pour l'entité si un générateur d'identificateur est configuré. Zéro n'est pas considéré comme un identifiant d'entité valide si l'identifiant est généré automatiquement.

Testé les deux cas avec Cmobilecom JPA, et cela fonctionne aussi bien. Bien sûr, aucune différence de performance ne peut être remarquée.

Disclaimer: Je suis un développeur de Cmobilecom JPA , une implémentation JPA légère pour Java et Android.

2
John

Les identifiants uniques d'entités et de collections peuvent être de tous types sauf binaires, blob et clob. (Les identifiants composites sont également autorisés, voir ci-dessous.)

Les types de valeur de base ont les constantes Type correspondantes définies dans org.hibernate.Hibernate. Par exemple, Hibernate.STRING représente le type de chaîne.

0
Angad Bansode

Je préfère Boxed Type dans le modèle d'entité, car cela donne de la flexibilité pour utiliser Boxed Type dans les génériques . Par exemple, ici, le modèle d'entité ne peut avoir que le type qui s'étend à Serializable for id. Ce sera utile plus tard dans la couche service où nous pouvons effectuer diverses opérations sur la clé primaire.

public interface BaseEntity<E extends Serializable> extends Serializable {
  E getId();
}

Le modèle d'entité pourrait être comme:

@Entity
public class PhoneNumber implements BaseEntity<Long> {
  private static final long serialVersionUID = 1L;

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "PHONE_NUMBER_ID")
  private Long id;
0
pradipforever