Persist Tables with parent-child relation between two different schema in Spring Data JPA












1














I am trying to do,



ChildTable child = new ChildTable();
clild.setParentTwoID(prentTwoID);
ParentOne parentOne = new ParentOne();
parentOne.getChildTableList().add(childTable);
parentReposetory.save(parentOne);


Where, ParentOne is in schema S1 and ParentTwo along with ChildTable in schema S2.



ParentOne.java



@Data
@EqualsAndHashCode(callSuper = false)
@Entity
@Table(name = "ParentOne", schema = "S1")
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, scope = ParentOne.class)
public class ParentOne implements Serializable {

private static final long serialVersionUID = 7502273069461829133L;

@Id
@Column(name = "ParentOneID", unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer parentOneID;

@OneToMany(targetEntity = ChildTable.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "ParentOneID", nullable = false, insertable = false, updatable = false)
private List<ChildTable> childTableList;
}


ParentTwo.java



@Data
@EqualsAndHashCode(callSuper = false)
@Entity
@Table(name = "ParentTwo", schema = "S2")
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, scope = ParentTwo.class)
public class ParentTwo implements Serializable {

private static final long serialVersionUID = 7502273069461829133L;

@Id
@Column(name = "ParentTwoID", unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer parentTwoID;

@OneToMany(targetEntity = ChildTable.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "ParentTwoID", nullable = false, insertable = false, updatable = false)
private List<ChildTable> childTableList;
}


ChildTable.java



@Data
@EqualsAndHashCode(callSuper = false)
@Entity
@Table(name = "ChildTable", schema = "S2")
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, scope = ChildTable.class)
public class ChildTable implements Serializable {

private static final long serialVersionUID = -6331600489988183852L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ChildTableID", unique = true, nullable = false)
private Integer childTableID;

@Column(name = "ParentOneID")
private Integer parentOneID;

@Column(name = "ParentTwoID", nullable = false)
@NotNull(message = "mandatory_field")
private Integer parentTwoID;

}


Here ParentTwo is already persisted and I have the Id of it. I am Going to Persist only ParentOne along with the ChildTable of different Schema. While I do this I get error saying that.




rg.springframework.dao.DataIntegrityViolationException: could not
execute statement; SQL [n/a]; constraint [null]; nested exception is
org.hibernate.exception.ConstraintViolationException: could not
execute statement



Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Cannot
insert the value NULL into column 'ParentOneID', table
'PT_Sample.S2.ChildTable'; column does not allow nulls. INSERT fails.



SQL Error: 515, SQLState: 23000











share|improve this question






















  • The error says that the column ChildTable.ParentOneID has a NOT NULL constraint on it and that an INSERT is being issued with a null value for that column. Since you are not setting the value of that column in your code anywhere, the error is expected. What exactly is the question?
    – manish
    May 1 '17 at 10:40










  • @manish As JPA will insert ParentOne table which will create a parentOneID and then Insert ChildTable with that generated parentOneID. But here for me its not happening.
    – Sathish Kumar k k
    May 1 '17 at 10:55
















1














I am trying to do,



ChildTable child = new ChildTable();
clild.setParentTwoID(prentTwoID);
ParentOne parentOne = new ParentOne();
parentOne.getChildTableList().add(childTable);
parentReposetory.save(parentOne);


Where, ParentOne is in schema S1 and ParentTwo along with ChildTable in schema S2.



ParentOne.java



@Data
@EqualsAndHashCode(callSuper = false)
@Entity
@Table(name = "ParentOne", schema = "S1")
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, scope = ParentOne.class)
public class ParentOne implements Serializable {

private static final long serialVersionUID = 7502273069461829133L;

@Id
@Column(name = "ParentOneID", unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer parentOneID;

@OneToMany(targetEntity = ChildTable.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "ParentOneID", nullable = false, insertable = false, updatable = false)
private List<ChildTable> childTableList;
}


ParentTwo.java



@Data
@EqualsAndHashCode(callSuper = false)
@Entity
@Table(name = "ParentTwo", schema = "S2")
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, scope = ParentTwo.class)
public class ParentTwo implements Serializable {

private static final long serialVersionUID = 7502273069461829133L;

@Id
@Column(name = "ParentTwoID", unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer parentTwoID;

@OneToMany(targetEntity = ChildTable.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "ParentTwoID", nullable = false, insertable = false, updatable = false)
private List<ChildTable> childTableList;
}


ChildTable.java



@Data
@EqualsAndHashCode(callSuper = false)
@Entity
@Table(name = "ChildTable", schema = "S2")
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, scope = ChildTable.class)
public class ChildTable implements Serializable {

private static final long serialVersionUID = -6331600489988183852L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ChildTableID", unique = true, nullable = false)
private Integer childTableID;

@Column(name = "ParentOneID")
private Integer parentOneID;

@Column(name = "ParentTwoID", nullable = false)
@NotNull(message = "mandatory_field")
private Integer parentTwoID;

}


