Java 更新包含对象字段的实体

Java 更新包含对象字段的实体,java,hibernate,jpa,Java,Hibernate,Jpa,我正在尝试更新包含其他类类型字段的实体 这就是我的实体: @Entity public class Owner { @Id @GeneratedValue private int id; @Column(name = "first_name") @NotNull(message="{NotNull}") @Size(min=2,max=15,message="{Size}") private String firstName;

我正在尝试更新包含其他类类型字段的实体

这就是我的实体:

@Entity
public class Owner {

    @Id
    @GeneratedValue
    private int id;

    @Column(name = "first_name")
    @NotNull(message="{NotNull}")
    @Size(min=2,max=15,message="{Size}")
    private String firstName;

    @NotNull(message="{NotNull}")
    @Size(min=2,max=15,message="{Size}")
    @Column(name = "last_name")
    private String lastName;

    @Valid
    @OneToOne(cascade = CascadeType.ALL)
    private Phone phone;

    @Valid
    @OneToOne(cascade = CascadeType.ALL)
    private Pet pet;
从这个观点来看:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>

<meta charset="ISO-8859-1"></meta>

<title>Owner details</title>
</head>
<body>
    <div id="owner">
        <form th:action="@{|/ownerList/${owner.id}.do|}"
            th:object="${owner}" method="post">
            <table>
                <tr>
                    <td>Id:</td>
                    <td><input type="text" th:field="*{id}" /></td>
                    <td th:if="${#fields.hasErrors('id')}" th:errors="*{id}">fieldError</td>
                </tr>
                <tr>
                    <td>First name</td>
                    <td><input type="text" th:field="*{firstName}" /></td>
                    <td th:if="${#fields.hasErrors('firstName')}"
                        th:errors="*{firstName}">fieldError</td>
                </tr>
                <tr>
                    <td>Last name</td>
                    <td><input type="text" th:field="*{lastName}" /></td>
                    <td th:if="${#fields.hasErrors('lastName')}"
                        th:errors="*{lastName}">fieldError</td>
                </tr>
                <tr>
                    <td>Phone</td>
                    <td><input type="text" th:field="*{phone.number}" /></td>
                    <td th:if="${#fields.hasErrors('phone.number')}"
                        th:errors="*{phones[0].number}">fieldError</td>
                </tr>
                <tr>
                    <td>Pet</td>
                    <td><input type="text" th:field="*{pet.petName}" /></td>
                    <td th:if="${#fields.hasErrors('pet.petName')}"
                        th:errors="*{pet.petName}">fieldError</td>
                </tr>
                <tr>
                    <td><input type="submit" value="update" name="action" /></td>
                    <td><input type="submit" value="delete" name="action" /></td>
                </tr>
            </table>
        </form>
        <a href="/ownerList">Back</a>
    </div>
</body>
</html>
所以我试图更新Owner的对象,但在.merge之后的数据库中,我可以找到新的实体,例如Phone,具有新Id

因此,举例来说,我有: 所有者: 名字:XYZ 姓氏:BBB 宠物:鲍勃 电话:1234

当我尝试更新手机时,比如说“2222”,然后在DB中我可以找到两条记录
一个是“1234”,第二个是“2222”,我想用“2222”替换旧的“1234”。

发生这种情况是因为您正在使用电话号码作为您的
电话实体的
@Id
。并且您不能更改实体的ID:您可以使用不同的ID创建一个新实体,或者
findById(number)
现有实体并更新其他字段的值(但不能更改
@ID
字段,因为这将再次创建一个新实体)

如果电话号码(“1234”或“2222”)是您所需要的全部,那么开始使用
phone
类是没有意义的。您只需使用
字符串
(如果您希望能够使用+XX XXX…格式或验证电话号码长度),甚至可以使用
整数


如果您确实需要
Phone
类,因为它有其他字段(如
Phone.totalCallsMade
或类似字段),那么您的程序将按预期工作:不同的号码、不同的实体。

如果您想在没有任何所有者引用的情况下删除手机,则需要添加@orniremove

当目标实体处于一对一或 一对多关系从关系中移除,通常是 希望将删除操作级联到目标实体。这样的 目标实体被视为“孤立实体”,孤立实体被删除 属性可用于指定应删除孤立实体 远离的。例如,如果订单有多个行项目,其中一个 如果从订单中删除,则删除的行项目将被视为 孤儿。如果将删除设置为true,则行项目实体将为 从订单中删除行项目时删除

@OneToMany和@oneToOne中的孤儿移除属性采用 布尔值,默认情况下为false

以下示例将删除操作级联到 从关系中删除孤立客户实体时:

@OneToMany(mappedBy=“customer”,orphan=“true”)公共 列出getOrders(){…}

如果你这样做:

owner.set(new Phone(2222));
entityManager.merge(owner));
// update the owner phone
owner.set(new Phone(77777));
//the phone(2222) will be deleted
entityManager.merge(owner));

在您的控制器中,更新方法不知道必须为特定的所有者Id更新哪个电话号码。在更新您的电话号码之后,从Jsp将所有者Id值作为隐藏值传递,并将具有特定所有者Id的电话号码作为隐藏值传递给Jsp,以获取控制器中的值。
@Entity
public class Owner {

    @Id
    @GeneratedValue
    private int id;

    @Column(name = "first_name")
    @NotNull(message="{NotNull}")
    @Size(min=2,max=15,message="{Size}")
    private String firstName;

    @NotNull(message="{NotNull}")
    @Size(min=2,max=15,message="{Size}")
    @Column(name = "last_name")
    private String lastName;

    @Valid
    @OneToOne(cascade = CascadeType.ALL, orphanRemoval="true")
    private Phone phone;

    @Valid
    @OneToOne(cascade = CascadeType.ALL, orphanRemoval="true")
    private Pet pet;
owner.set(new Phone(2222));
entityManager.merge(owner));
// update the owner phone
owner.set(new Phone(77777));
//the phone(2222) will be deleted
entityManager.merge(owner));