I have a problem when cascade deleting my Parent entity:
org.postgresql.util.PSQLException: UPDATE or DELETE on table "child" violates constraint "XXX": for key (id)=(4) there are references in table "child_properties"
#Entity
#Table(name = "Parent")
public class Parent{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToMany(fetch = FetchType.EAGER,mappedBy = "parent")
#OnDelete(action = OnDeleteAction.CASCADE)
private Set<Child> children;
}
#Entity
#Table(name = "child")
public class Child{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne
#JoinColumn(name = "parent_id")
private Parent parent;
#ElementCollection(fetch = FetchType.EAGER)
private Map<String,String> properties;
}
I expected child to delete its properties on parentRepository.delete(parent)
but this only happens on childRepository.delete(child). parent delete throws exception
the solution was ~3 hours googling...
the idea is to set custom foreign key
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "child_properties"
,joinColumns = {
#JoinColumn(name = "child_id"
, referencedColumnName = "id"
,foreignKey=#ForeignKey(name="CHILD_PROPERTY_FK"
, foreignKeyDefinition = "FOREIGN KEY (child_id) references public.child (id) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE CASCADE"))
}
)
#MapKeyColumn(name = "name")
#Column(name = "value")
private Map<String,String> properties;
Related
I have a view which has a parent-child relationship. So I have my entity this way:
#Entity
#Table(name = "assessment_v", schema = "hlt_hrsc")
public class HrscLabellingAssessmentVEntity {
#Id
private String id;
#Column(name = "child_id")
private String childId;
#ManyToOne(cascade = {CascadeType.ALL})
#JoinColumn(name = "id")
private HrscLabellingAssessmentVEntity parent;
#OneToMany(mappedBy = "parent")
private Set<HrscLabellingAssessmentVEntity> child = new HashSet<>();
}
when I start my application it throws an error :
nested exception is org.hibernate.MappingException: Could not determine type for: java.util.Set
Please find the below image of the view for parent child eg:
id child_id
120.35871 120.35872
120.35872 null
Here 120.35872 is the parent record and 120.35871 is the child record. The parentId is maintained on the child_id column. My requirement is when I try to fetch the parent it should have the child records also.
what am I doing wrong??
Please check this example
#Entity
#Table(name = "assessment_v", schema = "hlt_hrsc")
public class HrscLabellingAssessmentVEntity {
#Id
private String id;
#Column(name = "child_id")
private String childId;
#JsonBackReference
#JoinColumn(name = "parent_id", referencedColumnName = "id")
#ManyToOne(fetch = FetchType.LAZY)
#Fetch(FetchMode.JOIN)
private HrscLabellingAssessmentVEntity parentId;
#JsonManagedReference
#OneToMany(mappedBy = "parentId", cascade = CascadeType.ALL)
private Set<HrscLabellingAssessmentVEntity> child = new HashSet<>();
}
I'm trying to make simple one to many relationship but hibernate is throwing error, no idea what to do.
Class Product:
public class Products {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#ManyToOne()
#JoinColumn(name = "user_id", foreignKey = #ForeignKey(name = "fk_user"))
private Users users;
}
and Class Users:
public class Users {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long Id;
#OneToMany()
#JoinColumn(name = "product_id", foreignKey = #ForeignKey(name = "fk_product_id"))
private List<Products> productsList = new ArrayList<>();
}
I got error: Error executing DDL "alter table products drop constraint fk_user" via JDBC Statement
Here is a working example of such relationship :
Drawer class :
#OneToMany (mappedBy="drawer", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE, orphanRemoval = true)
private Set<Pocket> pockets;
Pocket class :
#ManyToOne (fetch=FetchType.EAGER)
#JoinColumn(name = "id_drawer", nullable = false)
private Drawer drawer;
Since the foreign key is on the child side (Products class), you can drop it on the parent side and reference to child as being the owning side:
public class Users {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long Id;
#OneToMany(mappedBy="users")
private List<Products> productsList = new ArrayList<>();
}
I have an ClientUser entity with #OneToMany field customField:
#Entity
#Data
public class ClientUser {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private long id;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(
name = "client_user_custom_field",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "field_id", referencedColumnName = "id"))
private Collection<ClientFieldValue> customFields;
}
And a ClientFieldValue entity:
#Entity
#Data
public class ClientFieldValue {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private long id;
private String value;
}
How can I create ClientFieldValue's for all existing ClientUser?
I know that I can do smth like:
final Iterable<ClientUser> clientUsers = userRepository.findAll();
clientUsers.forEach(clientUser ->
clientUser.setCustomFields(Collections.singleton(new ClientFieldValue())));
userRepository.saveAll(clientUsers);
But I don't want to query all and save them after set.
Is there another way to do this?
I have 3 entities User, Order, Item with a mapping like this:
#Entity
public class Item {
#Id
#Access(AccessType.PROPERTY)
private long id; // item id predefined
//..getters and setters
}
#Entity
public class Client {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
//...getters and setters
}
#Entity
public class Order {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(nullable = false)
#Access(AccessType.PROPERTY)
private Long id;
#ManyToOne(optional = false, fetch = FetchType.LAZY, cascade = {
CascadeType.PERSIST, CascadeType.MERGE,
CascadeType.REFRESH, CascadeType.DETACH
})// without removing
//#JoinColumn(name = "client_id") - works fine
#JoinTable(name = "client_cr_order_cr_item",
joinColumns = #JoinColumn(name = "order_id"),
inverseJoinColumns = #JoinColumn(name = "client_id"))
private Client client;
#NotEmpty
#OneToMany(fetch = FetchType.LAZY, cascade = {
CascadeType.PERSIST, CascadeType.MERGE,
CascadeType.REFRESH, CascadeType.DETACH
})// without removing
#JoinTable(name = "client_cr_order_cr_item",
joinColumns = #JoinColumn(name = "order_id"),
inverseJoinColumns = #JoinColumn(name = "item_id"))
private List<Item> items;
//...getters and setters
}
When I persist order it fails with error:
ERROR: null value in column "item_id" violates not-null constraint
it generate query like this:
insert into client_cr_order_cr_item (client_id, order_id) values ()
i.e. it do not fill out segment_id field by some reason I don't know. But I refer to client not thru 3th table but using FK #JoinColumn(name = "client_id") , then it generate correct query:
insert into order_cr_item (order_id, item_id) values ()
Please, could you explain this behavior? Why mapping of client affect items? Is there any hint to make hibernate persists items to 3th table?
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (ravermeister.artist_recordlabel, CONSTRAINT FK_9dgdyft45droyopxsqijwb1dx FOREIGN KEY (artist_id) REFERENCES artist (id))
Artist class
#Entity
#Repository
#Data
#NoArgsConstructor(force = true)
public class Artist {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "artist_firstname")
private String artist_firstname;
#Column(name = "artist_secondname")
private String artist_secondname;
#Column(name = "artist_nickname")
private String artist_nickname;
#ManyToMany (fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
#JoinTable(name = "artist_recordlabel", joinColumns = #JoinColumn(name = "artist_id"),
inverseJoinColumns = #JoinColumn(name = "label_id"))
private Set<RecordLabel> recordLabels;
#ManyToMany (fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
#JoinTable (name = "artist_musicrelease", joinColumns = #JoinColumn (name = "artist_id"),
inverseJoinColumns = #JoinColumn (name = "musicrelease_id"))
private Set <MusicRelease> musicReleaseSet;
and RecordLabel class
#Entity
#Repository
#Data
#NoArgsConstructor(force = true)
public class RecordLabel {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "label_name")
private String label_name;
#Column(name = "label_country")
private String label_country;
#ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
#JoinTable(name = "artist_recordlabel", joinColumns = #JoinColumn(name = "label_id"),
inverseJoinColumns = #JoinColumn(name = "artist_id"))
private Set<Artist> artistsList;
Please follow this guide for a many-to-many relation
http://www.baeldung.com/hibernate-many-to-many
I think this error means that you are trying to insert/update into RecordLabel table a artist_id value that does not exist in Artist table.