2010-12-12 3 views
4

Использование Play! Framework, у меня есть следующие две модели:Нарушение ограничения целостности

@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(); 

    } 
} 

Когда я пытаюсь запустить следующий тест:

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



} 

И я получаю эту ошибку: выход

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(); 

Log:

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, ?, ?, ?, 
?, ?, ?, ?, ?, ?, ?)] 

Может ли кто-нибудь помочь мне и вы можете понять, что означает ошибка, и что я делаю неправильно?

+0

Я не уверен, что это является причиной вашей проблемы, но Hibernate требует: «У всех постоянных классов должен быть конструктор по умолчанию» (больше настроек, нет конструктор аргументов). Я не видел его для сайта и пользователя. – Ralph

ответ

6

Ваша проблема заключается в сопоставлении между классом модели сайта и классом модели пользователя. Указанная ошибка представляет собой отсутствующий внешний ключ.

Если вы закомментируете список сайтов в своем классе User, ваш тест пройдет. Так что это сузило проблему.

Update:

Проблема в том, что, когда ваш объект сайта сохраняется, это сэкономит дочерние объекты первого (который включает в себя объект пользователя). Когда это происходит, он пытается создать ссылку на объект сайта (из-за параметра mappedBy), но это еще не было сохранено (это будет сделано ПОСЛЕ сохранения объекта User).

Таким образом, альтернативой было бы сопоставить по значению у вас есть доступ к (например, в siteId), или добавить пользователя к Сайту после того, как он был сохранен (так что значение ID сгенерирован.

Я изменил код, чтобы быть mappedBy="siteId" и тестовый прогон отлично.

+0

выглядит хорошо для меня! –

+0

Я попробовал ваше предложение, и теперь я получаю эту ошибку: –

+0

09: 17: 54710 ОШИБКА ~ Неудачная: изменить таблицу сайта добавить индекс FK2753671A145791 ( siteId), добавить ограничение FK2753671A145791 внешнего ключа (siteId) ссылки пользователя (я d) 09: 17: 54,710 Столбец ERROR ~ BLOB/TEXT 'siteId', используемый в спецификации ключа без длина ключа –

2

я решал такую ​​проблему с помощью «INITIALLY DEFERRED отложенной» в Oracle, это задерживает проверку, пока вы не зафиксируете всю сделку!

Смежные вопросы