"Select all Documents from one content" hibernate relationship many to many - java

I have tow models:
#Entity
public class Documento implements java.io.Serializable {
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
private Integer id;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "appc_contenido_documento", catalog = "appcope",
joinColumns = {
#JoinColumn(name = "id_documento", nullable = false, updatable =
false)}, inverseJoinColumns = {
#JoinColumn(name = "id_contenido", nullable = false, updatable =
false)})
private Set<Contenido> contenidos = new HashSet<Contenido>(0);
}
and
#Entity
public class Contenido implements java.io.Serializable {
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
private Integer id;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "appc_contenido_documento", catalog = "appcope",
joinColumns = {
#JoinColumn(name = "id_contenido", nullable = false, updatable =
false)}, inverseJoinColumns = {
#JoinColumn(name = "id_documento", nullable = false, updatable =
false)})
private Set<Documento> documentos = new HashSet<Documento>(0);
}
I don´t find an example this, only I find examples with relationship one to many
How can I select all the documents of a content with CriteriaQuery?

It is usually a good idea to reduce your many to many relationship to one to many. This usually can be done by introducing a bridging entity. It maybe worth adding such a table here.

Related

#ManyToOne in self-referencing entity with composite key - #IdClass, java, hibernate

Spent 3 days looking for a solution and finally I came here for community wisdom.
I have self-referencing entity like follows:
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#Entity
#IdClass(CompositeUserId.class)
#Table(name = "user", schema = "dbo")
public class User implements Serializable {
#Id
#Column(name = "id")
private Integer id;
#Id
#Column(name = "first_name")
private String firstName;
#Id
#Column(name = "last_name")
private String lastName;
#ManyToOne
#JoinColumn(name = "parent_id", referencedColumnName = "id", insertable = false, updatable = false)
#JoinColumn(name = "first_name", referencedColumnName = "first_name", insertable = false, updatable = false)
#JoinColumn(name = "last_name", referencedColumnName = "last_name", insertable = false, updatable = false)
private User parent;
#OneToMany(mappedBy = "parent", fetch = FetchType.EAGER)
private Set<User> children;
my CompositeUserId.class:
#Getter
#Setter
#EqualsAndHashCode
#AllArgsConstructor
#NoArgsConstructor
public class UserCompositeId implements Serializable {
private Integer id;
private String firstName;
private String lastName;
When I try retrieve all data from my user table I get error:
org.springframework.orm.jpa.JpaObjectRetrievalFailureException: Unable to find ...User with id UserCompositeId#19e66569; nested exception is javax.persistence.EntityNotFoundException:
I suppose there might be some kind of mistake in the #JoinColumn block.
Here is the sql query causing the error:
SELECT *
FROM dbo.user ur1 LEFT OUTER JOIN dbo.user ur2 ON ur1.first_name=ur2.first_name AND ur1.parent_id=ur2.id AND ur1.last_name=ur2.last_name
WHERE ur1.first_name='First Name' AND ur1.id=130 AND ur1.last_name='Last Name'
I ensured that the request does not return anything in the database by running it manually, but found out that if I will change id to parent_id it will return data, so again, probably some mistake in #JoinColumn block
You need you use #NotFound(action=NotFoundAction.IGNORE). If there is no records then it will assign null to it.
#ManyToOne
#JoinColumn(name = "parent_id", referencedColumnName = "id", insertable = false, updatable = false)
#JoinColumn(name = "first_name", referencedColumnName = "first_name", insertable = false, updatable = false)
#JoinColumn(name = "last_name", referencedColumnName = "last_name", insertable = false, updatable = false)
#NotFound(action=NotFoundAction.IGNORE)
private User parent;
The foreign key columns need different names than the primary key columns, e.g. like this (notice the 'parent' prefix in name):
#JoinColumn(name = "parent_id", referencedColumnName = "id", updatable = false, insertable = true)
#JoinColumn(name = "parent_firstname", referencedColumnName = "firstname", updatable = false, insertable = true)
#JoinColumn(name = "parent_lastname", referencedColumnName = "lastname", updatable = false, insertable = true)
#ManyToOne(fetch = FetchType.EAGER)
private UserEntity parent;
Additionally, the insertable value should be true, since otherwise no associations are persisted during the insert.
Be aware that a parent needs to be saved before a child can be associated. Since the parent fk is not updatable, is must be set on a newly created child before it is saved.
Feel free to have a look at this project containing the complete sample code:
Entity:
https://github.com/fladdimir/many-to-one-self-ref-composite-id/blob/master/src/main/java/org/demo/UserEntity.java
Integration-Test:
https://github.com/fladdimir/many-to-one-self-ref-composite-id/blob/master/src/test/java/org/demo/DemoApplicationTests.java
Also it is good practice to synchronize bidirectional associations:
https://vladmihalcea.com/jpa-hibernate-synchronize-bidirectional-entity-associations/
The sample entity could e.g. use some methods like these:
public void addChild(UserEntity child) {
child.parent = this; // sync owning side of the association
this.children.add(child);
}
public void setParent(UserEntity parent) {
parent.addChild(this);
}

org.postgresql.util.PSQLException: ERROR: null value in column "category_id" violates not-null constraint

i have a weird issue : i'am trying to save a User in my DB, this user has a list of skills. those skills are already in the db with linked categories and categories have linked domains. the structure looks like this :
when i print the list of skills from the applicant i have this :
skills=[Skill{categories=[Category{domains=[Domain{id=4, name=DevOps}], id=13, name=BackEnd}], id=23, name=Java}, Skill{categories=[Category{domains=[Domain{id=4, name=DevOps}], id=13, name=BackEnd}], id=24, name=C}],
and here is the table making the link between Applicant and skills :
but when i'm trying to save the applicant i have this Détail : Failing row contains (23, null, null, 499). can someone explain me ? I'm working on a spring application using jpa annotaions.
EDIT 1 :
ApplicantEntity :
#Entity
#Table(name = "ATS_APPLICANT")
public class ApplicantEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "home", unique = false, nullable = true)
private Boolean home;
#Column(name = "anonymous", unique = false, nullable = true)
private Boolean anonymous;
#Enumerated(EnumType.STRING)
#Column(name = "job_type")
private JobType jobType;
#Column(name = "min_salary", unique = false, nullable = true)
private Integer minSalary;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(unique = true)
private UserEntity user;
#OneToMany(targetEntity = ApplicantWorkExperienceEntity.class, cascade = CascadeType.ALL)
private List<ApplicantWorkExperienceEntity> applicantWorkExperiences = new ArrayList<ApplicantWorkExperienceEntity>();
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.MERGE)
#JoinTable(name = "ATS_APPLICANT_SKILL", joinColumns = #JoinColumn(name = "applicant_id", referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "skill_id", referencedColumnName = "id"))
private List<SkillEntity> skills = new ArrayList<SkillEntity>();
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "ATS_APPLICANT_LOCATION", joinColumns = #JoinColumn(name = "applicant_id", referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "location_id", referencedColumnName = "id"))
private List<LocationEntity> locations = new ArrayList<LocationEntity>();
SkillEntity :
#Entity
#Table(name = "ATS_SKILL")
public class SkillEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#NotNull
#Size(min = 1, max = 42)
#Column(name = "name", length = 42, nullable = false, unique = true)
private String name;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(name = "ATS_SKILL_CATEGORY", joinColumns = #JoinColumn(name = "skill_id", referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "category_id", referencedColumnName = "id"))
private List<CategoryEntity> categories = new ArrayList<CategoryEntity>();
CategoryEntity :
#Entity
#Table(name = "ATS_CATEGORY")
public class CategoryEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#NotNull
#Size(min = 1, max = 42)
#Column(name = "name", length = 42, nullable = false, unique = true)
private String name;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(name = "ATS_CATEGORY_DOMAIN", joinColumns = #JoinColumn(name = "category_id", referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "domain_id", referencedColumnName = "id"))
private List<DomainEntity> domains = new ArrayList<DomainEntity>();
EDIT 2 :
DomainEntity :
#Entity
#Table(name = "ATS_DOMAIN")
public class DomainEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#NotNull
#Size(min = 1, max = 42)
#Column(name = "name", length = 42, nullable = false, unique = true)
private String name;
I succeed by using #ElementCollection annotation on skills.

JoinColumn to an foreign key

I'm trying to achieve this with hibernate:
My codes is as follows:
Device model
#Entity
public class Device {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(nullable = false)
private long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "fk_user", nullable = true, referencedColumnName = "ID")
private User user;
...
}
Statistics model
#Entity
public class Statistic {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(nullable = false)
private long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns({ #JoinColumn(name = "fk_device", nullable = false, referencedColumnName = "ID"),
#JoinColumn(name = "fk_device_user", nullable = false, referencedColumnName = "fk_user") })
private Device device;
...
}
However, there's an error saying there's no logical column fk_user in device.
Caused by: org.hibernate.MappingException: Unable to find column with logical name: fk_user in device
I suppose it is because fk_user is a foreign key. But how can I solve this? Thanks.
Based on you schema i would map the Device entity as follows:
public class Devince{
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id", nullable = true)
private User user;
...
}
}
You dont need the referencedColumnName as you are referring to the User entity primary key. If you would refer to non-primary key column, then that would be necessary.
Regarding the Statistic entity:
public class Statistic {
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns({ #JoinColumn(name = "device_id", nullable = false),
#JoinColumn(name = "device_user_id", nullable = false,
referencedColumnName = "user_id") })
...
}
}
Again, you only need the referencesColumnName in the second #JoinColumn.

