从JSON映射子实体时缺少外键/如何生成它们?

时间:2015-06-07 17:50:59

标签: java json jpa mapping entity

我使用JPA将用户链接到许多设备,这些设备可以有许多遥控器,这些设备可以包含许多命令(按钮,如ON / OFF /更改频道/音量等)。

到目前为止,我所有的@OneToMany和@ManyToOne关系都正常工作,并且对我的休息服务进行@GET调用会给我用户以及与该用户对应的所有设备和所有遥控器等。

{
"devices": [{
    "deviceName": "Bedroom",
    "id": 2,
    "remotes": [{
        "commands": [{
            "commandName": "KEY_1",
            "id": 4
        },
        {
            "commandName": "KEY_3",
            "id": 7
        }],
        "id": 6,
        "remoteName": "Samsung TV Remote"
    },
    {
        "commands": [{
            "commandName": "KEY_4",
            "id": 8
        },
        {
            "commandName": "KEY_2",
            "id": 5
        }],
        "id": 3,
        "remoteName": "Samsung TV Remote 2"
    }]
}],
"id": 1,
"userName": "Cris"}

我想要做的是在将JSON similair发布到我的RESTful Web服务时立即创建所有这些。(直接将它们映射到实体而无需手动解析它)

{
"userName": "Cris",
"devices": [{
    "deviceName": "Bedroom",
    "remotes": [{
        "remoteName": "Samsung TV Remote",
        "commands": [{
            "commandName": "KEY_1"
        },
        {
            "commandName": "KEY_2"
        }]
    },
    {
        "remoteName": "Samsung TV Remote 2",
        "commands": [{
            "commandName": "KEY_3"
        },
        {
            "commandName": "KEY_4"
        }]
    }]
}]}

它会创建它们,但所有子实体(设备,遥控器,命令)都没有映射到它们的父项,因此它们的外键没有被填充。

以下是我的实体:

用户

    private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

private String userName;

@OneToMany(mappedBy = "user", fetch=FetchType.LAZY,cascade=CascadeType.PERSIST)
private List<Devices> devices;

设备

private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

private String deviceName;

@XmlTransient
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "USER_ID")
private Users user;

@OneToMany(mappedBy = "device",  fetch = FetchType.LAZY,cascade=CascadeType.PERSIST)
private List<Remotes> remotes;

遥控器

private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

private String remoteName;

@XmlTransient
@ManyToOne( fetch=FetchType.LAZY)
@JoinColumn(name = "DEVICE_ID")
private Devices device;

@OneToMany(mappedBy = "remote", fetch=FetchType.LAZY,cascade=CascadeType.PERSIST)
private List<Commands> commands;

命令

private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

private String commandName;

@XmlTransient
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name = "REMOTE_ID")
private Remotes remote;

POST

@POST
@Override
@Consumes({"application/json"})
public void create(Users entity) {
    super.create(entity);
}

有没有办法在POST JSON后自动将子实体映射到其父实体,还是需要手动将它们映射到彼此?

干杯

1 个答案:

答案 0 :(得分:0)

好的,这花了我一段时间,但实际上这是一个非常简单的修复。

在@POST方法中保留父项时,我所要做的就是在子实体中设置父项。

以下是使用带命令的遥控器添加设备的示例。 我添加了一些try块,因为这些实体中的任何一个实际上都没有Child实体列表。它可能不是防止由这些特定异常引起的崩溃的最干净的解决方案,但它可以满足我的需要。

@POST
@Consumes("application/json")
public void create(Devices device) {
     try {
        for (Remotes r : device.getRemotes()) {
            try {
                for (Commands c : r.getCommands()) {
                    c.setRemote(r);
                }
            } catch (Exception e) {
                System.out.println(r.getRemoteName() + ": commandList -> null");
            }
            r.setDevice(device);
        }
    } catch (Exception e) {
         System.out.println("remoteList -> null");
    }
    em.persist(device);
}