OneToOne entre deux tables, avec partage de la clé primaire
Je vais essayer de mettre en place les tableaux suivants en utilisant JPA/Hibernate:
User:
userid - PK
name
Validation:
userid - PK, FK(user)
code
Il peut y avoir de nombreux utilisateurs, et chaque utilisateur peut avoir max un code de validation ou d'aucun.
Voici mes classes:
public class User
{
@Id
@Column(name = "userid")
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long userId;
@Column(name = "name", length = 50, unique = true, nullable = false)
protected String name;
...
}
public class Validation
{
@Id
@Column(name = "userid")
protected Long userId;
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn(name = "userid", referencedColumnName = "userid")
protected User user;
@Column(name = "code", length = 10, unique = true, nullable = false)
protected String code;
...
public void setUser(User user)
{
this.user = user;
this.userId = user.getUserId();
}
...
}
J'ai créer un utilisateur, puis essayez d'ajouter un code de validation à l'aide du code suivant:
public void addValidationCode(Long userId)
{
EntityManager em = createEntityManager();
EntityTransaction tx = em.getTransaction();
try
{
tx.begin();
//Fetch the user
User user = retrieveUserByID(userId);
Validation validation = new Validation();
validation.setUser(user);
em.persist(validation);
tx.commit();
}
...
}
Quand j'essaie de le lancer, je reçois un org.mise en veille prolongée.PersistentObjectException: détaché entité passé à persister: l'Utilisateur
J'ai aussi essayé d'utiliser le code suivant dans ma Validation de classe:
public void setUserId(Long userId)
{
this.userId = userId;
}
et quand j'ai créer un code de validation je n'ai tout simplement:
Validation validation = new Validation();
validation.setUserId(userId);
em.persist(validation);
tx.commit();
Mais alors, étant donné que l'Utilisateur est null je reçois org.mise en veille prolongée.PropertyValueException: non-null références de propriété a la valeur null ou transitoire de la valeur: l'Utilisateur.code
Serais reconnaissant de toute aide sur la meilleure façon de résoudre ce problème!
OriginalL'auteur Jonas | 2011-04-27
Vous devez vous connecter pour publier un commentaire.
Si vous utiliser Hibernate vous pouvez également utiliser
Hibernate assurez-vous que l'ID de Validation sera le même que l'IDENTIFIANT de l'entité Utilisateur défini.
OriginalL'auteur Ben
J'ai été en mesure de résoudre ce problème de "OneToOne entre deux tables, avec partage de clé primaire" dans la pure JPA 2.0 manière(Grâce à de nombreux threads sur SOF). En fait il y a deux façons de JPA pour gérer cela. J'ai utilisé eclipselink en tant que fournisseur JPA et MySql comme base de données. Pour mettre en évidence une fois de plus pas de propriétaire eclipselink classes ont été utilisés ici.
Première approche consiste à utiliser la génération AUTOMATIQUE de type de stratégie sur l'Entité Mère du champ d'Identificateur.
Entité mère doit contenir l'Enfant Type d'Entité membre en relation OneToOne(cascade type de PERSISTER et de mappedBy = Parent Type d'Entité membre de l'Entité Enfant)
Enfant Entité ne doit pas contenir un identificateur de champ. Il doit contenir un membre de l'Entité Mère Type avec l'Id, OneToOne et JoinColumn annotations. JoinColumn devez spécifier le nom du champ code de la table DB.
Approche ci-dessus à l'interne utilise une valeur par défaut de la table DB nommé SÉQUENCE pour l'affectation de valeurs pour le champ identifiant. Si ce n'est déjà l'heure actuelle, Cette table doit être créé comme ci-dessous.
Deuxième approche consiste à utiliser personnalisés de génération de TABLE de type stratégie et TableGenerator annotation sur l'Entité Mère du champ d'Identificateur.
Sauf changement ci-dessus dans le champ d'identificateur de tout le reste demeure inchangé dans l'Entité Mère.
Il n'y a pas de changement dans l'Entité Enfant. Il reste le même que dans la première approche.
Ce tableau générateur approche utilise en interne une table DB APP_SEQ_STORE pour l'affectation de valeurs pour le champ identifiant. Ce tableau doit être créé comme ci-dessous.
OriginalL'auteur nirmalsingh
Êtes-vous en utilisant JPA ou JPA 2.0 ?
Si la Validation PK est un FK à l'Utilisateur, alors vous n'avez pas besoin de la Longue identifiant de l'attribut dans la validation de la classe, mais au lieu de faire la
@Id
annotation seul. Il serait:Essayer avec elle et dites-nous vos résultats.
Comment vous pouvez définir
userId
champ danssetUser()
lorsque vous n'avez pas le définir?OriginalL'auteur will824
Vous devez définir
userId
etuser
.Si vous définissez simplement la
user
, puis leid
pourValidation
est 0 et est réputé détaché. Si vous définissez simplement lauserId
, alors vous avez besoin pour faire de lauser
propriété nullable, qui n'a pas de sens ici.Pour être sûr, vous pouvez mettre les deux dans un seul appel de méthode:
J'ai marqué la méthode
@Transient
pour que Hibernate va l'ignorer. Aussi, de sorte que vous pouvez toujours avoirsetUser
etsetUserId
fonctionner comme prévu avec toutes les "effets indésirables".OriginalL'auteur Jeremy