Cant remove parent row in MysqlDatabase by JavaSpring - mysql

I have problem with deleting datas in my Tables.
CategoryModel:
#Entity
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Table(name = "Category")
public class CategoryModel {
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
private Long category_id;
#Column(name = "CategoryName")
private String cateGoryName;
#Column(name = "Image")
#Lob
private String image;
#OneToMany(mappedBy = "categoryModel", cascade = CascadeType.ALL, orphanRemoval = true)
private List<ProductModel> productModels = new ArrayList<>();
}
ProductModel:
#Entity
#Getter
#Setter
#Table(name = "Products")
public class ProductModel {
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
private Long product_id;
#Column(name = "ProductName")
#Lob
private String productName;
#Column(name = "ShortName")
private String shortName;
#Column(name = "Price")
private int price;
#Column(name = "Slider")
private Boolean slider;
#Column(name = "SpecialOffer")
private Boolean specialOffer;
#Column(name = "NewPrice")
private int newPrice;
#Column(name = "ShortDesc")
private String shortDesc;
#Column(name = "FullDescription")
#Lob
private String fullDescription;
#Column(name = "Image")
#Lob
private String image;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "category_model_category_id")
private CategoryModel categoryModel;
}
And even i have addnotation: "orphanRemoval = true" i still cant remove category when a product is assigned to it. Error looks like:
"#1451 - Cannot delete or update a parent row"
Can someone tell me how could i improve it?

Related

Setting up an inheritance with Hibernate

I've been trying to set up inheritance in my Spring boot project, but I failed to do so. I've tried using the superclass mappings, joined table, single table but still I think I'm missing something. Here is how the classes look like:
Person class:
#Entity
#MappedSuperclass
#Table(name = "person")
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id_person", nullable = false)
private Integer id;
#Column(name = "first_name", nullable = false, length = 200)
private String firstName;
#Column(name = "last_name", nullable = false, length = 200)
private String lastName;
#Column(name = "PESEL", nullable = false)
private Integer pesel;
#OneToOne(fetch = FetchType.LAZY, mappedBy = "person")
private Driver driver;
//setters and getters below
}
Driver class:
#Entity
#Table(name = "driver")
public class Driver {
#Id
#Column(name = "id_driver", nullable = false)
private Integer id;
#MapsId
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "id_driver")
private Person person;
#Column(name = "birth_date", nullable = false)
private LocalDate birthDate;
#Column(name = "license", nullable = false, length = 200)
private String license;
#OneToMany(mappedBy = "idDriver")
private Set<Ride> rides = new LinkedHashSet<>();
//setters and getters below
}
Here's how it is joined in the database (mysql):
I would be very thankful if you could at least point me in the right direction (like which inheritance type will suit this simple case the best)
First remove the #Entity and #Table annotations, as well as the relationship, from your superclass:
#MappedSuperclass
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id_person", nullable = false)
private Integer id;
#Column(name = "first_name", nullable = false, length = 200)
private String firstName;
#Column(name = "last_name", nullable = false, length = 200)
private String lastName;
#Column(name = "PESEL", nullable = false)
private Integer pesel;
//setters and getters below
}
Secondly, remove the duplicated id column and remove the relationship between the mapped superclass and your derived classes, and actually extend the superclass:
#Entity
#Table(name = "driver")
public class Driver extends Person{
#Column(name = "birth_date", nullable = false)
private LocalDate birthDate;
#Column(name = "license", nullable = false, length = 200)
private String license;
#OneToMany(mappedBy = "idDriver")
private Set<Ride> rides = new LinkedHashSet<>();
//setters and getters below
}

How can i mapping entities in spring boot jpa?