Here ParentTwo is already persisted and I have the Id of it. I am Going to Persist only ParentOne along with the ChildTable of different Schema. While I do this I get error saying that.




rg.springframework.dao.DataIntegrityViolationException: could not
execute statement; SQL [n/a]; constraint [null]; nested exception is
org.hibernate.exception.ConstraintViolationException: could not
execute statement



Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Cannot
insert the value NULL into column 'ParentOneID', table
'PT_Sample.S2.ChildTable'; column does not allow nulls. INSERT fails.



SQL Error: 515, SQLState: 23000











share|improve this question






















  • The error says that the column ChildTable.ParentOneID has a NOT NULL constraint on it and that an INSERT is being issued with a null value for that column. Since you are not setting the value of that column in your code anywhere, the error is expected. What exactly is the question?
    – manish
    May 1 '17 at 10:40










  • @manish As JPA will insert ParentOne table which will create a parentOneID and then Insert ChildTable with that generated parentOneID. But here for me its not happening.
    – Sathish Kumar k k
    May 1 '17 at 10:55














1












1








1


1





I am trying to do,



ChildTable child = new ChildTable();
clild.setParentTwoID(prentTwoID);
ParentOne parentOne = new ParentOne();
parentOne.getChildTableList().add(childTable);
parentReposetory.save(parentOne);


Where, ParentOne is in schema S1 and ParentTwo along with ChildTable in schema S2.



ParentOne.java



@Data
@EqualsAndHashCode(callSuper = false)
@Entity
@Table(name = "ParentOne", schema = "S1")
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, scope = ParentOne.class)
public class ParentOne implements Serializable {

private static final long serialVersionUID = 7502273069461829133L;

@Id
@Column(name = "ParentOneID", unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer parentOneID;

@OneToMany(targetEntity = ChildTable.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "ParentOneID", nullable = false, insertable = false, updatable = false)
private List<ChildTable> childTableList;
}


ParentTwo.java



@Data
@EqualsAndHashCode(callSuper = false)
@Entity
@Table(name = "ParentTwo", schema = "S2")
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, scope = ParentTwo.class)
public class ParentTwo implements Serializable {

private static final long serialVersionUID = 7502273069461829133L;

@Id
@Column(name = "ParentTwoID", unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer parentTwoID;

@OneToMany(targetEntity = ChildTable.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "ParentTwoID", nullable = false, insertable = false, updatable = false)
private List<ChildTable> childTableList;
}


ChildTable.java



@Data
@EqualsAndHashCode(callSuper = false)
@Entity
@Table(name = "ChildTable", schema = "S2")
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, scope = ChildTable.class)
public class ChildTable implements Serializable {

private static final long serialVersionUID = -6331600489988183852L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ChildTableID", unique = true, nullable = false)
private Integer childTableID;

@Column(name = "ParentOneID")
private Integer parentOneID;

@Column(name = "ParentTwoID", nullable = false)
@NotNull(message = "mandatory_field")
private Integer parentTwoID;

}


Here ParentTwo is already persisted and I have the Id of it. I am Going to Persist only ParentOne along with the ChildTable of different Schema. While I do this I get error saying that.




rg.springframework.dao.DataIntegrityViolationException: could not
execute statement; SQL [n/a]; constraint [null]; nested exception is
org.hibernate.exception.ConstraintViolationException: could not
execute statement



Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Cannot
insert the value NULL into column 'ParentOneID', table
'PT_Sample.S2.ChildTable'; column does not allow nulls. INSERT fails.



SQL Error: 515, SQLState: 23000











share|improve this question













I am trying to do,



ChildTable child = new ChildTable();
clild.setParentTwoID(prentTwoID);
ParentOne parentOne = new ParentOne();
parentOne.getChildTableList().add(childTable);
parentReposetory.save(parentOne);


