4

Playを使う!フレームワーク、私は次の2つのモデルを持っています:

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

ログ出力:

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

エラーの意味と私が間違っていることを誰かが理解するのを手伝ってもらえますか?

4

2 に答える 2

6

ここでの問題は、SiteモデルクラスとUserモデルクラスの間のマッピングです。与えられたエラーは、外部キーがありません。

Userクラスのサイトリストをコメントアウトすると、テストに合格します。これで問題が絞り込まれました。

アップデート:

問題は、Siteオブジェクトを保存すると、最初に子オブジェクト(Userオブジェクトを含む)が保存されるためです。これが発生すると、(mappedByパラメーターのために)Siteオブジェクトへの参照を作成しようとしますが、これはまだ保存されていません(これは、Userオブジェクトが保存された後に行われます)。

したがって、別の方法として、アクセスできる値(siteIdなど)でマップするか、保存後にユーザーをサイトに追加します(ID値が生成されます)。

コードをに変更しましたがmappedBy="siteId"、テストは正常に実行されました。

于 2010-12-12T10:14:07.950 に答える
2

Oracleで「INITIALLYDEFEREDDEFERRABLE」を使用してこのような問題を解決しました。これにより、トランザクション全体をコミットするまでチェックが遅延します。

于 2013-01-06T07:24:58.777 に答える