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

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

Related

Foreign Key violation on ManyToMany with inheritance

Im currently building the following scenario:
I have an Action which holds a list of Parameters. Those can be in other actions as well, so I have a ManyToMany relationship.
The Parameter is an abstract class, one implementation is a TextParameter.
So now I have the following code:
#Data
#Entity
public class Action {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(
name = "Action2ParameterMapping",
joinColumns = #JoinColumn(name = "actionId"),
inverseJoinColumns = #JoinColumn(name = "parameterId"))
private List<Parameter> parameters;
}
with Parameter as
#Data
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
public abstract class ProductSample {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...
}
And TextParameter:
#Data
#Entity
#PrimaryKeyJoinColumn(name = "parameterId")
public class TextParameter extends Parameter {
...
}
I now created the Tables as follows (I don't want to generate since we use Flyway migration):
CREATE TABLE Action
(
id BIGINT NOT NULL PRIMARY KEY IDENTITY
)
CREATE TABLE Parameter
(
id BIGINT NOT NULL PRIMARY KEY IDENTITY
)
CREATE TABLE TextParameter
(
parameterId BIGINT NOT NULL FOREIGN KEY REFERENCES Parameter (id)
)
-- Many-To-Many MappingTable
CREATE TABLE Action2ParameterMapping
(
actionId BIGINT NOT NULL FOREIGN KEY REFERENCES Action (id),
parameterId BIGINT NOT NULL FOREIGN KEY REFERENCES Parameter (id),
PRIMARY KEY (actionId, parameterId)
)
I use Quarkus and have the simple PanacheRepository
#ApplicationScoped
public class ActionRepository implements PanacheRepository<Action> {
}
So now, when I now create an Action-Object holding Parameter-Objects and persist it using actionRepository.persist(action), I get an SQLServerException The INSERT statement conflicted with the FOREIGN KEY constraint "FK__Action2Pa__actio__4242D080 and I don't understand why.
I understand that it tries to tell me, that it wanted to persist an entry in the MappingTable but the actionId did not belong to any Action, but how can that be?
I don't understand, why this won't work.
After having the problem for over 3 days, I've solved almost right after asking the question...
The problem was within the DB-Test-Suite.
The #AfterEachmethod tried to delete parameters, which violated the Contraint...

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

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)

Hibernate cascade save with OneToOne relation

I have two tables Users
CREATE TABLE `users` (
`id` BIGINT NOT NULL,
PRIMARY KEY (`id`))
and Carts
CREATE TABLE `carts` (
`id` BIGINT NOT NULL,
`user_id` BIGINT,
PRIMARY KEY (`id`))
ALTER TABLE `carts` ADD CONSTRAINT Cart_User_FK
FOREIGN KEY (`user_id`) REFERENCES `users` (`id`);
I create entities for them
#Entity
#Table(name = "users")
public class User{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#OneToOne(cascade = CascadeType.ALL, mappedBy = "user")
private Cart cart;
}
and
#Entity
#Table(name = "carts")
public class Cart{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "user_id")
private User user;
}
I try to set cart instance to user and save user
Cart cart = new Cart();
cartRepository.save(cart);
user.setCart(cart);
userRepository.save(user);
but hibernate don't update cart table
repositories extended from SimpleJpaRepository
Could somebody explain me how to update related object?

JPA auto-generated key not reflected in foreign key of child table

Parent Table:
#Table(name="parent_table_t")
public class ParentTable implements Serializable {
#Id
#Column(name="contact_id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer contactId;
---------
---------
#OneToOne (cascade = CascadeType.ALL, mappedBy = "parentTable")
private ChildTable childTable;
}
Child Table:
#Table(name="child_table_t")
public class ChildTable implements Serializable {
#Id
#Column(name="child_id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer childId;
#Column(name="contact_id")
private Integer contactId;
#JoinColumn(name="contact_id", referencedColumnName = "contact_id", insertable=false, updatable=false)
#OneToOne(cascade = CascadeType.ALL)
private ParentTable parentTable;
}
My requirement is when contact_id is generated in Parent_table_t, it should be copied into contact_id of child_table_t when saved.
When I am calling saveAndFlush / save on Parent Table Entity, it is:
Generating the auto-increment for Parent->contact_id.
But Child_table_t -> contact_id is always null.
Can someone please help in this.
I am using in-memorty hsqldb with spring-boot and JPA.
You marked the relationship #JoinColumn with insertable=false, updatable=false, likely because you have an integer mapping for the column as well. Unfortunately, these settings prevent JPA from setting it with values from the relationship, which instead is forced to set the column with the value in the contactId attribute.
Put the insertable=false, updatable=false on the #Column instead.

How to disable delete for JoinTable?

I have problem with disable delete for JoinTable.
#Entity
class Employee
{
#Id
Long id;
#ManyToOne( cascade = { CascadeType.REFRESH } )
#JoinTable( name = "Employee2AddressOracleView",
joinColumns = #JoinColumn( name = "employee_id" ),
inverseJoinColumns = #JoinColumn( name = "address_id" )
private Address address;
)
Address for Employee is calculated in View. It works, I can load Employee but when I want delete employee JPA want delete row from view to. It is possible to disable this delete query?
JPA query in console:
delete from Employee where employee_id = ?
delete from Employee2AddressOracleView where employee_id = ?
The accepted answer has a link to hibernate forums which are dead. I managed to pull the link out on archive.org.
The solution is to create a separate entity representing the join table, mapped to the view, instead of using #JoinTable.
Main entity mappings:
#Entity
#Table(name="Main")
public class MainEntity {
#Id
#Column(name="id")
private Integer id;
#OneToOne
#PrimaryKeyJoinColumn
private JoinTableViewEntity joinEntity;
}
Join table view entity mappings:
#Entity
#Table(name="TableView")
public class JoinTableViewEntity {
#Id
#Column(name="id")
private Integer mainEntityId;
#ManyToOne
#JoinColumn(name="other_id", updatable=false, insertable=false)
private OtherEntity other;
}
It also works without updateable and insertable attributes.
If you are using EclipseLink you can use a DescriptorCustomizer to make the mapping readOnly.