Where, ParentOne is in schema S1 and ParentTwo along with ChildTable in schema S2.



ParentOne.java



@Data
@EqualsAndHashCode(callSuper = false)
@Entity
@Table(name = "ParentOne", schema = "S1")
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, scope = ParentOne.class)
public class ParentOne implements Serializable {

private static final long serialVersionUID = 7502273069461829133L;

@Id
@Column(name = "ParentOneID", unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer parentOneID;

@OneToMany(targetEntity = ChildTable.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "ParentOneID", nullable = false, insertable = false, updatable = false)
private List<ChildTable> childTableList;
}


ParentTwo.java



@Data
@EqualsAndHashCode(callSuper = false)
@Entity
@Table(name = "ParentTwo", schema = "S2")
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, scope = ParentTwo.class)
public class ParentTwo implements Serializable {

private static final long serialVersionUID = 7502273069461829133L;

@Id
@Column(name = "ParentTwoID", unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer parentTwoID;

@OneToMany(targetEntity = ChildTable.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "ParentTwoID", nullable = false, insertable = false, updatable = false)
private List<ChildTable> childTableList;
}


ChildTable.java



@Data
@EqualsAndHashCode(callSuper = false)
@Entity
@Table(name = "ChildTable", schema = "S2")
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, scope = ChildTable.class)
public class ChildTable implements Serializable {

private static final long serialVersionUID = -6331600489988183852L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ChildTableID", unique = true, nullable = false)
private Integer childTableID;

@Column(name = "ParentOneID")
private Integer parentOneID;

@Column(name = "ParentTwoID", nullable = false)
@NotNull(message = "mandatory_field")
private Integer parentTwoID;

}


Here ParentTwo is already persisted and I have the Id of it. I am Going to Persist only ParentOne along with the ChildTable of different Schema. While I do this I get error saying that.




rg.springframework.dao.DataIntegrityViolationException: could not
execute statement; SQL [n/a]; constraint [null]; nested exception is
org.hibernate.exception.ConstraintViolationException: could not
execute statement



Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Cannot
insert the value NULL into column 'ParentOneID', table
'PT_Sample.S2.ChildTable'; column does not allow nulls. INSERT fails.



SQL Error: 515, SQLState: 23000








java sql-server hibernate spring-data-jpa jpa-2.0






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked May 1 '17 at 9:21









Sathish Kumar k k

69341438




69341438












  • The error says that the column ChildTable.ParentOneID has a NOT NULL constraint on it and that an INSERT is being issued with a null value for that column. Since you are not setting the value of that column in your code anywhere, the error is expected. What exactly is the question?
    – manish
    May 1 '17 at 10:40










  • @manish As JPA will insert ParentOne table which will create a parentOneID and then Insert ChildTable with that generated parentOneID. But here for me its not happening.
    – Sathish Kumar k k
    May 1 '17 at 10:55


















  • The error says that the column ChildTable.ParentOneID has a NOT NULL constraint on it and that an INSERT is being issued with a null value for that column. Since you are not setting the value of that column in your code anywhere, the error is expected. What exactly is the question?
    – manish
    May 1 '17 at 10:40










  • @manish As JPA will insert ParentOne table which will create a parentOneID and then Insert ChildTable with that generated parentOneID. But here for me its not happening.
    – Sathish Kumar k k
    May 1 '17 at 10:55
















The error says that the column ChildTable.ParentOneID has a NOT NULL constraint on it and that an INSERT is being issued with a null value for that column. Since you are not setting the value of that column in your code anywhere, the error is expected. What exactly is the question?
– manish
May 1 '17 at 10:40




The error says that the column ChildTable.ParentOneID has a NOT NULL constraint on it and that an INSERT is being issued with a null value for that column. Since you are not setting the value of that column in your code anywhere, the error is expected. What exactly is the question?
– manish
May 1 '17 at 10:40












@manish As JPA will insert ParentOne table which will create a parentOneID and then Insert ChildTable with that generated parentOneID. But here for me its not happening.
– Sathish Kumar k k
May 1 '17 at 10:55




@manish As JPA will insert ParentOne table which will create a parentOneID and then Insert ChildTable with that generated parentOneID. But here for me its not happening.
– Sathish Kumar k k
May 1 '17 at 10:55












