Spring JPA, stackoverflow about ManyToMany - java

I have a ManyToMany relation between EXPERIENCE and COMPETENCE_LEVEL.
I tried:
PROFIL.java:
#Entity
#Table(name="profil")
public class Profil {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="id_profil")
private Long idProfil;
public Profil() {
super();
}
public Long getIdProfil() {
return idProfil;
}
public void setIdProfil(Long idProfil) {
this.idProfil = idProfil;
}
#Override
public String toString() {
//[...]
}
}
EXPERIENCE.java:
#Entity
#Table(name="experience")
public class Experience {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="id_experience")
private Long idExperience;
#ManyToOne
#JoinColumn(name="id_profil")
private Profil idProfil;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "experience_competence_level", joinColumns = #JoinColumn(name = "id_experience", referencedColumnName = "id_experience"), inverseJoinColumns = #JoinColumn(name = "id_competence_level", referencedColumnName = "id_competence_level"))
private List<CompetenceLevel> competenceLevels;
public Experience() {
super();
idProfil = new Profil();
}
public Long getIdExperience() {
return idExperience;
}
public void setIdExperience(Long idExperience) {
this.idExperience = idExperience;
}
public Profil getIdProfil() {
return idProfil;
}
public void setIdProfil(Profil idProfil) {
this.idProfil = idProfil;
}
public List<CompetenceLevel> getCompetenceLevels() {
return competenceLevels;
}
public void setCompetenceLevels(List<CompetenceLevel> competenceLevels) {
this.competenceLevels = competenceLevels;
}
#Override
public String toString() {
// [...]
}
}
COMPETENCE_LEVEL.java:
#Entity
#Table(name="competence_level")
public class CompetenceLevel {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="id_competence_level")
private Long idCompetenceLevel;
#OneToOne
#JoinColumn(name="id_level")
private Level level;
#OneToOne
#JoinColumn(name="id_profil")
private Profil profil;
#ManyToMany(mappedBy = "competenceLevels")
private List<Experience> experiences;
public CompetenceLevel() {
super();
}
public Long getIdCompetenceLevel() {
return idCompetenceLevel;
}
public void setIdCompetenceLevel(Long idCompetenceLevel) {
this.idCompetenceLevel = idCompetenceLevel;
}
public Level getLevel() {
return level;
}
public void setLevel(Level level) {
this.level = level;
}
public Profil getProfil() {
return profil;
}
public void setProfil(Profil profil) {
this.profil = profil;
}
public List<Experience> getExperiences() {
return experiences;
}
public void setExperiences(List<Experience> experiences) {
this.experiences = experiences;
}
#Override
public String toString() {
// [...]
}
}
When I launch a web service which trying to get all my EXPERIENCE, my execution is freezing and it's feels like a stackoverflow issue (i'm not an expert) :/.
But, if I remove the List in CompetenceLevel class, it's working.
I don't understand why. I follow this tuto : https://hellokoding.com/jpa-many-to-many-relationship-mapping-example-with-spring-boot-maven-and-mysql/
Do you have an idea ? Thanks.

Related

Are entities relationship correct?

