Hibernate一对一映射不更新子表

时间:2013-02-14 15:17:21

标签: java spring hibernate postgresql rest

我有一对一的映射关联类。

@Entity
    public class EmployeeEntity
    {
      @Id
      private String id;

      private String name;


      @OneToOne(mappedBy = "employeeEntity", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
      @Fetch(FetchMode.SELECT)
      @JoinColumn(name = "empid")
      private AddressEntity addressEntity;
        ...
        ...
        getters & setters
    }


@Entity
public class AddressEntity
{
    @Id
    @Column(unique=true, nullable=false)
    @GeneratedValue(generator="gen")
    @GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property", value="employeeEntity"))
    private String empId;

    @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @PrimaryKeyJoinColumn
    private EmployeeEntity employeeEntity;
    ...
    getters & setters
}

我正在使用postgres并在addressentity表上使用以下foriegn键约束的表(employeeentity,addressentity): 外键约束:     “fkakhilesh”FOREIGN KEY(empid)REFERENCES employeeentity(id)ON DELETE CASCADE

我对不同的REST调用有以下要求:

  1. POST休息电话 - 应该创建一个有地址的员工。
  2. POST休息电话 - 应该创建一个没有地址的员工。
  3. GET休息电话 - 应该检索一名员工。如果存在,地址也应该出现。
  4. PUT休息电话 - 应更新员工和地址(如果地址存在)。
  5. PUT休息电话 - 应该更新员工和地址(当地址通过并且已经存在于empid的addressentity表中)
  6. PUT休息电话 - 应该更新员工并创建地址(当地址通过时,它在empres的addressentity表中不存在)
  7. 我可以毫无问题地执行操作1到5。

    主要问题在于6,我想到了以下问题: 1.当我执行“getSession()。update(object)”时,我得到了hibernate的StaleStateException:批量更新从update [0]返回了意外的行数;实际行数:0;预期:1。  如果地址不存在,“更新”是不可能的?我不能在更新期间创建新地址吗?

    1. 我是否需要将我的ServiceImpl调用更改为“getSession()。merge(object)?这种情况只能通过调用”merge“来处理吗?它如何影响性能?

    2. 如果我合并,我会得到hibernate的IdentifierGenerationException:尝试从null一对一属性中分配id。 我错过了什么吗?

    3. 这可以通过改变hibernate映射来解决吗?或者与cascade相关的事情。

    4. 这里@GeneratedValue(generator =“gen”)的重要性是什么?为什么@parameter在@GenericGenerator中使用

    5. 我是hibernate的新手,并试图深入了解hibernate映射。 此外,如果您能在设计上建议我应该是处理此问题的最佳方法,我会很高兴。

2 个答案:

答案 0 :(得分:3)

我得到了解决方案。这个一对一的映射有点棘手,并不像我最初想的那么简单。 我使用了双向一对一映射,因此在更新期间调用EmployeeEntity和AddressEntity的setter来设置彼此非常重要。例如:

必须明确调用

employeeEntity.setAddressEntity(addressEntity)和addressEntity.setEmpoyeeEntity(empoyeeEntity)。

单独设置employeeEntity.setAddressEntity(addressEntity)将无效。

答案 1 :(得分:0)

  • 始终使用整数ID并使用.getSession.saveOrUpdate(entity);进行保存或更新。

  • 在一对一映射中,您应该在孩子身上提到constrained=true。它使Child Id与Parent Id相同。

  • 将这些行用于子ID。我不知道Java属性语法。

<generator class="foreign">
    <param name="property">employeeEntity</param>
</generator>
  • 同时从子项中删除抓取类型和Cascade.All。我认为默认的提取模式是Select,这很好。 Cascade通常用于负责父子关系的Parent部分。