I'm new in Spring Boot JPA
I have questions in JPA Entity mappings.
there is 4 tables in my MySql DB
SPACE, PROJECT, ISSUE, MEMBER
SPACE is Big Project which contains multiple PROJECT.
PROJECT contains multiple ISSUE.
and MEMBER can join only 1 SPACE and multiple PROJECT which MEMBER belongs to SPACE.
MEMBER can write multiple ISSUE
in this situation, my ERD model is correct?
my ERD
and please check my jpa mappings.
If there's anything wrong, please point it out.
SPACE
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "space_no")
private Long spaceNo;
#NotEmpty
#Column(name = "space_name", unique=true, length = 100)
private String spaceName;
/** 1:N relation */
#OneToMany(mappedBy = "smsSpace")
private List<PmsProject> pmsProjects = new ArrayList<>();
PROJECT
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "project_no")
private Long projectNo;
#Column(name ="space_no")
private Long spaceNo;
#Column(name = "project_name", length = 100)
private String projectName;
/** 1:N relation */
#OneToMany(mappedBy = "pmsProject")
private List<ImsIssue> imsIssues = new ArrayList<>();
#OneToMany(mappedBy = "pmsProject")
private List<PmsProjectMember> projectMembers = new ArrayList<>();
/** N:1 relation */
#ManyToOne
#JoinColumn(name = "space_no", referencedColumnName = "space_no", insertable = false, updatable = false)
private SmsSpace smsSpace;
MEMBER
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "member_no")
private Long memberNo;
#Column(name = "mail_address", unique=true, length = 100)
private String mailAddress;
#Column(name = "name", length = 100)
private String name;
#Column(name = "keyword", length = 1000)
private String keyword;
#Column(name = "image", length = 1000)
private String image;
#Column(name = "password", length = 1000)
private String password;
#Column(name = "user_id", length = 50)
private String userId;
#Enumerated(EnumType.STRING)
private MemberRole role;
public void encodingPassword(String password) {
this.password = password;
}
/** 1:N realtion */
#OneToMany(mappedBy = "mmsMember")
private List<PmsProjectMember> projectMembers = new ArrayList<>();
ISSUE
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "issue_no")
private Long issueNo;
#Column(name ="project_no")
private Long projectNo;
#Column(name = "issue_name", length = 1000)
private String issueName;
#Column(name = "priority")
private Long priority;
#Column(name = "status", length = 20)
private String status;
#Column(name = "summary", length = 100)
private String summary;
#Column(name = "is_overdue")
private Long isOverdue;
#Column(name = "issue_type_cd")
private String issueTypeCd;
/** N:1 relation */
#ManyToOne
#JoinColumn(name = "project_no", referencedColumnName = "project_no", insertable = false, updatable = false)
private PmsProject pmsProject;
PROJECTMEMBER
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "group_no")
private Long groupNo;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "member_no")
private MmsMember mmsMember;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "project_no")
private PmsProject pmsProject;
I've been thinking about it for days, but I can't solve it because I lack knowledge. Please help me.
Assuming I got your situation right, you have A member that can have one Space and multiple project, space has multiple projects, every project can have more than one issue, every member can write more then one issue for each project.
Due to the suggestion the ERD you posted it's not corrected.
Here is the correct ERD
(I just wrote the Foreign Keys and Primary Keys, the rest its up to you)
And here you have all the entites:
Member
#Entity
#Table(name = "MEMBERS")
public class Member {
//members is the property name in Project entity.
#ManyToMany(mappedBy = "members")
Set<Project> projects;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY, generator = "native")
#Column(name = "MEMBER_ID")
private Long id;
#ManyToOne
#JoinColumn(name = "SPACE_ID")
private Space space;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Space getSpace() {
return space;
}
public void setSpace(Space space) {
this.space = space;
}
public Set<Project> getProjects() {
return projects;
}
public void setProjects(Set<Project> projects) {
this.projects = projects;
}
}
Space
#Entity
#Table(name = "SPACES")
public class Space {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY, generator = "native")
#Column(name = "SPACE_ID")
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
Issue
#Entity
#Table(name = "ISSUES")
public class Issue {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY, generator = "native")
#Column(name = "ISSUE_ID")
private Long id;
#ManyToOne
#JoinColumn(name = "MEMBER_ID")
private Member member;
#ManyToOne
#JoinColumn(name = "PROJECt_ID")
private Project project;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Member getMember() {
return member;
}
public void setMember(Member member) {
this.member = member;
}
public Project getProject() {
return project;
}
public void setProject(Project project) {
this.project = project;
}
}
Project
#Entity
#Table(name = "PROJECTS")
public class Project {
#ManyToMany
#JoinTable(
name = "PROJECTS_MEMBERS",
joinColumns = #JoinColumn(name = "PROJECT_ID"),
inverseJoinColumns = #JoinColumn(name = "MEMBER_ID"))//Is referring to the id of the other Entity, in this case, members
Set<Member> members;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY, generator = "native")
#Column(name = "PROJECT_ID")
private Long id;
#ManyToOne
#JoinColumn(name = "SPACE_ID")
private Space space;
public Set<Member> getMembers() {
return members;
}
public void setMembers(Set<Member> members) {
this.members = members;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Space getSpace() {
return space;
}
public void setSpace(Space space) {
this.space = space;
}
}
You don't have to put necessarily both #ManyToOne and #OneToMany annotation, the back-reference could be useful in some use case, you have to see if you need it or not. Remember the back reference could cause problems with deserialization, creating a stack overflow by circular reference. You can avoid this, using transient keyword or various annotation (depending on the library you are using, Jackson, Gson, ecc..).
Be careful to don't use FetchType.EAGER randomly here's the why => Difference between FetchType LAZY and EAGER in Java Persistence API?