1 Answer
1






active

oldest

votes


















2














When using JPA, the JPA provider needs to be allowed to manage the relationships between entity instances. In the given case, the relationships are being managed manually by keeping a track of various foreign key identifiers. Therefore, the JPA provider is unable to set the foreign key column values.



The basic problem seems to be in the understanding of how JPA (or any other ORM) works. Entities are not a column-by-column replica of database tables. They need to be thought of and modelled as objects without thinking of the underlying database. The mapping of entity attributes to database columns should be left to the JPA provider.





The following entity model will solve the problem (all unnecessary code removed for brevity):




ParentOne entity




@Entity
@Table(name="ParentOne", schema="S1")
public class ParentOne {
@Id
@Column(name="ParentOneID", unique=true, nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL, mappedBy="parentOne")
private List<Child> children;

public void addChild(final Child child) {
if (children == null) {
children = new ArrayList<>();
}

children.add(child);

child.setParentOne(this);
}
}


The following points are noteworthy:




  1. The schema name (S1) has been declared along side the table name to which the entity instances must be persisted.

  2. The relationship with the child entity is declared as a collection and annotated as @OneToMany.

  3. Persistence operations (save, update, delete) are cascaded to the child entity instances (cascade = CascadeType.ALL). This ensures that a persistence operation on a parent instance automatically takes care of appropriate operations on any associated child instances.



ParentTwo entity




@Entity
@Table(name="ParentTwo", schema="S2")
public class ParentTwo {
@Id
@Column(name="ParentTwoID", unique=true, nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL, mappedBy="parentTwo")
private List<Child> children;

public void addChild(final Child child) {
if (children == null) {
children = new ArrayList<>();
}

children.add(child);

child.setParentTwo(this);
}
}



Child entity




@Entity
@Table(name="ChildTable", schema="S2")
public class Child {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="ChildTableID", unique=true, nullable=false)
private Integer id;

@ManyToOne(cascade=CascadeType.PERSIST)
@JoinColumn(name="ParentOneID", nullable=false)
private ParentOne parentOne;

@ManyToOne(cascade=CascadeType.PERSIST)
@JoinColumn(name="ParentTwoID", nullable=false)
private ParentTwo parentTwo;

void setParentOne(final ParentOne parentOne) {
this.parentOne = parentOne;
}

void setParentTwo(final ParentTwo parentTwo) {
this.parentTwo = parentTwo;
}
}


The following points are noteworthy:




  1. The schema name (S2) is declared along side the table names.

  2. The associations with the parent tables are declared as object instances, instead of raw columns.


After this, the following code will work fine:



Child child = new Child();
...

ParentOne parentOne = new ParentOne();
ParentTwo parentTwo = new ParentTwo();
...

parentOne.addChild(child);
parentTwo.addChild(child);

parentOneRepository.save(parentOne);





share|improve this answer























  • Ya Its working and I would like to know is it possible to persist all three tables together (i.e) clild.setParentTwoID(prentTwoID); I am not going to give this line of code will it work?
    – Sathish Kumar k k
    May 2 '17 at 11:31










  • Yes, as long as operations have been configured to cascade to the appropriate related entities, a save can be initiated with any entity instance and will get cascaded to all others. See edited answer for details.
    – manish
    May 2 '17 at 11:40











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f43716896%2fpersist-tables-with-parent-child-relation-between-two-different-schema-in-spring%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














When using JPA, the JPA provider needs to be allowed to manage the relationships between entity instances. In the given case, the relationships are being managed manually by keeping a track of various foreign key identifiers. Therefore, the JPA provider is unable to set the foreign key column values.



The basic problem seems to be in the understanding of how JPA (or any other ORM) works. Entities are not a column-by-column replica of database tables. They need to be thought of and modelled as objects without thinking of the underlying database. The mapping of entity attributes to database columns should be left to the JPA provider.





The following entity model will solve the problem (all unnecessary code removed for brevity):




ParentOne entity




@Entity
@Table(name="ParentOne", schema="S1")
public class ParentOne {
@Id
@Column(name="ParentOneID", unique=true, nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL, mappedBy="parentOne")
private List<Child> children;

public void addChild(final Child child) {
if (children == null) {
children = new ArrayList<>();
}

children.add(child);

child.setParentOne(this);
}
}


