JPA |使用eager fetch进行一对一映射

时间:2015-01-01 07:36:46

标签: spring hibernate jpa orm spring-data-jpa

我正在使用带有hibernate作为JPA提供程序的JPA示例应用程序。 我在其中使用获取类型EAGER进行一对一映射。

以下是我的代码块:

Person.java

public class Person extends Persistent  implements Serializable {

private static final long serialVersionUID = 1L;

String name;

// address as composition
Address address;

String addressId;

Address.java

public class Address extends Persistent implements Serializable {


private static final long serialVersionUID = 1L;


String address;

mapping.xml

<entity name="Person" class="com.csam.mtp.wallet.wallet.Person"
    access="FIELD">
    <table name="person" />
    <attributes>

        <basic name="name">
            <column name="name" length="36" nullable="false" />
        </basic>

        <basic name="addressid">
            <column name="addressid" length="36"/>
        </basic>

        <one-to-one name="address" fetch="EAGER">
            <join-column name="addressid"
                referenced-column-name="id" insertable="false" updatable="false"
                nullable="false" />
        </one-to-one>

    </attributes>
</entity>
<entity name="address" class="com.csam.mtp.wallet.wallet.Address"
    access="FIELD">
    <table name="address" />
    <attributes>
        <basic name="address">
            <column name="address" length="36" />
        </basic>
    </attributes>
</entity>

数据库脚本

CREATE TABLE address (
id VARCHAR (50) not null,
address VARCHAR(50),
primary key(id)

);

CREATE TABLE person (
id VARCHAR (50) not null,
name VARCHAR(50),
addressid VARCHAR(50),
primary key(id),
foreign key (addressid) REFERENCES address(id),

);

驱动程序类

Address address = new Address();
    address.setAddress("test");
    address = addressRepository.save(address);

    Person person = new Person("Mike");

    //person.setAddressId(address.id());

    try {
        person = personRepository.save(person);
    } catch (Exception e) {
        e.printStackTrace();
    }

    System.out.println(personRepository.exists(person.getID()));
    Person savedPerson = personRepository.findOne(person.getID());
    // Asserts
    assertNotNull(savedPerson);
    assertNotNull(savedPerson.id());

保存人员如果我没有设置地址ID,那么它会成功保存人员,exists返回true但是找到一个api总是返回null

在保存人员的同时,首先我保存地址并亲自设置地址ID并保存 它成功保存人,存在返回true并找到一个api返回带有地址对象的Person对象(因为它很渴望)

所以下面是我的查询,

如果在子节点上使用eager fetch进行一对一映射,则必须保存子节点并在保存父节点之前设置为父节点吗?

我试图找出相关的arcticle但不能得到一个,请协助。

提前致谢

2 个答案:

答案 0 :(得分:1)

在您的情况下,地址是父亲,而人是儿童。这是因为Child通过addressId FK指向了Parent。

因为您没有双向关联,所以您不应该insertable="false" updatable="false"

通过这些设置,Hibernate无法在INSERT或UPDATE查询中包含addressId

  1. 删除insertable="false" updatable="false"
  2. 也删除addressId列,因为您可以通过address.id
  3. 引用它
  4. 从人员到地址添加级联:

    <one-to-one name="address" fetch="EAGER">
        <join-column name="addressid"
            referenced-column-name="id" nullable="false" />
        <cascade>
            <cascade-persist/>
            <cascade-merge/>
        </cascade>
    </one-to-one>       
    
  5. 可能最好有一个双向关联,这样一个地址也有一个人的引用,在这种情况下你应该有一对多的关联,因为一个地址可能有多个人。

答案 1 :(得分:0)

最后得到了nullable = true的解决方案,如下所示:

<one-to-one name="address" fetch="EAGER">
        <join-column name="addressid"
            referenced-column-name="id" insertable="false" updatable="false"
            nullable="true" />
</one-to-one>