SpringBoot : parameterize resolving entity relations by different GET requests

i would like to parameterize fetching and returning an entity relation bydifferent GET requests on the entity.
Is there a configuration way to achieve that, combining fetch strategy and json inclusion ?
example : how to return / not return the list of Bs by different Gets on A.
#Entity
public class A {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToMany(mappedBy = "a", fetch = FetchType.LAZY)
private List<B> listBs ;
}
#Entity
public class B {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToOne(fetch = FetchType.LAZY)
private A a ;
}
You can do it using #JsonManagedReference, #JsonBackReference
#Entity
public class A {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToMany(mappedBy = "a", fetch = FetchType.LAZY)
#JsonBackReference
private List<B> listBs ;
}
#Entity
public class B {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToOne(fetch = FetchType.LAZY)
#JsonManagedReference
private A a ;
}

Nested one to many relationship jpa spring boot

I have three classes - Document, Page, Sentence. A Document will have multiple Pages & each Page will have multiple Sentences. I'm trying to map One to Many relationship using Spring Data JPA annotation. But it only works when there are only one layer like - Document>Page. Doesn't work while it's Document>Page>Sentence.
Can anyone please give me a solution for how to do it for nested one to many relationship ?
My classes are given below.
#Entity
#Table(name = "DOCUMENT")
public class Document implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "FILEID")
#GeneratedValue(strategy = GenerationType.AUTO)
private long idFile;
#Lob
#Column(name = "CONTENT")
private byte[] content;
#Column(name = "NAME")
private String name;
#Column(name = "ID_MAIL_USER")
private String idMailUser;
#Column(name = "NUM_PAGES")
private int numPages;
#Column(name = "TO_ANALIZE")
private boolean toAnalize;
#Column(name = "HASH")
private String hash;
#Column(name = "EXTENSION")
private String extension;
#Column(name = "SIZE")
private double size;
#Column(name = "LINK_TO_DRIVE_FILE")
private String linkToDriveFile;
#Column(name="PATH")
private String path;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#Column(name = "PAGES")
private List<Page> pages = new ArrayList<>();
// Setter Getters
}
.
#Entity
#Table(name = "PAGE")
public class Page implements Serializable {
#Id
#Column(name = "PAGE_ID")
#GeneratedValue(strategy = GenerationType.AUTO)
private long idPage;
#Column(name = "PAGE_NUMBER")
private int pageNum;
#Lob
#Column(name = "CONTENT")
private String content;
#ManyToMany(cascade = CascadeType.ALL)
#Column(name = "SENTENCES")
private List<Sentence> sentences = new ArrayList<>();
// Setter Getters
}
.
#Entity
#Table(name = "SENTENCE")
public class Sentence implements Serializable {
//private long idFile;
//private long idPage;
#Id
#Column(name = "SENTENCE_ID")
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "PAGE_NUMBER")
private int pageNumber;
#Column(name = "ORDER")
private int ord;
#Column(name = "CONTENT")
private String content;
#Column(name = "HASH")
private String hash;
// Setter Getters
}
Your OneToMany mappings are incorrect. Correct it as follows
#Entity
#Table(name = "DOCUMENT")
public class Document implements Serializable {
......
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name = "DOCUMENT_ID") //Name the foreign key column in PAGE table to DOCUMENT_ID
private List<Page> pages = new ArrayList<>();
}
#Entity
#Table(name = "PAGE")
public class Page implements Serializable {
....
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "PAGE_ID") //Name the forein key column in PAGE table to PAGE_ID
private List<Sentence> sentences = new ArrayList<>();
}
Use #JoinColumn annotation instead of #Column to give the name of the foreign key that do the physical mapping between tables in your database.
#Entity
#Table(name = "DOCUMENT")
public class Document implements Serializable {
private static final long serialVersionUID = 1L;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy="document")
#Column(name = "PAGES")
private List<Page> pages = new ArrayList<>();
}
#Entity
#Table(name = "PAGE")
public class Page implements Serializable {
#ManyToOne
#JoinColumn(name="DOCUMENT_ID")
private Document document;
#ManyToMany(cascade = CascadeType.ALL, mappedBy="pages")
#Column(name = "SENTENCES")
private List<Sentence> sentences = new ArrayList<>();
}
#Entity
#Table(name = "SENTENCE")
public class Sentence implements Serializable {
#ManyToMany(mappedBy="sentences")
private List<Page> pages;
}
Here a Document One to Many relationship with Pages.
So.. we need define mappedBy in the entity we want to map another entity.. so in this case
#OneToMany(mappedBy="document",cascade = CascadeType.ALL, orphanRemoval = true)
and in referenced entity i.e. Pages we want foreign key DOCUMENT_ID, so we have to define it using
#ManyToOne
#JoinColumn(name="DOCUMENT_ID")