In my project I try yo use Spring data Jpa. My find methods(findById, findAll) works correctly, but delete and save method works with problems. Delete method delete only from duck table. Save doesn't work:
Exception in thread "main" org.springframework.orm.jpa.JpaObjectRetrievalFailureException: Unable to find springdata.entities.FrogJpa with id 2; nested exception is javax.persistence.EntityNotFoundException: Unable to find springdata.entities.FrogJpa with id 2
I have 2 entities: Frog and Duck. Every ducks have 1 Frog(OneToOne). There are problems with entities relationship?
There are my entities class:
#Entity
#Table(name = "DUCKS")
public class DuckJpa implements Serializable {
#Id
private int id;
#Column(name = "NAME")
private String name;
#Column(name = "FLY")
private String flyBehavior;
#Column(name = "QUACK")
private String quackBehavior;
#OneToOne(optional = false)
#JoinColumn(name = "FROG_ID", unique = true, nullable = false, updatable = false)
private FrogJpa frogJpa;
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setFlyBehavior(String flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(String quackBehavior) {
this.quackBehavior = quackBehavior;
}
public void setFrogJpa(FrogJpa frogJpa) {
this.frogJpa = frogJpa;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getFlyBehavior() {
return flyBehavior;
}
public String getQuackBehavior() {
return quackBehavior;
}
public FrogJpa getFrogJpa() {
return frogJpa;
}
And Frog:
#Entity
#Table(name = "FROGS")
public class FrogJpa {
#OneToOne(optional = false, mappedBy = "frogJpa")
private DuckJpa duckJpa;
#Id
private int id;
#Column(name = "name")
private String name;
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setDuckJpa(DuckJpa duckJpa) {
this.duckJpa = duckJpa;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public DuckJpa getDuckJpa() {
return duckJpa;
}
}
My service class:
public interface DuckService {
List<DuckJpa> findAll();
Optional<DuckJpa> findById(Integer i);
DuckJpa save(DuckJpa duckJpa);
void delete(DuckJpa duckJpa);
}
And it's implementation:
#Service("springJpaDuckService")
#Transactional
public class DuckServiceImpl implements DuckService {
#Autowired
private DuckJpaRepository duckJpaRepository;
#Transactional(readOnly = true)
public List<DuckJpa> findAll() {
return new ArrayList<>(duckJpaRepository.findAll());
}
#Override
public Optional<DuckJpa> findById(Integer i) {
return duckJpaRepository.findById(i);
}
#Override
public DuckJpa save(DuckJpa duckJpa) {
duckJpaRepository.save(duckJpa);
return duckJpa;
}
#Override
public void delete(DuckJpa duckJpa) {
duckJpaRepository.delete(duckJpa);
}
Use #OneToOne(cascade=CascadeType.ALL, fetch = FetchType.LAZY).
For more information please refer What is cascading in Hibernate?

A Foreign key refering has the wrong number of column. should be 2

Here is my code
VirsualPerson
public class VirsualPerson extends Person{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#PrimaryKeyJoinColumn(name="VIRSUALPERSON_ID")
private long virsualPersonId;
#ManyToMany(fetch=FetchType.LAZY,cascade=CascadeType.ALL)
#JoinTable(name="Anime_character",catalog="anime",joinColumns={
#JoinColumn(name="VIRSUALPERSON_ID",nullable=false)},inverseJoinColumns={#JoinColumn(name="ANIME_ID",nullable=false)})
private Set<Anime>animeCharacters=new HashSet<Anime>();
#OneToMany(fetch=FetchType.LAZY,mappedBy="charecter")
private Set<VirsualPeopleComment>comments=new HashSet<VirsualPeopleComment>();
public long getVirsualPersonId() {
return virsualPersonId;
}
public void setVirsualPersonId(long virsualPersonId) {
this.virsualPersonId = virsualPersonId;
}
public Set<Anime> getAnimeCharacters() {
return animeCharacters;
}
public void setAnimeCharacters(Set<Anime> animeCharacters) {
this.animeCharacters = animeCharacters;
}
public Set<VirsualPeopleComment> getComments() {
return comments;
}
public void setComments(Set<VirsualPeopleComment> comments) {
this.comments = comments;
}
}
VirsualPersonComment
#Entity
#Table(name="people_comment")
public class VirsualPeopleComment {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="peopleCommentId")
private long commentId;
#Column(name="content")
private String commentContent;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="POST_TIME")
private Date postTime;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="USER_ID")
private User commentUser;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="VIRSUALPERSON_ID")
private VirsualPerson charecter;
public long getCommentId() {
return commentId;
}
public void setCommentId(long commentId) {
this.commentId = commentId;
}
public String getCommentContent() {
return commentContent;
}
public void setCommentContent(String commentContent) {
this.commentContent = commentContent;
}
public Date getPostTime() {
return postTime;
}
public void setPostTime(Date postTime) {
this.postTime = postTime;
}
public User getCommentUser() {
return commentUser;
}
public void setCommentUser(User commentUser) {
this.commentUser = commentUser;
}
public VirsualPerson getCharecter() {
return charecter;
}
public void setCharecter(VirsualPerson charecter) {
this.charecter = charecter;
}
}
And here is the error
A Foreign key refering VirsualPerson from VirsualPeopleComment has the wrong number of column. should be 2
I want to know what's wrong with my annotations and thanks a lot
I guess you should specify #JoinColumn here as well:
#OneToMany(fetch=FetchType.LAZY,mappedBy="charecter")
private Set<VirsualPeopleComment>comments=new HashSet<VirsualPeopleComment>();
looks like it should be
#OneToMany(fetch=FetchType.LAZY,mappedBy="charecter")
#JoinColumn(name="peopleCommentId")
private Set<VirsualPeopleComment>comments=new HashSet<VirsualPeopleComment>();

MySQLIntegrityConstraintViolationException: column "question_id" cannot be null error

i have two entity classes named Qa.java and Answeres.java
my Qa entity consists of lists of answers.
Qa.Java
#Entity
#Table(name = "qa")
public class Qa {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
private String question;
private String type;
private String description;
private String param;
private int maxlength;
#OneToMany(mappedBy = "qa", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<Answers> answersList = new ArrayList<>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getQuestion() {
return question;
}
public void setQuestion(String question) {
this.question = question;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getParam() {
return param;
}
public void setParam(String param) {
this.param = param;
}
public int getMaxlength() {
return maxlength;
}
public void setMaxlength(int maxlength) {
this.maxlength = maxlength;
}
public List<Answers> getAnswersList() {
return answersList;
}
public void setAnswersList(List<Answers> answersList) {
this.answersList = answersList;
}
}
Answers.java
#Entity
#Table(name = "answers")
public class Answers {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String ans_label;
private int ans_value;
private int ans_weightage;
private int is_default;
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "question_id", referencedColumnName = "id",nullable = false)
private Qa qa;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAns_label() {
return ans_label;
}
public void setAns_label(String ans_label) {
this.ans_label = ans_label;
}
public int getAns_value() {
return ans_value;
}
public void setAns_value(int ans_value) {
this.ans_value = ans_value;
}
public int getAns_weightage() {
return ans_weightage;
}
public void setAns_weightage(int ans_weightage) {
this.ans_weightage = ans_weightage;
}
public int getIs_default() {
return is_default;
}
public void setIs_default(int is_default) {
this.is_default = is_default;
}
public Qa getQa() {
return qa;
}
public void setQa(Qa qa) {
this.qa = qa;
}
}
My controller from where i am trying to insert data.
TableDataController.java
#Controller
public class TabletDataController {
#Autowired
QaRepository qaRepository;
#RequestMapping(value = "/saveApiData", method = RequestMethod.GET)
public void saveApiData(){
Qa qa = new Qa();
qa.setParam("");
qa.setType("input_spinner");
qa.setDescription("");
qa.setQuestion("व्यक्तिको पहिलो नाम ?");
ArrayList<Answers> answersArrayList = new ArrayList<>();
Answers answers = new Answers();
answers.setAns_label("नेपाली");
answers.setAns_value(1);
answers.setAns_weightage(0);
answers.setIs_default(0);
answersArrayList.add(answers);
qa.setAnswersList(answersArrayList);
qaRepository.save(qa);
}
}
my qaRepository extends JpaRepository. so whenever i call this api i get an error of com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'question_id' cannot be null
what am i doing wrong?
You have a bidirectional OneToMany relationship, so you need to manually maintain both sides of the relationship. Here you are only setting the Qa side with qa.setAnswersList(answersArrayList);
You need to set the other side of your relationship manually. add:
answers.setQa(qa);
before you save your list
code as follow
public void saveApiData(){
Qa qa = new Qa();
qa.setParam("");
qa.setType("input_spinner");
qa.setDescription("");
qa.setQuestion("व्यक्तिको पहिलो नाम ?");
ArrayList<Answers> answersArrayList = new ArrayList<>();
Answers answers = new Answers();
answers.setAns_label("नेपाली");
answers.setAns_value(1);
answers.setAns_weightage(0);
answers.setIs_default(0);
answers.setQa(qa);
answersArrayList.add(answers);
qa.setAnswersList(answersArrayList);
qaRepository.save(qa);
}
when you save.you should Cascade save.Your annotations configure the relationship of the associated tables but also to associate them when they are saved

