Java JPA保存将嵌入对象转换为代理

Java JPA保存将嵌入对象转换为代理,java,hibernate,jpa,Java,Hibernate,Jpa,我试图用JPA映射一个遗留数据库,因此无法更改数据库结构。我有一个实体表a和一个集合表B,其中外键在表B上。此集合中的对象与TableC具有多通关系。TableB与TableD也有一个one关系,外键也在TableB上。TableD与TableE(TableD具有外键)具有多通关系,最后TableE与tableC(TableE具有外键)具有单通关系 当我在tableA上调用save时,我希望它将所有更改级联到集合TableB,这样我就级联了save操作。这似乎工作正常,但当我向集合添加新的Tab

我试图用JPA映射一个遗留数据库,因此无法更改数据库结构。我有一个实体表a和一个集合表B,其中外键在表B上。此集合中的对象与TableC具有多通关系。TableB与TableD也有一个one关系,外键也在TableB上。TableD与TableE(TableD具有外键)具有多通关系,最后TableE与tableC(TableE具有外键)具有单通关系

当我在tableA上调用save时,我希望它将所有更改级联到集合TableB,这样我就级联了save操作。这似乎工作正常,但当我向集合添加新的TableB实体时,我在TableB实体上设置了一个tableC对象,但在保存后,它变成了代理,但我需要对此进行初始化。我在下面模拟了一个例子

数据库表

CREATE TABLE TABLEA (tableAPk VARCHAR2(10) PRIMARY KEY);
CREATE TABLE TABLEC (ID NUMBER PRIMARY KEY);
CREATE TABLE TABLEE (ID NUMBER PRIMARY KEY, tableEProperty NUMBER,  
CONSTRAINT FK_TABLEC2 FOREIGN KEY (tableEProperty) REFERENCES TABLEC(ID));
CREATE TABLE TABLED (ID NUMBER PRIMARY KEY, tableDProperty NUMBER, 
CONSTRAINT FK_TABLEE FOREIGN KEY (tableDProperty) REFERENCES TABLEE(ID));
CREATE TABLE TABLEB (ID NUMBER PRIMARY KEY, tableBProperty VARCHAR2(10), tableBProperty2 NUMBER, tableBProperty3 NUMBER,
CONSTRAINT FK_TABLEA FOREIGN KEY (tableBProperty) REFERENCES TABLEA (tableAPk), 
CONSTRAINT FK_TABLEC FOREIGN KEY (tableBProperty2) REFERENCES TABLEC (ID),
CONSTRAINT FK_TABLED FOREIGN KEY (tableBProperty3) REFERENCES TABLED (ID));
CREATE SEQUENCE TABLEA_SEQ START WITH 1;
CREATE SEQUENCE TABLEB_SEQ START WITH 1;
CREATE SEQUENCE TABLEC_SEQ START WITH 1;
CREATE SEQUENCE TABLED_SEQ START WITH 1;
CREATE SEQUENCE TABLEE_SEQ START WITH 1;
Java代码:

@Entity
public class TableA {

    @Id
    private String tableAPk;

    @OneToMany(mappedBy="tableBProperty", fetch=FetchType.EAGER, cascade=CascadeType.ALL, orphanRemoval=true) 
    private List<TableB> tableBs = new ArrayList<TableB>();

    public String getTableAPk() {
        return tableAPk;
    }

    public void setTableAPk(String tableAPk) {
        this.tableAPk = tableAPk;
    }

    public List<TableB> getTableBs() {
        return tableBs;
    }

    public void setTableBs(List<TableB> tableBs) {
        this.tableBs = tableBs;
    }

}

@Entity
public class TableB {

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="TABLEB_SEQ")
    @SequenceGenerator(sequenceName = "TABLEB_SEQ", allocationSize = 1, name = "TABLEB_SEQ")
    private Integer id;

    private String tableBProperty;

    @ManyToOne
    @JoinColumn(name = "tableBProperty2")
    private TableC tableC;

    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name="tableBProperty3")
    private TableD tableD;

    public TableB() {} 

    public TableB(String tableBProperty, TableC tableC, TableD tableD) {
        this.tableBProperty = tableBProperty;
        this.tableC = tableC;
        this.tableD = tableD;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTableBProperty() {
        return tableBProperty;
    }

    public void setTableBProperty(String tableBProperty) {
        this.tableBProperty = tableBProperty;
    }

    public TableC getTableC() {
        return tableC;
    }

    public void setTableC(TableC tableC) {
        this.tableC = tableC;
    }

    public TableD getTableD() {
        return tableD;
    }

    public void setTableD(TableD tableD) {
        this.tableD = tableD;
    }

}