The following points are noteworthy:




  1. The schema name (S1) has been declared along side the table name to which the entity instances must be persisted.

  2. The relationship with the child entity is declared as a collection and annotated as @OneToMany.

  3. Persistence operations (save, update, delete) are cascaded to the child entity instances (cascade = CascadeType.ALL). This ensures that a persistence operation on a parent instance automatically takes care of appropriate operations on any associated child instances.



ParentTwo entity




@Entity
@Table(name="ParentTwo", schema="S2")
public class ParentTwo {
@Id
@Column(name="ParentTwoID", unique=true, nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL, mappedBy="parentTwo")
private List<Child> children;

public void addChild(final Child child) {
if (children == null) {
children = new ArrayList<>();
}

children.add(child);

child.setParentTwo(this);
}
}



Child entity




@Entity
@Table(name="ChildTable", schema="S2")
public class Child {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="ChildTableID", unique=true, nullable=false)
private Integer id;

@ManyToOne(cascade=CascadeType.PERSIST)
@JoinColumn(name="ParentOneID", nullable=false)
private ParentOne parentOne;

@ManyToOne(cascade=CascadeType.PERSIST)
@JoinColumn(name="ParentTwoID", nullable=false)
private ParentTwo parentTwo;

void setParentOne(final ParentOne parentOne) {
this.parentOne = parentOne;
}

void setParentTwo(final ParentTwo parentTwo) {
this.parentTwo = parentTwo;
}
}


The following points are noteworthy:




  1. The schema name (S2) is declared along side the table names.

  2. The associations with the parent tables are declared as object instances, instead of raw columns.


After this, the following code will work fine:



Child child = new Child();
...

ParentOne parentOne = new ParentOne();
ParentTwo parentTwo = new ParentTwo();
...

parentOne.addChild(child);
parentTwo.addChild(child);

parentOneRepository.save(parentOne);





share|improve this answer























  • Ya Its working and I would like to know is it possible to persist all three tables together (i.e) clild.setParentTwoID(prentTwoID); I am not going to give this line of code will it work?
    – Sathish Kumar k k
    May 2 '17 at 11:31










  • Yes, as long as operations have been configured to cascade to the appropriate related entities, a save can be initiated with any entity instance and will get cascaded to all others. See edited answer for details.
    – manish
    May 2 '17 at 11:40
















2














When using JPA, the JPA provider needs to be allowed to manage the relationships between entity instances. In the given case, the relationships are being managed manually by keeping a track of various foreign key identifiers. Therefore, the JPA provider is unable to set the foreign key column values.



The basic problem seems to be in the understanding of how JPA (or any other ORM) works. Entities are not a column-by-column replica of database tables. They need to be thought of and modelled as objects without thinking of the underlying database. The mapping of entity attributes to database columns should be left to the JPA provider.





The following entity model will solve the problem (all unnecessary code removed for brevity):




ParentOne entity




@Entity
@Table(name="ParentOne", schema="S1")
public class ParentOne {
@Id
@Column(name="ParentOneID", unique=true, nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL, mappedBy="parentOne")
private List<Child> children;

public void addChild(final Child child) {
if (children == null) {
children = new ArrayList<>();
}

children.add(child);

child.setParentOne(this);
}
}


The following points are noteworthy:




  1. The schema name (S1) has been declared along side the table name to which the entity instances must be persisted.

  2. The relationship with the child entity is declared as a collection and annotated as @OneToMany.

  3. Persistence operations (save, update, delete) are cascaded to the child entity instances (cascade = CascadeType.ALL). This ensures that a persistence operation on a parent instance automatically takes care of appropriate operations on any associated child instances.



ParentTwo entity




@Entity
@Table(name="ParentTwo", schema="S2")
public class ParentTwo {
@Id
@Column(name="ParentTwoID", unique=true, nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL, mappedBy="parentTwo")
private List<Child> children;

public void addChild(final Child child) {
if (children == null) {
children = new ArrayList<>();
}

children.add(child);

child.setParentTwo(this);
}
}



Child entity




@Entity
@Table(name="ChildTable", schema="S2")
public class Child {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="ChildTableID", unique=true, nullable=false)
private Integer id;

@ManyToOne(cascade=CascadeType.PERSIST)
@JoinColumn(name="ParentOneID", nullable=false)
private ParentOne parentOne;

@ManyToOne(cascade=CascadeType.PERSIST)
@JoinColumn(name="ParentTwoID", nullable=false)
private ParentTwo parentTwo;

