Spring JPA: try to delete a record in a table with foreign key constraint - spring

In a project with Spring Boot and Spring JPA I an enitity FunctionConfiguration with a list of Integer target_device
#Entity
#Table(name = "function_configuration")
public class FunctionConfigurationEntity {
#Id
#Column(name = "id_function_configuration")
#GeneratedValue(strategy = IDENTITY)
private Integer idFunctionConfiguration;
#ElementCollection
#CollectionTable(name = "target_device")
private List<Integer> targetDevice;
}
If I try to do a delete with an id of a functionConfiguration
#Transactional
#Modifying
#Query(value = "DELETE FROM FunctionConfigurationEntity fce WHERE fce.idFunctionConfiguration = idFunctionConfiguration")
void deleteByFunctionConfigurationId(#Param("idFunctionConfiguration") Integer functionConfigurationId);
I get the following error:
Caused by: org.postgresql.util.PSQLException: ERROR: UPDATE or DELETE statement on table "function_configuration" violates foreign key constraint "fk69tox326tcrs3wed1neufb0pv" on table "target_device"
How can I fix it?

Related

Why Value is not getting assigned in JPA for insert statement

Hi I have couple of Entity classes as below, using lombok for getter and setters
Parent Entity Class have
#Table(name = "PARTY")
#Entity
public class Party {
#Id
#Column(name = "PARTY_ID")
private Long partyId;
#OneToMany(targetEntity = DVLoanParticipants.class,cascade = CascadeType.ALL)
#JoinColumn(name = "PARTY_ID")
#MapKey(name="dvpParticipantName")
#LazyCollection(LazyCollectionOption.FALSE)
private Map<String, DVLoanParticipants> dvLoanParticipantsMap;
}
Child Entity Class have
#Table(name = "DV_LOAN_PARTICIPANTS")
#Entity
public class DVLoanParticipants implements Serializable {
#Id
#Column(name = "PARTY_ID")
private Long partyId;
#Id
#Column(name = "DVP_PARTICIPANT_NAME")
private String dvpParticipantName;
#Column(name = "DVP_PARTICIPANT_TYPE")
private String dvpParticipantType;
}
In service class i am calling save operation as
repository.save(parentEntityObject);
I am able to execute update statements ,but when i try to insert new row for child entity class i am getting an error saying
cannot insert NULL into ("ABC"."DV_LOAN_PARTICIPANTS"."PARTY_ID")
But if i print the parentEntityObject just before the save operation i see the values like
(partyId=12345678, dvpParticipantName=XYZ, dvpParticipantType=VKP)
I see the query formed as
insert
into
DV_LOAN_PARTICIPANTS
(DVP_PARTICIPANT_TYPE, PARTY_ID, DVP_PARTICIPANT_NAME)
values
(?, ?, ?)
Just before te save i am seeing valules in the Object
Builder=DVLoanParticipants(partyId=123456, dvpParticipantName=Builder,
dvpParticipantType=Individual)
Update
This is the setting part for values
DVLoanParticipants dvLoanParticipants = new
DVLoanParticipants();
dvLoanParticipants.setPartyId(Long.valueOf(partyId));
dvLoanParticipants.setDvpParticipantName("Builder");
dvLoanParticipants.setDvpParticipantType("Individual");
Party party = new Party();
Map<String, DVLoanParticipants> dvLoanParticipantsMap = new
java.util.HashMap<>();
dvLoanParticipantsMap.put("Builder", dvLoanParticipants);
party.setPartyId(Long.valueOf(partyId));
party.setDvLoanParticipantsMap(dvLoanParticipantsMap);
repository.save(party);
What is the mistake i am doing ?
The root cause of your problem in this part:
#OneToMany(targetEntity = DVLoanParticipants.class,cascade = CascadeType.ALL)
#JoinColumn(name = "LOAN_ID")
#MapKey(name="dvpParticipantName")
private Map<String, DVLoanParticipants> dvLoanParticipantsMap;
actually for your case the column name in the #JoinColumn means:
If the join is for a unidirectional OneToMany mapping using a foreign key mapping strategy, the foreign key is in the table of the target entity.
So, assuming for the clarity that you want to map the following schema:
create table PARTY
(
PARTY_ID int,
-- ...
primary key (PARTY_ID)
);
create table DV_LOAN_PARTICIPANTS
(
PARTY_ID int,
DVP_PARTICIPANT_NAME varchar(50),
DVP_PARTICIPANT_TYPE varchar(10),
-- ...
primary key (PARTY_ID, DVP_PARTICIPANT_NAME),
foreign key (PARTY_ID) references PARTY(PARTY_ID)
);
You can use the following mapping:
#Entity
#Table(name = "PARTY")
public class Party
{
#Id
#Column(name = "PARTY_ID")
private Long partyId;
// I use fetch = FetchType.EAGER instead of deprecated #LazyCollection(LazyCollectionOption.FALSE)
// targetEntity = DVLoanParticipants.class is redundant here
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "PARTY_ID") // this is DV_LOAN_PARTICIPANTS.PARTY_ID column
#MapKey(name = "dvpParticipantName")
private Map<String, DVLoanParticipants> dvLoanParticipantsMap;
public Party()
{
dvLoanParticipantsMap = new HashMap<>();
}
// getters / setters
public void addParticipant(DVLoanParticipants p)
{
this.dvLoanParticipantsMap.put(p.getDvpParticipantName(), p);
p.setPartyId(getPartyId());
}
}
#Entity
#Table(name = "DV_LOAN_PARTICIPANTS")
public class DVLoanParticipants implements Serializable
{
#Id
#Column(name = "PARTY_ID")
private Long partyId;
#Id
#Column(name = "DVP_PARTICIPANT_NAME")
private String dvpParticipantName;
#Column(name = "DVP_PARTICIPANT_TYPE")
private String dvpParticipantType;
// getters / setters
}
and example how to save:
Party party = new Party();
party.setPartyId(2L);
// ...
DVLoanParticipants part1 = new DVLoanParticipants();
part1.setDvpParticipantName("Name 3");
part1.setDvpParticipantType("T1");
DVLoanParticipants part2 = new DVLoanParticipants();
part2.setDvpParticipantName("Name 4");
part2.setDvpParticipantType("T1");
party.addParticipant(part1);
party.addParticipant(part2);
repository.save(party);
and several notes:
The LazyCollectionOption.TRUE and LazyCollectionOption.FALSE values are deprecated since you should be using the JPA FetchType attribute of the #OneToMany association.
You use hibernate specific approach for mapping сomposite identifiers. As it's mentioned in the hibernate documentation:
The restriction that a composite identifier has to be represented by a primary key class (e.g. #EmbeddedId or #IdClass) is only JPA-specific.
Hibernate does allow composite identifiers to be defined without a primary key class via multiple #Id attributes.
But if you want to achieve more portability you should prefer one of the jpa allowed approaches.

Parent key not found with #MapsId

I am using Java8, SpringBoot 2.3.7 and JPA with Oracle
There is this legacy table (I cannot touch it, as it is in production with other applications)
TRANSFE (TRA_ID_PK NUMBER, ACCOUNT_ID NUMBER, .... )
CONSTRAINT "TRANSFE_UNIQUE" UNIQUE ("TRA_ID_PK")
In my new application some of the new Transfe will be TransfeIn, with only one field, so I created this table
TRANSFE_IN (ID NUMBER, ....)
CONSTRAINT "TRANSF_IN_PK" PRIMARY KEY ("ID")
Everything works fine with Jpa:
#Entity
#Table(name = "TRANSFE")
public class Transfe implements Serializable {
#Id
#Column(name = "TRA_ID_PK")
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_TRANSFES")
#SequenceGenerator(name="SEQ_SW_TRANSFERENCIAS", sequenceName="SEQ_TRANSFES", allocationSize=1)
private Long id;
#ManyToOne
#JoinColumn(name = "TRA_ID")
private Account account;
#OneToOne(cascade = {CascadeType.ALL})
#PrimaryKeyJoinColumn
private TransfeIn transfeIn;
and
#Entity
#Table(name = "TRANSFE_IN")
public class TransferenciaEntrant {
#Id
private Long id;
#MapsId
#OneToOne(cascade = {CascadeType.ALL}, mappedBy = "transfeIn")
#JoinColumn(name = "id")
private Transfe transfe;
The problem raises when I add this to TRANSFE_IN
CONSTRAINT "TRANSFE_IN_FK" FOREIGN KEY ("ID") REFERENCES "TRANSFE" ("TRA_ID_PK")
So when there is a new TransfeIn to be stored with
accountRepository.save(account)
(Account has a #OneToMany(mappedBy = "account", cascade = CascadeType.ALL) List transfes), I get
SQLIntegrityConstraintViolationException: ORA-02291: integrity constraint (TRANSFE_ENTR_FK) violated - parent key not found
In the logs, I can see how a new TRANSFE_IN row with the right ID (taken from SEQ_TRANSFES) is being inserted. But the table TRANSFE is empty, yet.
What am I doing wrong? Should I not use the FK? Or there is something in the annotations to be changed?

ERROR: UPDATE or DELETE statement on table

In a project with Spring Boot and Spring JPA I Have two entities FunctionConfiguration and InvokeFunctionResult.
#Entity
#Table(name = "function_configuration")
public class FunctionConfigurationEntity {
#Id
#Column(name = "id_function_configuration")
#GeneratedValue(strategy = IDENTITY)
private Integer idFunctionConfiguration;
}
#Entity
#Table(name = "invoked_function_result")
public class InvokedFunctionResultEntity {
#Id
#Column(name = "id_invoked_result_function")
#GeneratedValue(strategy = IDENTITY)
private Integer idInvokedResultFunction;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "function_configuration_id", nullable = false, foreignKey = #ForeignKey(name = "function_configuration_fk"), referencedColumnName = "id_function_configuration")
private FunctionConfigurationEntity functionConfiguration;
}
The InvokeFunctionResult has foreign key the id of the FunctionConfiguration.
If I try to do a delete with an id of a functionConfiguration that is present in the InvokeFunctionResult:
#Transactional
#Modifying
#Query(value = "DELETE FROM FunctionConfigurationEntity fce WHERE fce.idFunctionConfiguration = idFunctionConfiguration")
void deleteByFunctionConfigurationId(#Param("idFunctionConfiguration") Integer functionConfigurationId);
I get the following error: Caused by: org.postgresql.util.PSQLException: ERROR: UPDATE or DELETE statement on table "function_configuration" violates foreign key constraint "function_configuration_fk" on table "invoked_function_result"
How can I fix it?

Remove rows mappedBy a foreign key of another table

I have two tables Company and Employees. They have a 1-many relation. I want to delete all rows from Company and set null the column with foreign-key from Employees.
#Entity
public class Employees{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int empId;
#ManyToOne
#JoinColumn(name="company_id")
private Company company;
}
#Entity
public class Company{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int comId;
#OneToMany(mappedBy = "company", cascade = CascadeType.ALL)
private List<Employees> employees = new LinkedList<>();
}
public interface CompanyRepository extends JpaRepository<Company, Integer> {
}
public interface EmployeesRepository extends JpaRepository<Employees, Integer> {
}
In controller if I just delete Company rows with #AutowiredCompanyRepository companyRepo; companyRepo.deleteAll(); it shows of course:
Cannot delete or update a parent row: a foreign key constraint fails.
I tried to write an update in EmployeesRepository over Employees to set company.comId to null, because I want to keep the rows, except comId field. In EmployeesRepository I wrote:
#Modifying
#Query("UPDATE Employees e SET e.company.comId=null")
void removeCompanyId();
It caused the following error:
javax.persistence.TransactionRequiredException: Executing an update/delete query

Spring: relation data many-to-one

i have first entity :
#Entity
#Table(name="TABLE_ONE")
public class TableOne implements Serializable {
#Id
#Column(name="ID")
private Integer id;
#ManyToOne
#JoinColumn(name="TABLE_TWO_ID", nullable = false)
private TableTwo tableTwoId;
and the second table entity :
#Entity
#Table(name="TABLE_TWO")
public class TableTwo{
#Id
#Column(name="ID")
private Integer id;
, but then after i compile , the result is :
ERROR: column "table_two_id" does not exist
I want to get ID from TableTwo.
Joincolumn annotation tells hibernate the foreign key join column name, in this case I guess it's ID.

Resources