@Entity
public class TableC {

    @Id private Integer id;

    @OneToOne(mappedBy="tableC")
    private TableE tableE;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public TableE getTableE() {
        return tableE;
    }

    public void setTableE(TableE tableE) {
        this.tableE = tableE;
    }
}

@Entity
public class TableD {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="TABLED_SEQ")
    @SequenceGenerator(sequenceName = "TABLED_SEQ", allocationSize = 1, name = "TABLED_SEQ")
    private Integer id;

    @ManyToOne(cascade={CascadeType.PERSIST})
    @JoinColumn(name="tableDProperty")
    private TableE tableE;

    public TableD() {}

    public TableD(TableE tableE) {
        this.tableE = tableE;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }


}

@Entity
public class TableE {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="TABLEE_SEQ")
    @SequenceGenerator(sequenceName = "TABLEE_SEQ", allocationSize = 1, name = "TABLEE_SEQ")
    private Integer id;

    @OneToOne(fetch=FetchType.LAZY)
    @JoinColumn(name = "tableEProperty")
    private TableC tableC;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public TableC getTableC() {
        return tableC;
    }

    public void setTableC(TableC tableC) {
        this.tableC = tableC;
    }

}

public interface TableARepository extends JpaRepository<TableA, String>{
}

public interface TableCRepository extends JpaRepository<TableC, Integer> {
}

@RunWith(SpringRunner.class)
@SpringBootTest
public class TableARepositoryTest {

    private static final Integer TEST_ID = -1;
    private static final String TEST_ID_STRING = "TEST1";

    @Autowired protected DataSource ds;
    @Autowired private TableARepository repoA;
    @Autowired private TableCRepository repoC;
    protected JdbcTemplate jdbcTemplate;

    @Before
    public void setUp() throws Exception{
        jdbcTemplate = new JdbcTemplate(ds);
        String insertASql = "insert into TableA (tableAPk) values (?)";
        jdbcTemplate.update(insertASql, new Object[]{TEST_ID_STRING});
        String insertCSql = "insert into TableC (id) values (?)";
        jdbcTemplate.update(insertCSql, new Object[]{TEST_ID});
        String insertESql = "insert into TableE (id, tableEProperty) values (?, ?)";
        jdbcTemplate.update(insertESql, new Object[]{TEST_ID, TEST_ID});
    }

    @After
    public void tearDown() throws Exception{
        String deleteBSql = "delete from TableB where tableBProperty = ?";
        jdbcTemplate.update(deleteBSql, new Object[]{TEST_ID_STRING});
        String deleteDSql = "delete from TableD where tableDProperty = ?";
        jdbcTemplate.update(deleteDSql, new Object[]{TEST_ID});
        String deleteESql = "delete from TableE where ID = ?";
        jdbcTemplate.update(deleteESql, new Object[]{TEST_ID});
        String deleteASql = "delete from TableA where tableAPk = ?";
        jdbcTemplate.update(deleteASql, new Object[]{TEST_ID_STRING});
        String deleteCSql = "delete from TableC where ID = ?";
        jdbcTemplate.update(deleteCSql, new Object[]{TEST_ID});
    }