void setParentOne(final ParentOne parentOne) {
this.parentOne = parentOne;
}

void setParentTwo(final ParentTwo parentTwo) {
this.parentTwo = parentTwo;
}
}


The following points are noteworthy:




  1. The schema name (S2) is declared along side the table names.

  2. The associations with the parent tables are declared as object instances, instead of raw columns.


After this, the following code will work fine:



Child child = new Child();
...

ParentOne parentOne = new ParentOne();
ParentTwo parentTwo = new ParentTwo();
...

parentOne.addChild(child);
parentTwo.addChild(child);

parentOneRepository.save(parentOne);





share|improve this answer























  • Ya Its working and I would like to know is it possible to persist all three tables together (i.e) clild.setParentTwoID(prentTwoID); I am not going to give this line of code will it work?
    – Sathish Kumar k k
    May 2 '17 at 11:31










  • Yes, as long as operations have been configured to cascade to the appropriate related entities, a save can be initiated with any entity instance and will get cascaded to all others. See edited answer for details.
    – manish
    May 2 '17 at 11:40














2












2








2






When using JPA, the JPA provider needs to be allowed to manage the relationships between entity instances. In the given case, the relationships are being managed manually by keeping a track of various foreign key identifiers. Therefore, the JPA provider is unable to set the foreign key column values.



The basic problem seems to be in the understanding of how JPA (or any other ORM) works. Entities are not a column-by-column replica of database tables. They need to be thought of and modelled as objects without thinking of the underlying database. The mapping of entity attributes to database columns should be left to the JPA provider.





The following entity model will solve the problem (all unnecessary code removed for brevity):




ParentOne entity




@Entity
@Table(name="ParentOne", schema="S1")
public class ParentOne {
@Id
@Column(name="ParentOneID", unique=true, nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL, mappedBy="parentOne")
private List<Child> children;

public void addChild(final Child child) {
if (children == null) {
children = new ArrayList<>();
}

children.add(child);

child.setParentOne(this);
}
}


The following points are noteworthy:




  1. The schema name (S1) has been declared along side the table name to which the entity instances must be persisted.

  2. The relationship with the child entity is declared as a collection and annotated as @OneToMany.

  3. Persistence operations (save, update, delete) are cascaded to the child entity instances (cascade = CascadeType.ALL). This ensures that a persistence operation on a parent instance automatically takes care of appropriate operations on any associated child instances.



ParentTwo entity




@Entity
@Table(name="ParentTwo", schema="S2")
public class ParentTwo {
@Id
@Column(name="ParentTwoID", unique=true, nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL, mappedBy="parentTwo")
private List<Child> children;

public void addChild(final Child child) {
if (children == null) {
children = new ArrayList<>();
}

children.add(child);

child.setParentTwo(this);
}
}



Child entity




@Entity
@Table(name="ChildTable", schema="S2")
public class Child {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="ChildTableID", unique=true, nullable=false)
private Integer id;

@ManyToOne(cascade=CascadeType.PERSIST)
@JoinColumn(name="ParentOneID", nullable=false)
private ParentOne parentOne;

@ManyToOne(cascade=CascadeType.PERSIST)
@JoinColumn(name="ParentTwoID", nullable=false)
private ParentTwo parentTwo;

void setParentOne(final ParentOne parentOne) {
this.parentOne = parentOne;
}

void setParentTwo(final ParentTwo parentTwo) {
this.parentTwo = parentTwo;
}
}


The following points are noteworthy:




  1. The schema name (S2) is declared along side the table names.

  2. The associations with the parent tables are declared as object instances, instead of raw columns.


After this, the following code will work fine:



Child child = new Child();
...

ParentOne parentOne = new ParentOne();
ParentTwo parentTwo = new ParentTwo();
...

parentOne.addChild(child);
parentTwo.addChild(child);

parentOneRepository.save(parentOne);





share|improve this answer














When using JPA, the JPA provider needs to be allowed to manage the relationships between entity instances. In the given case, the relationships are being managed manually by keeping a track of various foreign key identifiers. Therefore, the JPA provider is unable to set the foreign key column values.



The basic problem seems to be in the understanding of how JPA (or any other ORM) works. Entities are not a column-by-column replica of database tables. They need to be thought of and modelled as objects without thinking of the underlying database. The mapping of entity attributes to database columns should be left to the JPA provider.





