Cannot delete parent and child - mysql

I have two entities using Spring and Hibernate
Entity A:
#Entity
#Table(name = "A")
public class A {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#OneToOne(cascade = CascadeType.ALL, mappedBy = "a")
private B b;
Here i have a one to one relationship with Entity B, the owner of the relationship is Entity A.
Entity B:
#Entity
public class B{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#OneToOne
#JoinColumn(name = "a_ID")
private A a;
Saving the entities gives no problem. Entity B gets the ID of entity A in the Database.
But when i delete Entity A, I also want to delete Entity B that belongs to A.
When I delete i get the error:
MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails
I think my declarations in my entities are correct. What is the problem here?
Edit
When I inspect the table of Entity B and specifically the Foreign key to Entity A it says Restricted on Update en on Delete

set orphanRemoval property to true in class A
like this: #OneToOne(mappedBy = "a", cascade = CascadeType.ALL, orphanRemoval = true)

Related

Problem while creating multiple foreign keys on a compound primary key using JPA

I have a table structure like this:
Table Structure
The dependencies are unidirectional.
My POJO classes look like this:
class T1 {
#EmbeddedId T1PK t1Pk;
String c13;
// getter setter
}
#Embeddable
class T1PK {
String c11;
String c12;
// getter setters hashCode equals
}
class T3 {
#Id String T31
String T32
// getter setter
}
#Embeddable
class T2PK {
T1PK t1Pk;
String c31;
// getter setters hashCode equals
}
class T2 {
#EmbeddedId T2PK t2Pk;
#MapsId("c31")
#JoinColumn(name = "c31", referencedColumnName = "c31", foreignKey = #ForeignKey(name = "FK_32"))
#OneToOne
private T3 t3;
#MapsId("t1Pk")
#JoinColumns(foreignKey = #ForeignKey(name = "FK_12"), value = {
#JoinColumn(name = "c11", referencedColumnName = "c11"),
#JoinColumn(name = "c12", referencedColumnName = "c12") })
#OneToOne
private T1 t1;
// getter setter
}
When I am starting my spring boot application, the following error is being encountered
Foreign key (FKakdpaxm8kl8mv0ld210dg7mcw:t2 [c11,c12,c31])) must have same number of columns as the referenced primary key (t3 [t31])
However it works fine if I just comment out the dependency of any one table, t3 or t1. A proper foreign key with the mentioned FK name gets created.
I wasn't able to try this out but T2PK should not contain a reference to T1PK but rather the #OneToOne relationship to T1 that is currently placed in T2.
#Embeddable
class T2PK {
#JoinColumns(foreignKey = #ForeignKey(name = "FK_12"), value = {
#JoinColumn(name = "c11", referencedColumnName = "c11"),
#JoinColumn(name = "c12", referencedColumnName = "c12") })
#OneToOne
private T1 t1;
String c31;
}
class T2 {
#EmbeddedId
T2PK t2Pk;
#MapsId("c31")
#JoinColumn(name = "c31", referencedColumnName = "c31", foreignKey = #ForeignKey(name = "FK_32"))
#OneToOne
private T3 t3;
}
Edit: It also may be possible that you can place the #OneToOne to T1 in T2 and use a #MapsId without value or a #MapsId("t1") to map the whole T1 object into your T2PK but I am not sure.

Foreign key constraint fails while using Spring Data

I'm using Spring Data to access my MySQL database with following entities
#Entity
#Table(name = "tbl_product")
public class Product implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;
#ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn
private Category category;
}
#Entity
#Table(name = "tbl_category")
public class Category implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(unique = true)
private String name;
}
Now I try to use my Controller to delete Product
#RequestMapping(path="/remove/{id}", method=RequestMethod.DELETE)
#ResponseBody
public String removeProduct(#PathVariable Long id) {
return productService.removeProduct(id);
}
public String removeProduct(Long productID) {
try {
productRepository.delete(productID);
return "OK";
} catch (Exception e) {
logger.info(e.getMessage());
return "Error";
}
}
Now, for example if there are 3 Products with Category A and 1 with Category B, I can remove the one with Category B. But if I try to remove any other one, I got
Cannot delete or update a parent row: a foreign key constraint fails
(product_db.tbl_product, CONSTRAINT FKfq7110lh85cseoy13cgni7pet
FOREIGN KEY (category_id) REFERENCES tbl_category (id))
It is because of the cascading that you are applying by cascade = CascadeType.ALL.
So, whenever you delete any product, JPA deletes the category id too. It works well if that category is not associated with any other product(which is what is happening in your second case). But if the category is associated with any other product then the foreign key constraint fails stating that category which you are trying to delete is associated with other product.
You should be very careful while mentioning cascade type. By default cascade mode is NONE but you can give different strategies like UPDATE, PERSIST etc. based upon your requirement

Alternative for #Formula?

I have two objects:
#Table(name = "user")
User
#Id
Integer id
Integer uuid;
and reservation:
#Table(name = "reservation")
Reservation
#Id
Integer id;
Integer uuid;
My goal is:
#Table(name = "reservation")
Reservation
#Id
Integer id;
Integer uuid;
#Formula("(SELECT * FROM user b WHERE b.uuid = uuid )")
List<User> users;
The problem is #Formula doesnt work with objects.
How to include list of all users in reservation with same uuid?
I found this but maybe there is better option
https://stackoverflow.com/a/37502703/3871754
Support of relationships that references non-PK columns is an optional feature. In simple cases it's supported by Hibernate
#NotAudited
#OneToMany
#JoinColumn(name = "uuid", referencedColumnName = "uuid")
private List<Barrier> barriers = new ArrayList<>();
and implemented Serializable for Reservation

Many to Many child removel JPA

Hi i have many to many relationship and entities are here:
#Entity
public class Company implements Serializable
{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer idcompany;
//bi-directional many-to-many association to Client
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinTable(name="company_client",
joinColumns=#JoinColumn(name="company_idcompany",
referencedColumnName="idcompany"),
inverseJoinColumns=#JoinColumn(name="client_idclient",
referencedColumnName="idclient"))
Set<Client> clients = new HashSet<Client>();
and second entity
#Entity
public class Client implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int idclient;
#ManyToMany(mappedBy="clients",cascade = CascadeType.PERSIST , fetch =
FetchType.LAZY )
Set<Company> companies = new HashSet<Company>();
and here is details of date in all 3 tables
---------------------------------------------
company table client table company_client table
id name id name fk_compny fk_client
1 Oracle 1 Abc 1 1
2 XYZ 1 2
when i want to remove row from client table e.g "XYZ" id=2
Client cl = em.find(Client.class,2);
em.remove(cl);
it throws exception "Cannot delete or update a parent row: a foreign key constraint fails " .
How to remove this row

Hibernate insert ID into auto-increment column

I am using Sprint Boot, Sprint Data JPA, Hibernate 4 and MySQL. I have a table with an autoincrement column. I can insert new entities ok and the column auto-increments. Sometimes though I want to specify the ID when doing an insert but Hibernate appears to ignore any ID value I set.
Table definition:
#Entity
#Table(name = "example")
public class Example implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
... more columns ....
}
How can I have both auto-increment when no id is set AND allow setting of the ID by my application?
Its because your ID is not that will be stored in the database,rather than that it is considering #GeneratedValue(strategy = GenerationType.IDENTITY) which is generating values for you