    @Test
    public void test() {
        TableA tableA = repoA.findById(TEST_ID_STRING).get();
        TableC tableC = repoC.findById(TEST_ID).get();
        tableA.getTableBs().add(new TableB(TEST_ID_STRING, tableC, new TableD(tableC.getTableE())));
        TableA updatedTableA = null;
        try {
            updatedTableA = repoA.save(tableA);
        } catch(Exception e) {
            fail("test:"+e.getMessage());
        }

        assertNotNull(updatedTableA);
        assertTrue(Hibernate.isInitialized(updatedTableA.getTableBs().get(0).getTableC()));
    }
}
@实体
公共类表格{
@身份证
私有字符串表;
@OneToMany(mappedBy=“tableBProperty”,fetch=FetchType.EAGER,cascade=CascadeType.ALL,orphanRemoving=true)
私有列表tableBs=newarraylist();
公共字符串getTableAPk(){
返回表APK;
}
公共void setTableAPk(字符串tableAPk){
this.tableAPk=tableAPk;
}
公共列表getTableBs(){
返回表格;
}
公共无效设置表(列表表){
这个.tableBs=tableBs;
}
}
@实体
公共类表格B{
@身份证
@GeneratedValue(策略=GenerationType.SEQUENCE,generator=“TABLEB_SEQ”)
@SequenceGenerator(sequenceName=“TABLEB_-SEQ”,allocationSize=1,name=“TABLEB_-SEQ”)
私有整数id;
私有字符串表属性;
@许多酮
@JoinColumn(name=“tableBProperty2”)
私人表格;
@OneTONE(级联=级联类型.ALL,孤立删除=真)
@JoinColumn(name=“tableBProperty3”)
私人会议;
公共表B(){}
公共表格B(字符串表格属性,表格C表格C,表格D){
this.tableBProperty=tableBProperty;
此表c=表c;
this.tableD=tableD;
}
公共整数getId(){
返回id;
}
公共无效集合id(整数id){
this.id=id;
}
公共字符串getTableBProperty(){
返回表属性;
}
公共void setTableBProperty(字符串tableBProperty){
this.tableBProperty=tableBProperty;
}
公共表getTableC(){
返回表c;
}
公共空间设置表C(表C表C){
此表c=表c;
}
公共表格getTableD(){
返回表;
}
已设置公共无效(已提交){
this.tableD=tableD;
}
}
@实体
公共类表格C{
@Id私有整数Id;
@OneTONE(mappedBy=“表C”)
私人表格;
公共整数getId(){
返回id;
}
公共无效集合id(整数id){
this.id=id;
}
公共表格gettable(){
返回表;
}
公共无效设置表(TableE TableE){
this.table=table;
}
}
@实体
公开课提交会议省览{
@身份证
@GeneratedValue(策略=GenerationType.SEQUENCE,generator=“TABLED_SEQ”)
@SequenceGenerator(sequenceName=“TABLED_-SEQ”,allocationSize=1,name=“TABLED_-SEQ”)
私有整数id;
@manytone(cascade={CascadeType.PERSIST})
@JoinColumn(name=“tableDProperty”)
私人表格;
公共表(){}
公众席{
this.table=table;
}
公共整数getId(){
返回id;
}
公共无效集合id(整数id){
this.id=id;
}
}
@实体
公共类表格{
@身份证
@GeneratedValue(策略=GenerationType.SEQUENCE,generator=“TABLEE_SEQ”)
@SequenceGenerator(sequenceName=“TABLEE_-SEQ”,allocationSize=1,name=“TABLEE_-SEQ”)
私有整数id;
@OneToOne(fetch=FetchType.LAZY)
@JoinColumn(name=“TableProperty”)
私人表格;
公共整数getId(){
返回id;
}
公共无效集合id(整数id){
this.id=id;
}
公共表getTableC(){
返回表c;
}
公共空间设置表C(表C表C){
此表c=表c;
}
}
公共接口表position扩展了JPA position{
}
公共接口表position扩展了JPareposition{
}
@RunWith(SpringRunner.class)
@春靴测试
公共类表阳性测试{
私有静态最终整数测试_ID=-1;
私有静态最终字符串测试\u ID\u String=“TEST1”;
@自动连线保护数据源ds;
@自动连接的专用表存储报告;
@自动连线私人桌面存储;
受保护的JdbcTemplate JdbcTemplate;
@以前
public void setUp()引发异常{
jdbcTemplate=新的jdbcTemplate(ds);
String insertASql=“插入到表A(tableAPk)值(?);
update(insertASql,新对象[]{TEST\u ID\u STRING});
字符串insertCSql=“插入到表C(id)值(?);
update(insertCSql,新对象[]{TEST_ID});
String insertESql=“插入表格(id,TableProperty)值(?,)”;
update(insertESql,新对象[]{TEST\u ID,TEST\u ID});
}
@之后
public void tearDown()引发异常{
String deleteBSql=“从TableB中删除,其中tableBProperty=?”;
update(deleteBSql,新对象[]{TEST\u ID\u STRING});
String deleteDSql=“从TableD中删除,其中tableDProperty=?”;
update(deleteDSql,新对象[]{TEST_ID});
String deleteESql=“从表中删除,其中ID=?”;
update(deleteESql,新对象[]{TEST_ID});
String deleteASql=“从TableA中删除,其中tableAPk=?”;
update(deleteASql,新对象[]{TEST\u ID\u STRING});
String deleteCSql=“从表C中删除,其中ID=?”;
J
public static <T> T unproxy(T entity){
   Hibernate.initialize(entity)
   if(entity instanceof HibernateProxy){
       entity = (T)((HibernateProxy)entity).getHibernateLazyInitializer().getImplementation();
   } else {
       entity = (T)entity
   }
   return entity;
}