Can we have a #OneToMany and #ManyToOne relationship between two tables in hibernate?

Eg.
public class Portfolio implements Serializable {
#ManyToOne()
#JoinColumn(name = "PORTFOLIO_OWNER", referencedColumnName = "USER_ID", foreignKey = #ForeignKey(name = "FK__USER__PORTFOLIO"), nullable = false)
private User portfolioOwner;
#ManyToOne()
#JoinColumn(name = "ACCOUNT_CAPTAIN", referencedColumnName = "USER_ID", foreignKey = #ForeignKey(name = "FK__USER__PORTFOLIO2"))
private User accountCaptain;
}
and
public class User {
#ManyToOne
#JoinColumn(name = "PORTFOLIO_ID", referencedColumnName = "PORTFOLIO_ID", foreignKey = #ForeignKey(name = "FK_DEF_PORTFOLIO_USER"))
#Fetch(FetchMode.JOIN)
private Portfolio defaultPortfolio;
}
I run into Stackoverflow on fetching them using JACKSON as a JSON
org.springframework.http.converter.HttpMessageNotWritableException:
Could not write content: Infinite recursion (StackOverflowError)
(through reference chain:
com.User["defaultPortfolio"]->com..Portfolio["portfolioOwner"]->com.User["defaultPortfolio"]->com.Portfolio["portfolioOwner"]->com..User["defaultPortfolio"]-
you need to add json ignore to one side of the relations ex:
public class Portfolio implements Serializable {
#ManyToOne()
#JoinColumn(name = "PORTFOLIO_OWNER", referencedColumnName = "USER_ID", foreignKey = #ForeignKey(name = "FK__USER__PORTFOLIO"), nullable = false)
#JsonIgnore
private User portfolioOwner;
#ManyToOne()
#JoinColumn(name = "ACCOUNT_CAPTAIN", referencedColumnName = "USER_ID", foreignKey = #ForeignKey(name = "FK__USER__PORTFOLIO2"))
private User accountCaptain;
}

Hibernate many-to-many mapping referencing partial composite key

My problem is like this one: https://forum.hibernate.org/viewtopic.php?f=1&t=1002125
I have the following tables in my schema:
a table A with a composite key (attr1, attr2);
a table B with a pk (attr3);
and a table A_B which is a relationship table between A and B with a composite key (fk_attr1, fk_attr3), where fk_attr1 and fk_attr3 references the fields attr1 and attr2, respectively
The attr2 is not used in the relationship.
I generated the mapping java classes with hibernate plugin, and the generated code looks like this:
class A
private Set<B> bs = new HashSet<B>(0);
private AId id;
#EmbeddedId
#AttributeOverrides({ #AttributeOverride(name = "attr1", column = #Column(name = "attr1", nullable = false)),
#AttributeOverride(name = "attr2", column = #Column(name = "attr2", nullable = false)) })
public AId getId() {
return this.id;
}
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "A_B", catalog = "my_schema", joinColumns = { #JoinColumn(name = "fk_attr1", nullable = false, updatable = false) }, inverseJoinColumns = { #JoinColumn(name = "fk_attr3", nullable = false, updatable = false) })
public Set<B> getBs() {
return this.bs;
}
class B
private Set<A> as = new HashSet<A>(0);
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "A_B", catalog = "my_schema", joinColumns = { #JoinColumn(name = "fk_attr3", nullable = false, updatable = false) }, inverseJoinColumns = { #JoinColumn(name = "fk_attr1", nullable = false, updatable = false) })
public Set<A> getAs() {
return this.as;
}
class AId (the id for entity A)
private String attr1;
private Long attr2;
#Column(name = "attr1", nullable = false)
public String getAttr1() {
return this.attr1;
}
#Column(name = "attr2", nullable = false)
public Long getAttr2() {
return this.attr2;
}
But it always generates this exception:
org.hibernate.AnnotationException: A Foreign key refering A from B has the wrong number of column. should be 2
What is the right way to accomplish this relationship with Hibernate?

Categories