Cannot remove object list in java spring

my code is :
List<Session> futureSessions = this.getFutureSession(group.getSessions());
for (Session session: futureSessions) {
Boolean exists = false;
for (SessionDTO sessionDTO: groupDTO.getSessions()) {
if (session.getId() == sessionDTO.getId()) {
exists = true;
}
}
if(false == exists) {
// sessionService.delete(session);
group.getSessions().remove(session);
} else {
exists = false;
}
} Group groupUpdated = groupService.save(group);
This part of code is for remove object (session) into my group object. I use java spring for dilog between angular and java.
I have a relationship between this 2 objects and before save my group object i look for if my session groupServive.save(group) my sessions are not removed from database.
Any help will be very appreciate !
Here is my group model :
`#Entity
#Table(name = "t_group")
public class Group implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private Boolean actif;
private Boolean deleted;
private Enterprise enterprise;
private String avatar;
private Date date_creation;
private Date date_update;
private Integer version;
private Set<User> users;
private List<Rule> rules;
private List<Session> sessions;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Column(nullable = false, unique = true)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Column(nullable = false)
public Boolean getActif() {
return actif;
}
public void setActif(Boolean actif) {
this.actif = actif;
}
#Column(nullable = false)
public Boolean getDeleted() {
return deleted;
}
public void setDeleted(Boolean deleted) {
this.deleted = deleted;
}
#ManyToOne
#JoinColumn(name = "t_enterprise", nullable = true)
public Enterprise getEnterprise() {
return enterprise;
}
public void setEnterprise(Enterprise enterprise) {
this.enterprise = enterprise;
}
#Lob
#Column(columnDefinition = "LONGTEXT")
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
public Date getDate_creation() {
return date_creation;
}
public void setDate_creation(Date date_creation) {
this.date_creation = date_creation;
}
public Date getDate_update() {
return date_update;
}
public void setDate_update(Date date_update) {
this.date_update = date_update;
}
#ManyToMany
#JoinTable(name = "t_user_group", joinColumns = {
#JoinColumn(name = "t_group", nullable = false) },
inverseJoinColumns = { #JoinColumn(name = "t_user") })
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
#OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="group")
public List<Rule> getRules() {
return rules;
}
public void setRules(List<Rule> rules) {
this.rules = rules;
}
#OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="group")
public List<Session> getSessions() {
return sessions;
}
public void setSessions(List<Session> sessions) {
this.sessions = sessions;
}
#Version
#Column(nullable = false)
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
#PreUpdate
private void setLastUpdate() {
this.setDate_update(new Date());
}
#PrePersist
private void setFirstCreationDate() {
this.setLastUpdate();
if(null == this.getDate_creation()){
this.setDate_creation(new Date());
}
}
`
ok, the solution was only to add a method in my sessionDAO
`
#Override
public void delete(Session session) {
// repository.delete(session);
if (session.getId() > 0) {
query = em.createNativeQuery("DELETE FROM `t_session` WHERE `id` = :t_session", Session.class);
query.setParameter("t_session", session.getId());
query.executeUpdate();
}
}`

