JPA doubts about mapping #ManyToMany - java

Hi i am learning about #ManyToMany relationship mapping using JPA.
I more or less understand how it works, but i have a doubt. Let me show you first this code where i do some mapping:
#Entity
public class EntityE implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long eId;
#ManyToMany
#JoinTable(joinColumns =
#JoinColumn(name = "eId"), inverseJoinColumns =
#JoinColumn(name = "fId"))
private Collection<EntityF> entityFs;
//...
}
Also see this other entity:
#Entity
public class EntityF implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long fId;
private Collection<EntityE> entityEs;
//...
}
This is what i get in the database:
My doubts are:
-I want to create a #ManyToMany relationship where EntityE is the owner of the relationship, is this approach correct?
-I want the relationship to be unidirectional, so it is supposed to create just one mediator table called EntityB_EntityF. But for some reason it creates also a second table called EntityF_EntityE. I dont understand why is that?,Is that normal? and if not how should i fix it?

Ok i just got the answer after doing some little experiment.I think it is correct, it now works as i spected.
What i did was, add a name for the relationship, because for some strange reason if you don't specify the name it creates a bidirectional relationship.
See this code fixed it:
#Entity
public class EntityE implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long eId;
#ManyToMany
#JoinTable(name="entitye_entityf",joinColumns =
#JoinColumn(name = "eId"), inverseJoinColumns =
#JoinColumn(name = "fId"))
private Collection<EntityF> entityFs;
Here is the other entity.
#Entity
public class EntityF implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long fId;
#ManyToMany
#JoinTable(name="entitye_entityf",joinColumns =
#JoinColumn(name = "fId"), inverseJoinColumns =
#JoinColumn(name = "eId"))
private Collection<EntityE> entityEs;
So as you can see from the image, managed to solve my doubts. I hope this answer can be useful for someone else as well.

Related

One table has two same joins in another table

I have one table called image and another table called duplicate. There are two OneToMany relations are associated.
I am not quite sure whether below implementation is the right approach for that. Moreover whether we require that second private List<DuplicateEntity> duplicateEntities2; ?
ImageEntity:
#Entity
#Table(name = "image")
public class ImageEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "filename")
private String fileName;
#OneToMany(mappedBy = "imageEntity1")
private List<DuplicateEntity> duplicateEntities1;
#OneToMany(mappedBy = "imageEntity2")
private List<DuplicateEntity> duplicateEntities2;
}
DuplicateEntity:
#Entity
#Table(name = "duplicate")
public class DuplicateEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne
#JoinColumn(name = "image_a_id")
private ImageEntity imageEntity1;
#ManyToOne
#JoinColumn(name = "image_b_id")
private ImageEntity imageEntity2;
}

How to maintain foreign key relationship in hibernate

I have two classes and I want to have a one to many relation between them, for e.g.:
Home(id<int>, rooms<string>)
Vehicle(id<int>, home_id<int>, name<string>)
I need to have a relation between Home and Vehicle class using Home.id and vehicle.home_id.
Please suggest any example which I can use here for CURD operation to implement REST service.
I need to have a relation between Home and Vehicle class using Home.id
and vehicle.home_id.
Your entities should look like this :
Vehicle Entity
#Entity
#Table(name = "vehicle", catalog = "bd_name", schema = "schema_name")
#XmlRootElement
public class Vehicle implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Column(name = "name")
private String name;
#JoinColumn(name = "home_id", referencedColumnName = "id")
#ManyToOne
private Home homeId;
//constructor getter & setters
}
Home Entity
#Entity
#Table(name = "home", catalog = "bd_name", schema = "schema_name")
#XmlRootElement
public class Home implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Column(name = "room")
private Character room;
#OneToMany(mappedBy = "homeId")
private List<Vehicle> vehicleList;
//constructor getter & setters
}

Hibernate merge parent and update Lazy Child Collection List

