Java JPA保存将嵌入对象转换为代理
我试图用JPA映射一个遗留数据库,因此无法更改数据库结构。我有一个实体表a和一个集合表B,其中外键在表B上。此集合中的对象与TableC具有多通关系。TableB与TableD也有一个one关系,外键也在TableB上。TableD与TableE(TableD具有外键)具有多通关系,最后TableE与tableC(TableE具有外键)具有单通关系 当我在tableA上调用save时,我希望它将所有更改级联到集合TableB,这样我就级联了save操作。这似乎工作正常,但当我向集合添加新的TableB实体时,我在TableB实体上设置了一个tableC对象,但在保存后,它变成了代理,但我需要对此进行初始化。我在下面模拟了一个例子 数据库表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
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;
}