JPA EclipseLink oneToMany Derived Ids Fail

Hello I'm trying to make an example of persistence of a OneToMany relationship in which I get the following error:
Exception Description: Invalid composite primary key specification. The names of the primary key fields or properties in the primary key class [entitys.OrderItemPK] and those of the entity bean class [class entitys.OrderItem] must correspond and their types must be the same. Also, ensure that you have specified ID elements for the corresponding attributes in XML and/or an #Id on the corresponding fields or properties of the entity class.
Note: I'm using EclipseLink and MySQL DB
The entities:
#Entity
public class CustomerOrder implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "idOrder")
private Integer idOrder;
#Basic(optional = false)
#Column(name = "orderText")
private String orderText;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "customerOrder")
private Collection<OrderItem> orderItemCollection;
public CustomerOrder() {
}
}
#Entity
#IdClass(OrderItemPK.class)
public class OrderItem implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected OrderItemPK orderItemPK;
#Basic(optional = false)
#Column(name = "itemDesc")
private String itemDesc;
#Id
#ManyToOne(optional = false)
#JoinColumns({
#JoinColumn(name="idOrder", referencedColumnName="idOrder"),
#JoinColumn(name="ItemNumber", referencedColumnName="ItemNumber")
})
//#JoinColumn(name = "idOrder", referencedColumnName = "idOrder", insertable = false, updatable = false)
private CustomerOrder customerOrder;
private CustomerOrder customerOrder;
public OrderItem() {
this.orderItemPK = new OrderItemPK();
}
}
#Embeddable
public class OrderItemPK implements Serializable {
#Basic(optional = false)
#Column(name = "idOrder")
private int idOrder;
#Basic(optional = false)
#Column(name = "itemNumber")
private int itemNumber;
public OrderItemPK() {
}
}
The test Source:
public static void main(String[] args) {
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();
// Fill the items fileds
OrderItem item = new OrderItem();
item.setItemDesc("Item Text");
// Fill the orders fields
CustomerOrder order = new CustomerOrder();
order.setOrderText("Order text");
// Fill the relationship fields
order.getOrderItemCollection().add(item);
item.setCustomerOrder(order);
em.persist(order);
em.getTransaction().commit();
}
I have no idea what I'm doing wrong, any suggestions are welcome.
Well i managed to solve the problem by removing idClass annotation and adding the #MapId
heres the final code:
#Entity
#Table(name = "Orders")
public class CustomerOrder implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "idOrder")
private Integer idOrder;
#Basic(optional = false)
#Column(name = "orderText")
private String orderText;
#OneToMany(mappedBy = "customerOrder", cascade = CascadeType.ALL)
private Collection<OrderItem> orderItemCollection;
public CustomerOrder() {
}
#Entity
#Table(name = "OrdersItems")
public class OrderItem implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected OrderItemPK orderItemPK;
#Basic(optional = false)
#Column(name = "itemDesc")
private String itemDesc;
#MapsId("idOrder")
#ManyToOne(optional = false)
#JoinColumn(name = "idOrder", referencedColumnName = "idOrder", nullable = false)
private CustomerOrder customerOrder;
public OrderItem() {
this.orderItemPK = new OrderItemPK();
}
#Embeddable
public class OrderItemPK implements Serializable {
#Basic(optional = false)
#Column(name = "idOrder")
private int idOrder;
#Basic(optional = false)
#Column(name = "itemNumber")
private int itemNumber;
public OrderItemPK() {
}
public static void main(String[] args) {
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();
// Fill the order item
OrderItem item = new OrderItem();
item.getOrderItemPK().setItemNumber(1);
item.setItemDesc("Product Name");
// Fill the order
CustomerOrder order = new CustomerOrder();
order.setOrderText("Testing");
// Create relationship
order.getOrderItemCollection().add(item);
item.setCustomerOrder(order);
// Persist
em.persist(order);
em.getTransaction().commit();
}
But i can't get it work with IdClass, here's the source
#Embeddable
public class OrderItemPK implements Serializable {
#Basic(optional = false)
#Column(name = "idOrder")
private Integer idOrder;
#Basic(optional = false)
#Column(name = "ItemNumber")
private Integer itemNumber;
public OrderItemPK() {
}
#Entity
#IdClass(OrderItemPK.class)
public class OrderItem implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "itemNumber")
private Integer itemNumber;
#Basic(optional = false)
#Column(name = "itemDesc")
private String itemDesc;
#MapsId("idOrder")
#ManyToOne(optional = false)
#JoinColumn(name = "idOrder", referencedColumnName = "idOrder", nullable = false)
private CustomerOrder customerOrder;
public OrderItem() {
}
#Entity
public class CustomerOrder implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "idOrder")
private Integer idOrder;
#Basic(optional = false)
#Column(name = "OrderText")
private String orderText;
#OneToMany(mappedBy = "customerOrder", cascade = CascadeType.ALL)
private Collection<OrderItem> orderItemCollection;
public CustomerOrder() {
this.orderItemCollection = new ArrayList();
}
Use MapsId in OrderItem:
#Entity
public class OrderItem implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected OrderItemPK orderItemPK;
#Basic(optional = false)
#Column(name = "itemDesc")
private String itemDesc;
#MapsId("idOrder")
#ManyToOne(optional = false)
#JoinColumn(name = "idOrder", referencedColumnName = "idOrder")
private CustomerOrder customerOrder;
}
An alternative is to remove the embedded id and use an ID class:
#Entity
#IdClass(OrderItemPK.class)
public class OrderItem implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "itemNumber")
private int itemNumber;
#Basic(optional = false)
#Column(name = "itemDesc")
private String itemDesc;
#Id
#ManyToOne(optional = false)
#JoinColumn(name = "idOrder", referencedColumnName = "idOrder")
private CustomerOrder customerOrder;
}
public class OrderItemPK implements Serializable {
//name of the relation in the entity, but same type as the CustomerOrder PK.
int customerOrder;
int itemNumber;
public OrderItemPK() {
}
}