Foreign key is inserted null with CascadeType.PERSIST,- Spring Data Jpa - postgresql

I have two tables Parent and Child. They have one to one relation between them. When I save the Parent table it should insert into the Child table as well. A child table is inserted but the foreign key is null in the child table. I want a foreign key to be the autogenerated value from the Parent table.
I am using the Postgres database.
Here are my entity relations:
#Table(name = "`PARENT`")
#Setter
#Getter
#Entity
public class Parent{
#Id
#Column(name = "`RPT_PARM_ID`")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
//Other column mappings.
#OneToOne(mappedBy = "parent", cascade = { CascadeType.DETACH, CascadeType.MERGE,
CascadeType.REFRESH, CascadeType.PERSIST })
private Child child;
}
#Entity
#Table(name = "`CHILD`")
#Setter
#Getter
public class Child {
#Id
#Column(name = "`ID`")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
//Other column mappings
#OneToOne(optional = false,cascade = { CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.PERSIST })
#JoinColumn(name = "`PARAM_ID`", referencedColumnName ="`RPT_PARM_ID`" )
private Parent parent;
}
//This is how I save the code
pubilc void save(){
Parent parent = new Parent();
//set other fields for parent.
Child child =new Child();
//set other fields in child.
parent.setChild(child);
repository.save(parent);
}
In child table, PARAM_ID is inserted null, but I want the column value from RPT_PARM_ID (this is auto-generated)

Related

Pagerequest object with sort property of the child

How to specify the children's property name while creating the PageRequest object. In the below example, I want to sort based on the name property of the Customer entity which is part of the Order class. I should be able to sort on any of the parent or child field.
Sort.Direction sortDirection = direction
.equalsIgnoreCase("asc") ? Sort.Direction.ASC : Sort.Direction.DESC;
//how to make the `name` property map to `Customer` name
PageRequest pageRequest = PageRequest.of(page, size, sortDirection, "name");
Page<Order> pageResponse = this.orderRepository.findAll(pageRequest);
#Entity
#Table(name = "orders")
public class Order {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToOne
#JoinColumn(name="customer_id", nullable = false)
#JsonBackReference
private Customer customer;
...
----------
#Entity
#Table(name = "customers")
#NoArgsConstructor
public class Customer implements UserDetails {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#NotEmpty(message = "customer name cannot be empty")
private String name;
#OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JsonManagedReference
private Set<Order> orders;
...

JPA Mapping OneToMany with partial embedded id child

Simple example (hopefully). I have a primary key (using a sequence) in one table and that value is a partial FK into a child table. I see the Parent is trying to be saved with a generated sequence, but then I see an exception that the parentId in the embeddable is null while saving the child. The sequence value used for the parent is not being carried over to the child. I have tried many annotations and mappedBy/join column names but no luck.
Any pointers would be very much appreciated.
public class Parent {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "audit_seq")
#SequenceGenerator(name = "audit_seq", allocationSize = 5)
private Long id;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "parent")
private List<Child> childList = new ArrayList<>();
//Used to add child record o the parent
public void addChild(Child child) {
this.childList .add(child);
child.setParent(this);
}
}
#Embeddable
public class ChildId {
private Long parentId;
private String name;
}
public class Child {
#EmbeddedId
private ChildId id;
private String myCol;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name = "parentId", insertable = false, updatable = false)
private Parent parent;
}
I was able to get this resolved with the use of a couple of annotations:
Parent class:
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "parent", orphanRemoval = true)
#PrimaryKeyJoinColumn
private List<Child> childList = new ArrayList<>();
Child class:
#ManyToOne
#MapsId("id")
#JoinColumn(name = "id")
private Parent parent;
Now all objects are being persisted when saving the parent with the appropiate sequence id.

how to store one table primary as an another table foreign key using one-to-one relationship

I have two entities with one to one relationship, I want parent entity primary as a child entity foreign key along with child entity primary key
I have been trying with JPA #MapsId() but I could not succeed
my parent entity
#Id
#SequenceGenerator(initialValue=10000, name = "parent_seq")
#GeneratedValue(strategy = GenerationType.SEQUENCE,
generator="parent_seq")
#Column(name = "parent_id")
private long parentid;
#OneToOne(mappedBy="parentEntity", cascade = CascadeType.ALL)
private ChildEntity childEntity;
and in my child entity
#SequenceGenerator(initialValue=10000, name = "child_seq")
#GeneratedValue(strategy = GenerationType.SEQUENCE,
generator="child_seq")
#Column(name = "child_id")
private long childid;
#MapsId("parent_id")
#OneToOne
private ParentEntity parentEntity;
here I would like to create tables using JPA for that I have given
spring.jpa.hibernate.ddl-auto=create
this is working fine but I am expecting that parent_id column should be created inside my childEntity table but it is not creating and the parent_id should be inserted into child tables parent_id column.
When you are going to use #MapsId feature then your 'child' entity should have the 'simple' identifier without any generation. For example:
#Entity
#Table(name = "parents")
public class Parent {
#Id
#GeneratedValue(...)
private Long id;
// other stuff...
}
#Entity
#Table(name = "children")
public class Child {
#Id
private Long id;
#MapsId
#OneToOne(fetch = FetchType.LAZY)
private Parent parent;
// other stuff...
}
In this case, the children table will be like the following:
create table children (
parent_id bigint not null constraint children_pkey primary key,
-- other stuff...
constraint fk_children_parent_id foreign key (parent_id) references parents(id)
);
More info: The best way to map a #OneToOne relationship with JPA and Hibernate