hibernate association with n levels

I have two tables (ProspectMaster,ProspectContactsMaster). to maintain a relationship, I made a mapping table(ProspectContactsMap) using an embeddable entity(ProspectContactsMapID). Bellow are the all entities
#Entity
public class ProspectMaster {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int prospectID;
#Column(nullable=false)
#Length(max = 50)
private String companyName;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "prospectContactsMapID.prospectMaster", cascade=CascadeType.ALL)
private Set<ProspectContactsMap> prospectContactsMap = new HashSet<ProspectContactsMap>(0);
public int getProspectID() {
return prospectID;
}
public void setProspectID(int prospectID) {
this.prospectID = prospectID;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public Set<ProspectContactsMap> getProspectContactsMap() {
return prospectContactsMap;
}
public void setProspectContactsMap(Set<ProspectContactsMap> prospectContactsMap) {
this.prospectContactsMap = prospectContactsMap;
}
}
#Entity
public class ProspectContactsMaster {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int prospectContactID;
#Length(max = 25)
private String firstName;
public int getProspectContactID() {
return prospectContactID;
}
public void setProspectContactID(int prospectContactID) {
this.prospectContactID = prospectContactID;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
#Entity
#AssociationOverrides({
#AssociationOverride(name = "prospectContactsMapID.prospectMaster",
joinColumns = #JoinColumn(name = "prospectID")),
#AssociationOverride(name = "prospectContactsMapID.prospectContactsMaster",
joinColumns = #JoinColumn(name = "prospectContactID")) })
public class ProspectContactsMap {
#EmbeddedId
private ProspectContactsMapID prospectContactsMapID = new ProspectContactsMapID();
private int isMainContact;
#Transient
public ProspectMaster getProspectMaster() {
return this.getProspectContactsMapID().getProspectMaster();
}
public void setProspectMaster(ProspectMaster prospectMaster) {
getProspectContactsMapID().setProspectMaster(prospectMaster);
}
#Transient
public ProspectContactsMaster getProspectContactsMaster() {
return this.getProspectContactsMapID().getProspectContactsMaster();
}
public void setProspectContactsMaster(ProspectContactsMaster prospectContactsMaster) {
getProspectContactsMapID().setProspectContactsMaster(prospectContactsMaster);
}
public ProspectContactsMapID getProspectContactsMapID() {
return prospectContactsMapID;
}
public void setProspectContactsMapID(ProspectContactsMapID prospectContactsMapID) {
this.prospectContactsMapID = prospectContactsMapID;
}
public int getIsMainContact() {
return isMainContact;
}
public void setIsMainContact(int isMainContact) {
this.isMainContact = isMainContact;
}
}
#Embeddable
public class ProspectContactsMapID implements Serializable {
#ManyToOne
private ProspectMaster prospectMaster;
#ManyToOne
private ProspectContactsMaster prospectContactsMaster;
public ProspectMaster getProspectMaster() {
return prospectMaster;
}
public void setProspectMaster(ProspectMaster prospectMaster) {
this.prospectMaster = prospectMaster;
}
public ProspectContactsMaster getProspectContactsMaster() {
return prospectContactsMaster;
}
public void setProspectContactsMaster(ProspectContactsMaster prospectContactsMaster) {
this.prospectContactsMaster = prospectContactsMaster;
}
}
now my requirement is to fetch all prospect having company name starts with d or having main contacts starts with d. I have made a query, but in n level I can not provide association property. Bellow is my query
Disjunction disjOrCondition = Restrictions.disjunction();
Criteria cr = getCurrentSession().createCriteria(ProspectMaster.class);
cr.createAlias("prospectContactsMap", "prospectContact");
Criterion thirdCondition = Restrictions.conjunction().add(Restrictions.eq("prospectContact.isMainContact",1))
.add(Restrictions.like("prospectContact.prospectContactsMapID.prospectContactsMaster.firstName", searchVal.toString(),MatchMode.ANYWHERE));
disjOrCondition.add(Restrictions.like("companyName", searchVal.toString(),MatchMode.ANYWHERE));
disjOrCondition.add(thirdCondition);
if I run this, I get bellow exception
org.hibernate.QueryException: could not resolve property: prospectContactsMapID.prospectContactsMaster.firstName
can anyone please tell me where is the problem? and can anyone tell me any example on same. I want to use hql only.
From what I know I just can tell you 2 things:
you can try another fetching strategy; instead of LAZY you could try EAGER
there is a property in the configuration file: hibernate.max_fetch_depth, but i guess you are using the default. It sets the maximum depth for a single-ended asociation.

Categories