The following entity model will solve the problem (all unnecessary code removed for brevity):




ParentOne entity




@Entity
@Table(name="ParentOne", schema="S1")
public class ParentOne {
@Id
@Column(name="ParentOneID", unique=true, nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL, mappedBy="parentOne")
private List<Child> children;

public void addChild(final Child child) {
if (children == null) {
children = new ArrayList<>();
}

children.add(child);

child.setParentOne(this);
}
}


The following points are noteworthy:




  1. The schema name (S1) has been declared along side the table name to which the entity instances must be persisted.

  2. The relationship with the child entity is declared as a collection and annotated as @OneToMany.

  3. Persistence operations (save, update, delete) are cascaded to the child entity instances (cascade = CascadeType.ALL). This ensures that a persistence operation on a parent instance automatically takes care of appropriate operations on any associated child instances.



ParentTwo entity




@Entity
@Table(name="ParentTwo", schema="S2")
public class ParentTwo {
@Id
@Column(name="ParentTwoID", unique=true, nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL, mappedBy="parentTwo")
private List<Child> children;

public void addChild(final Child child) {
if (children == null) {
children = new ArrayList<>();
}

children.add(child);

child.setParentTwo(this);
}
}



Child entity




@Entity
@Table(name="ChildTable", schema="S2")
public class Child {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="ChildTableID", unique=true, nullable=false)
private Integer id;

@ManyToOne(cascade=CascadeType.PERSIST)
@JoinColumn(name="ParentOneID", nullable=false)
private ParentOne parentOne;

@ManyToOne(cascade=CascadeType.PERSIST)
@JoinColumn(name="ParentTwoID", nullable=false)
private ParentTwo parentTwo;

void setParentOne(final ParentOne parentOne) {
this.parentOne = parentOne;
}

void setParentTwo(final ParentTwo parentTwo) {
this.parentTwo = parentTwo;
}
}


The following points are noteworthy:




  1. The schema name (S2) is declared along side the table names.

  2. The associations with the parent tables are declared as object instances, instead of raw columns.


After this, the following code will work fine:



Child child = new Child();
...

ParentOne parentOne = new ParentOne();
ParentTwo parentTwo = new ParentTwo();
...

parentOne.addChild(child);
parentTwo.addChild(child);

parentOneRepository.save(parentOne);






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 13 '18 at 3:12

























answered May 1 '17 at 12:18









manish

12.8k43769




12.8k43769












  • Ya Its working and I would like to know is it possible to persist all three tables together (i.e) clild.setParentTwoID(prentTwoID); I am not going to give this line of code will it work?
    – Sathish Kumar k k
    May 2 '17 at 11:31










  • Yes, as long as operations have been configured to cascade to the appropriate related entities, a save can be initiated with any entity instance and will get cascaded to all others. See edited answer for details.
    – manish
    May 2 '17 at 11:40


















  • Ya Its working and I would like to know is it possible to persist all three tables together (i.e) clild.setParentTwoID(prentTwoID); I am not going to give this line of code will it work?
    – Sathish Kumar k k
    May 2 '17 at 11:31










  • Yes, as long as operations have been configured to cascade to the appropriate related entities, a save can be initiated with any entity instance and will get cascaded to all others. See edited answer for details.
    – manish
    May 2 '17 at 11:40
















Ya Its working and I would like to know is it possible to persist all three tables together (i.e) clild.setParentTwoID(prentTwoID); I am not going to give this line of code will it work?
– Sathish Kumar k k
May 2 '17 at 11:31




Ya Its working and I would like to know is it possible to persist all three tables together (i.e) clild.setParentTwoID(prentTwoID); I am not going to give this line of code will it work?
– Sathish Kumar k k
May 2 '17 at 11:31












Yes, as long as operations have been configured to cascade to the appropriate related entities, a save can be initiated with any entity instance and will get cascaded to all others. See edited answer for details.
– manish
May 2 '17 at 11:40




Yes, as long as operations have been configured to cascade to the appropriate related entities, a save can be initiated with any entity instance and will get cascaded to all others. See edited answer for details.
– manish
May 2 '17 at 11:40


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f43716896%2fpersist-tables-with-parent-child-relation-between-two-different-schema-in-spring%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Bressuire

Vorschmack

Quarantine