deleting parent exception with jpa

With netbeans 8.1 I have generated entity and jpa controller.
I have a parent entity and a child with a one to one relation.
The child entity has primary key equals to foreign key to the parent:
#Entity
#Table(name = "parent")
#XmlRootElement
public class Parent implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#OneToOne(cascade = CascadeType.ALL, mappedBy = "parent")
private Child child;
public Parent() {
}
etc....
}
#Entity
#Table(name = "child")
#XmlRootElement
public class Child implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "parent_id")
private Integer parentId;
#JoinColumn(name = "parent_id", referencedColumnName = "id", insertable = false, updatable = false)
#OneToOne(optional = false)
private Parent parent;
public Child() {
}
etc....
}
When I try to delete the parent I get:
IllegalOrphanException: This Parent (model.Parent[ id=1 ]) cannot be destroyed since the Child model.Child[ parentId=1 ] in its child field has a non-nullable parent field.
To avoid this I should delete the child first, but due to cascade.ALL it should be already done automatically.
Coding Child class as follows works
#Entity
#Table(name = "child")
#XmlRootElement
public class Child implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#JoinColumn(name = "parent_id", referencedColumnName = "id")
#OneToOne(optional = false)
private Parent parent;
...
}
Tables look like
create table child (parent_id integer not null,..., primary key (parent_id))
create table parent (id integer not null, ..., primary key (id))
alter table child add constraint ... foreign key (parent_id) references parent
The removal of a parent (em.remove(parent)) leads to
delete from child where parent_id=?
delete from parent where id=?

JPA: How to fill related entity after the master is inserted

I have two tables called SL_DOCUMENT and SL_PROPOSE. The SL_DOCUMENT has its own ID (ID_DOCUMENT) and a foreign key to SL_PROPOSE (ID_PROPOSE). The SL_PROPOSE ID column is ID_PROPOSE. The particularity is that SL_PROPOSE ID value is actually the SL_DOCUMENT.ID_DOCUMENT value. i.e., after a new SL_DOCUMENT is inserted, the related SL_PROPOSE should be inserted with the SL_DOCUMENT.ID_DOCUMENT as ID and later the same value should be used in SL_DOCUMENT.ID_PROPOSE column.
I did my JPA mapping as follows:
#Entity
#Table(name = "SL_DOCUMENT")
public class DocumentORM {
#Id
#Column(name = "ID_DOCUMENT")
#SequenceGenerator(name = "SEQ_SL_DOCUMENT", sequenceName = "SEQ_SL_DOCUMENT")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_SL_DOCUMENT")
private Long id;
#OneToOne(mappedBy = "document", cascade = { CascadeType.PERSIST })
// #JoinColumn(name = "ID_PROPOSE", updatable = false)
private ProposeORM propose;
// ...
}
#Entity
#Table(name = "SL_PROPOSE")
public class ProposeORM {
#Id
#Column(name = "ID_PROPOSE")
private Long id;
#MapsId
#OneToOne
#JoinColumn(name="ID_PROPOSE")
private DocumentORM document;
// ...
public ProposeORM(DocumentORM document) {
super();
this.document = document;
this.document.setPropositura(this);
}
}
To create the new instances of of DocumentORM and ProposeORM:
DocumentORM document = new DocumentORM();
ProposeORM propose = new ProposeORM(document);
And finally to insert the new Document with ProposeORM:
this.documentoDAO.insert(document);
When I really insert a document, according the snippets above, I see in the console (Websphere 8.5) the INSERT commands for the SL_DOCUMENT, SL_PROPOSE running correctly. However, when I see the tables, the column SL_DOCUMENT.ID_PROPOSE is still NULL. Even If I uncomment the #JoinColumn annotation over DocumentORM.propose, the SL_DOCUMENT.ID_PROPOSE column continues to be not filled.
The ideal would be if SL_DOCUMENT had a discriminator column and ProposeORM was a DocumentORM subclass, using the JOINED InheritanceType (there are other tables with the same kind of relationship with SL_DOCUMENT). However, these are legacy tables and it is not possible to change it.
So, what is the alternative to fill SL_DOCUMENT.ID_PROPOSE? A workaround I was thinking is fill this column using a native SQL. Do you have better ideas?
Thanks,
Rafael Afonso
The solution I see is to make ProposeORM's ID not auto-generated, since you always want it to have the ID of the document it's linked to, AND still have a join column in the document table:
#Entity
#Table(name = "SL_DOCUMENT")
public class DocumentORM {
#Id
#Column(name = "ID_DOCUMENT")
#SequenceGenerator(name = "SEQ_SL_DOCUMENT", sequenceName = "SEQ_SL_DOCUMENT")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_SL_DOCUMENT")
private Long id;
#OneToOne
#JoinColumn(name = "ID_PROPOSE")
private ProposeORM propose;
// ...
}
#Entity
#Table(name = "SL_PROPOSE")
public class ProposeORM {
#Id
#Column(name = "ID_PROPOSE")
private Long id;
#OneToOne(mappedBy = propose)
private DocumentORM document;
// ...
public ProposeORM(DocumentORM document) {
super();
this.id = document.getId();
this.document = document;
this.document.setPropositura(this);
}
}
You'll have to persist the document first, flush the EntityManager to make sure the document has a generated ID, and then persist the propose and set it into the document.