2010-12-12 37 views
4

Utilisation de Play! Cadre, j'ai les deux modèles suivants:Violation de la contrainte d'intégrité

@Entity 
public class User extends Model { 
    public String firstName; 
    public String lastName; 
    public String email; 
    public String password; 
    public boolean isAdmin; 

    @OneToMany(mappedBy="id", cascade=CascadeType.ALL) 
    public List<Site> sites; 

    public User(String firstName, String lastName, String email, String password) { 
     this.firstName = firstName; 
     this.lastName = lastName; 
     this.email = email; 
     this.password = password; 
    } 

    public static User connect(String email, String password) { 
     return User.find("byEmailAndPassword",email,Crypto.passwordHash(password)).first(); 
    } 

    public static User findUser(String email) { 
     return User.find("byEmail",email).first(); 
    } 

    public static User createUser(String firstName, String lastName, String email, String password, boolean isAdmin) { 
     String pw = Crypto.passwordHash(password); 

     User u = new User(firstName, lastName, email, pw); 
     u.isAdmin = isAdmin; 
     u.save(); 
     return u; 
    } 
} 

@Entity 
public class Site extends Model { 

    public UUID siteId; 

    public String alias; 
    public String protocol; 
    public String host; 
    public String username; 
    public String password; 
    public int port; 
    public String rootPath; 

    @Lob 
    public String description; 

    @ManyToOne 
    public User user; 

    public Site(User user, String alias, String protocol, String host, String username, String password) { 
     this.user = user; 
     this.alias = alias; 
     this.protocol = protocol; 
     this.host = host; 
     this.username = username; 
     this.password = password; 
     this.port = 21; 
     this.siteId = UUID.randomUUID(); 

    } 
} 

Quand je tente de lancer le test suivant:

public class BasicTest extends UnitTest { 

    @Before 
    public void setup() { 
     Fixtures.deleteAll(); 
    } 

    @Test 
    public void createAndRetrieveUser() { 
     new User("Jason","Miesionczek","something","something").save(); 
     User jason = User.find("byEmail", "something").first(); 

     assertNotNull(jason); 
     assertEquals("Jason", jason.firstName); 
    } 

    @Test 
    public void userSite() { 
     new User("Jason","Miesionczek","something","something").save(); 
     User jason = User.find("byEmail", "something").first(); 

     new Site(jason, "InterEditor","ftp","something","something","something").save(); 

     List<Site> sites = Site.find("byUser", jason).fetch(); 

     assertEquals(1, sites.size()); 

     Site site1 = sites.get(0); 
     assertNotNull(site1); 
     assertEquals("InterEditor", site1.alias); 
     assertNotNull(site1.siteId); 
    } 



} 

Et je reçois cette erreur:

A javax.persistence.PersistenceException has been caught, org.hibernate.exception.ConstraintViolationException: could not insert: [models.Site] 
In /test/BasicTest.java, line 27 : 
new Site(jason, "InterEditor","ftp","something","something","something").save(); 

sortie du journal:

00:06:26,184 WARN ~ SQL Error: -177, SQLState: 23000 
00:06:26,184 ERROR ~ Integrity constraint violation - no parent FK2753674FD92E0A 
table: USER in statement [insert into Site (id, alias, description, host, passw 
ord, port, protocol, rootPath, siteId, user_id, username) values (null, ?, ?, ?, 
?, ?, ?, ?, ?, ?, ?)] 

Quelqu'un peut-il m'aider? Comprendre ce que l'erreur signifie et ce que je fais mal?

+0

Je suis pas sûr si c'est la cause de votre problème, mais Hibernate exige "Toutes les classes persistantes doivent avoir un constructeur par défaut" (plus de précision, aucun constructeur d'argument). Je ne l'ai pas vu pour Site et Utilisateur. – Ralph

Répondre

6

Votre problème ici est le mappage entre la classe de modèle Site et la classe de modèle User. L'erreur indiquée est une clé étrangère manquante.

Si vous mettez en commentaire la liste des sites dans votre classe d'utilisateurs, votre test passera. Cela a donc réduit le problème.

Mise à jour:

Le problème est que lorsque votre objet du site est enregistré, il sauvera l'enfant d'abord des objets (qui comprend l'objet utilisateur). Lorsque cela se produit, il essaie de créer une référence à l'objet Site (à cause du paramètre mappedBy), mais cela n'a pas encore été sauvegardé (ceci sera fait APRES la sauvegarde de l'objet User).

Ainsi, une alternative serait de la carte par une valeur que vous avez accès à (comme le siteId), ou ajouter l'utilisateur au site après qu'il a été enregistré (si la valeur d'identification a été généré.

j'ai changé votre code pour être mappedBy="siteId" et l'essai fin.

+0

me semble bon! –

+0

J'ai essayé votre suggestion, et maintenant je reçois cette erreur: –

+0

09: 17: 54710 ERREUR ~ Unsuccessful: alter table du site Ajouter un index FK2753671A145791 ( siteId), ajouter la contrainte FK2753671A145791 références clés étrangères (SITEID) Utilisateur (i d) 09: 17: 54,710 ERROR ~ BLOB/TEXT colonne 'siteId' utilisée dans la spécification de clé sans une longueur de clé –

2

Je résolu un problème en utilisant « INITIALEMENT REPORTÉ DEFERRABLE » dans Oracle, ce qui retarde la vérification jusqu'à ce que vous commettez la transaction entière!