I am having a problem when I perform merge parent table, the existing child records will be insert rather than update.
For example, Member(Parent) and Address(Child) tables,
public class Member implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id")
private int id;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "member", cascade = CascadeType.ALL)
public List<Address> addressList;
}
public class Address implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int address_id;
#Column(name = "member_id")
private int mem_id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumns({
#JoinColumn(name = "member_id", referencedColumnName = "id", insertable = false, updatable = false)
})
public Member member;
}
While I perform changes and merge(Member), the address record is being inserted rather than update the existing record.
Does anyone know what would be the reason?
when you perform changes do you set correct address_id ? . Do some debugging and find address_id match with existing id in Address table.
in my approach class will look like below. I don't see need of member_id attribute. because it is same as id attribute of member.
public class Address implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int address_id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "member_id", nullable = false)
public Member member;
public void setMember(Member member) {
this.member = member;
}
}
I can't see any parent child relationship in your snapshot code.
Please amend the code for child class with below code to create the inheritance relationship.
public class Child extends Member implements Serializable{
Extending the Child class to the Parent(Member) will reflect the required changes related to lazy loading.

Mapping composite key with Hibernate produces a raw field in Oracle

-- The Facts....
In my project every class/table should have a couple (Site,Structure) in order to provide multisite deploy.
I provided an Installation class
#Entity
#Table(name="COM_INSTALLATION")
#IdClass(InstallationPK.class)
public class Installation implements Serializable{
private static final long serialVersionUID = 3601006283578715263L;
#Id
#Column(name = "site")
private String site;
#Id
#Column(name = "structure")
private String structure;
/* ... constructor, getters, setters ... */
}
and its PK, as
public class InstallationPK implements Serializable {
private static final long serialVersionUID = 1L;
private String site;
private String structure;
/* .. constructor, getters, setters ... */
}
then I have a MappedSuperclass named BaseEntity
#MappedSuperclass
public class BaseEntity
{
private Installation installation;
#OneToOne
#JoinColumns({
#JoinColumn(name = "site", referencedColumnName = "site"),
#JoinColumn(name = "structure", referencedColumnName = "structure")
})
public Installation getInstallation() {
return installation;
}
public void setInstallation(Installation installation) {
this.installation = installation;
}
}
quite easy so far... every #Entity and #Table annotated class extending BaseEntity contains a column SITE, a column STRUCTURE and a related foreign key.
-- The Problem....
It happens that with a class implementing org.springframework.security.core.userdetails.UserDetails and extending BaseEntity, Hibernate does not create the two columns but an INSTALLATION column with RAW type. That's the class
#Entity
#Table(name="USR_USER", uniqueConstraints =
#UniqueConstraint(columnNames = { "username" }))
#SequenceGenerator(name = "userId_seq_generator", sequenceName = "S_USER")
public class User extends BaseEntity implements UserDetails{
private static final long serialVersionUID = 8698408700004341649L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "userId_seq_generator")
private Long userId;
/* ... getter, setters, ... */
}
and that's the result
Any ideas? Thanks in advance
I don't have point reputation to comment so i'll put here my comments:
Why instalationPK field isn't in instalation.class??
You should put #EmbeddedId in the field instalationPK in Installation.class.
I don't if makes differences, but put joinCollums on the field in BaseEntity:
#OneToOne
#JoinColumns({
#JoinColumn(name = "site", referencedColumnName = "site"),
#JoinColumn(name = "structure", referencedColumnName = "structure")
})
private Installation installation;

createAlias/createCriteria hibernate INNER_JOIN

I am having two tables Parent and Child. The query I want to use in Hibernate Criteria
SELECT tcr.*
FROM case_reminders tcr
INNER JOIN case_reminder_opr tco ON tcr.case_id = tco.case_id
WHERE tcr.case_status = 'OPN'
AND tco.operator_id = 111;
I have written the criteria as
Criteria ctr = getSession().createCriteria(CaseReminderOpr.class).add(Restrictions.eq("pk.oprOperatorId", operatorId));
ctr.createCriteria("pk.crmCaseId", "CR", Criteria.INNER_JOIN).add(Restrictions.eq("CR.caseStatus", STATUS.OPEN.getValue()));
List<CaseReminderOpr> oprList = ctr.list();
tried with createAlias as well but I am getting error as
ORA-00904: "CR1_"."CASE_STATUS": invalid identifier
Classes of CaseReminders(Parent) and CaseReminderOpr(Child) as follows.
#Entity
#Table(name = "CASE_REMINDERS")
public class CaseReminders implements Serializable {
#Id
#Column(name = "CASE_ID")
private Long caseId;
#Column(name = "CASE_STATUS")
private String caseStatus;
}
#Entity
#Table(name="CASE_REMINDER_OPR")
public class CaseReminderOpr implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
private CaseReminderOprPK pk;
}
#Embeddable
public class CaseReminderOprPK implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
#ManyToOne
#JoinColumn(name = "CASE_ID")
private CaseReminders crmCaseId;
#Column(name="OPERATOR_ID")
private Long operatorId;
}
Please help me with the inner_join query, appreciate your help again.
The change would be as below then it works. I have realized this later.
Make the Joincolumn as insertable=false,updatable=false in main entity class.
#Entity
#Table(name="CASE_REMINDER_OPR")
public class CaseReminderOpr implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
private CaseReminderOprPK pk;
#ManyToOne
#JoinColumn(name = "CASE_ID", insertable=false, updatable=false)
private CaseReminders caseRem;
}
Now the query should work as expected.
Criteria ctr = getSession().createCriteria(CaseReminderOpr.class, "CRO").add(Restrictions.eq("pk.oprOperatorId", operatorId));
ctr.createCriteria("CRO.caseRem", "CR", Criteria.INNER_JOIN).add(Restrictions.eq("CR.caseStatus", STATUS.OPEN.getValue()));
List<CaseReminderOpr> oprList = ctr.list();
Hopefully I am clear in explaining.

Categories