【问题标题】:Hibernate, Saving new entity without fetching associated entities休眠,保存新实体而不获取关联实体
【发布时间】:2016-12-27 02:09:32
【问题描述】:

我正在使用 spring boot 和 hibernate,试图通过仅发布引用实体的 id 来保存具有 @ManyToOne 关系的实体

@Entity
@Table(name = "foo_table")
public class Foo implements Serializable {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private id;

    @NotNull
    @JsonIdentityReference(alwaysAsId=true)
    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "bar_id", nullable = false)
    private Bar bar;

    ...
}


@Entity
@Table(name = "bar_table")
public class Bar implements Serializable {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private id;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "bar")
    private Set<Foo> foos;

    ...
}

和控制器代码类似:

@RestController
public class FooController {

    @Autowired
    private FooRepo fooRepo;

    @RequestMapping(value = "/foo", method= RequestMethod.POST)
    public Foo foo(@RequestBody @Valid Foo foo)
        throws Exception {
        return fooRepo.save(foo);
    }
}

并且发布的 JSON 类似于

{
    "bar" : 1
}

但是我在反序列化时在 jackson 中遇到错误

"Could not read document: Unresolved forward references for: Object id [1]"

【问题讨论】:

    标签: java hibernate spring-boot jackson


    【解决方案1】:

    您可以更改 json,以便为 Jackson 期望的 bar 字段提供对象类型,而不是整数,并明确传递 id

    {
        "bar": {
            "id": 1
        }
    }
    

    在您的 Foo 类中创建相应的设置器 - 一个与 ID 类型具有相同输入类型的设置器 - 在您的情况下是一个整数:

    public class Foo implements Serializable {
        ...
    
        @JsonProperty("bar")
        public void setBar(int id) {
            // For example:
            this.bar = new Bar(id);
        }
    }
    

    【讨论】:

    • 虽然这有效(在添加 @JsonProperty(access = Access.WRITE_ONLY) 之后),但是,我正在尝试使用 @JsonIdentityReference(alwaysAsId=true) 以相同的方式实现序列化和反序列化 Bar /跨度>
    • 即如果它在响应中表示为 { bar : 1 },我也需要将其发送为 {bar : 1}。
    • @BadrGhatasheh 对不起,我没有从问题中得到它 - 提供的类没有你说你使用的那些注释。更新了我的答案。
    • 但这不起作用,因为“new Bar()”没有附加到实体管理器并且将无法插入
    • @BadrGhatasheh 是的,这个问题是指反序列化错误。但如何处理数据的完整性取决于您。您可以通过调用 dao.getBarById(id) 从数据库加载实体,之后您将拥有一个托管实例。实际上,在序列化/反序列化步骤中弄乱事务并不是一个好主意 - 通常您创建仅用于 Web 层的附加类 FooDto 和 BarDto,然后在控制器内手动将它们转换为您的实体,确保所有字段的方式您需要 - 加载哪些字段,忽略哪些字段。
    猜你喜欢
    • 2017-08-28
    • 2012-09-09
    • 1970-01-01
    • 1970-01-01
    • 2015-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多