使用Hibernate和三个表发生java.lang.StackOverflowError

时间:2014-03-14 13:49:25

标签: java mysql json spring hibernate

我正在构建一个应用程序,该应用程序要求设备可以向Web服务发送请求,询问它是否可以运行Jasmine单元测试。这个位有效。什么行不通,如果我要求Hibernate检索完整的数据列表,我得到一个StackOverFlowError。

我已经包含了这三个实体。

@Entity
@Table(name = "device")
    public class Device {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "device_id")
    private Integer id;

    @Column(name = "device_name")
    private String deviceName;

    @OneToMany(mappedBy = "device", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private Set<Test> tests;

}

@Entity
@Table(name = "test")
public class Test {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "test_id")
    private Integer id;

    @Column(name = "test_name")
    private String testName;

    @OneToMany(mappedBy = "test", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private Set<Test_Case> testcases;

    @ManyToOne
    @JoinColumn(name = "device_id")
    private Device device;

}

@Entity
@Table(name = "test_case")
public class Test_Case {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Integer id;

    @Column(name = "test_case_id")
    private String testCaseId;

    @Column(name = "can_run")
    private String canRun;

    @ManyToOne
    @JoinColumn(name = "test_id")
    private Test test;
}

重申一下。设备包含一组测试,测试类似于条形码,扫描仪等,每个测试包含一组测试用例。测试用例是条形码等的单独测试。数据库的模式如下所示。

CREATE TABLE device (
    device_id int(11) NOT NULL AUTO_INCREMENT,
    device_name varchar(100) DEFAULT NULL,
    PRIMARY KEY(device_id)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

CREATE TABLE test(
    test_id int(11) NOT NULL AUTO_INCREMENT,
    test_name varchar(100) DEFAULT NULL,
    device_id int(11) NOT NULL,
    PRIMARY KEY(test_id),
    INDEX FK_DEVC (device_id),
    CONSTRAINT FK_DEVC FOREIGN KEY (device_id) REFERENCES device (device_id)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

CREATE TABLE test_case (
    id int(11) NOT NULL AUTO_INCREMENT,
    test_case_id varchar(100) DEFAULT NULL,
    can_run varchar(1) DEFAULT NULL,
    test_id int(11) NOT NULL,
    PRIMARY KEY(id),
    INDEX FK_TEST (test_id),
    CONSTRAINT FK_TEST FOREIGN KEY (test_id) REFERENCES test (test_id)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;

当我要求Hibernate检索所有内容时,我会生成以下查询。

Hibernate: select device0_.device_id as device_i1_0_, device0_.device_name as device_n2_0_ from device device0_

Hibernate: select tests0_.device_id as device_i3_0_1_, tests0_.test_id as test_id1_2_1_, tests0_.test_id as test_id1_2_0_, tests0_.device_id as device_i3_2_0_, tests0_.test_name as test_nam2_2_0_ from test tests0_ where tests0_.device_id=?

Hibernate: select testcases0_.test_id as test_id4_2_1_, testcases0_.id as id1_3_1_, testcases0_.id as id1_3_0_, testcases0_.can_run as can_run2_3_0_,testcases0_.test_id as test_id4_3_0_, testcases0_.test_case_id as test_cas3_3_0_ from test_case testcases0_ where testcases0_.test_id=?

这会在生成结果时导致StackOverflow,并且在查看代码几天并遵循其他答案的建议后,我无法让它停止产生该错误。

调用由Spring MVC Restful接口生成,该接口使用Jackson将响应体发送回来将输出转换为JSON。

有什么明显的我在这里做错了吗?对于那些感兴趣的人,我使用的是Spring 3.2.7,Hibernate 4.2.8和MySQL 5.something。

1 个答案:

答案 0 :(得分:1)

杰克逊的序列化正在圈中。序列化Test Jackson时,还会序列化Test_Case对象。但是要序列化Test_Case,Jackson也会尝试序列化Test对象。

您可以将@JsonIgnore注释添加到Test_Case中的成员测试中以打破此圈。

Test类中的成员设备也需要@JsonIgnore注释。