hibernate join table mapping - hibernate-mapping

I want to map two entity classes:
#entity
Class A{
private long A_ID // primarykey
private long userID // not a primarykey
}
#entity
Class B{
private long B_ID // primary key
}
I want to join A and B where A_ID = B_ID. Is there any way to map both of them by using join table/association class that can have A_ID, B_ID and userID? I am not sure if this is possible?
Class A_B{
private long A_ID
private long userID
private long B_ID
}

Related

Spring boot JPA - primary key of entities in database

I have #OneToMany and #ManyToOne relationship between parent and child entities.
#Entity
#Table(name = "parent")
public class Parent {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
#OneToMany(targetEntity=Measurement.class, mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
#PrimaryKeyJoinColumn
#JsonManagedReference
private List<Child> children = new ArrayList<>();
}
and I have child entity like this
#Entity
#Table(name = "child")
public class Child {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToOne(targetEntity=Parent.class, fetch = FetchType.LAZY)
#JoinColumn(name = "parent_id")
#JsonBackReference
private Parent parent;
After saving this data, the database looks like following,
Parent:
id
1
Child
id parent_id
2 1
my question is, why does the primary key of child is 2 and not 1? In the child table, it could have a primary key as 1 and foreign key reference to parent as 1. When I add one more parent, then the tables looks like this,
Parent:
id
1
3
Child
id parent_id
2 1
4 3
Am I doing something wrong or it is the expected behaviour?
The generation strategy #GeneratedValue(strategy = GenerationType.AUTO) will takes value from the default hibernate sequence, so the same sequence is used for all key generation.
When you are inserting the data, it inserts in the sequence like Parent then Child, as it is getting values from the same sequence generator, it will increase in sequence for all your table.
You need to use the GenerationType.IDENTITY strategy for your purpose.
In parent Parent
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
In child
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

How to write select named query in jpa for EmbeddedId?

I have a JPA entity called Parent and inside that there is embeddedPrimary key as Child
#Entity
#Table(name = "PARENT")
#NamedQuery(?????)
public class Parent implements Serializable {
#EmbeddedId
private ChildPK child;
}
and
#Embeddable
public class ChildPK implements Serializable {
#Column(name = "DEALERID")
private String dealerId;
#Column(name = "BRANDID")
private Long brandId;
..
}
How can I write named Query in Parent class so that i can perform select on dealerId and brandId from ChildPk.
SELECT p FROM Parent p WHERE p.child.dealerId = ? and p.child.brandId=?

Hibernate grouping and result set transformation

Suppose I have the following result set:
So, we have one-to-many-to-many relation here.
The question is what would be the best way to group it in Hibernate and convert this data structure to DTO with fields like:
String countryName
String companyName
List invoiceNumbers
Thank you!
For Country and Company ---- Many-to-Many
For Company and Invoice --- One-to-Many
#Entity
public class Country {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#ManyToMany(mappedBy="countries")
private Collection<Country> countries;
...
getters and setters
}
#Entity
public class Company {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#ManyToMany
private Collection<Country> countries;
#OneToMany
private Collection<Invoice> invoices;
...
getters and setters
}
#Entity
public class Invoice {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private int invoice_number;
...
getters and setters
}

Multiple unidirectional oneToMany relationship columns from one table to another table in JPA

I'm trying to have a localization table that is linked to from multiple tables.
I'm realizing that the problem is that I'm using the ID of Localization (eg Localization_Id) so I can't link to different localizations without some other key. Should I use a join table or some other sequential id in the database somehow? Not sure what the best approach is using JPA.
Thanks in advance.
#Entity
public class MyEntityWithLocalization {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
long id;
#OneToMany(fetch = FetchType.EAGER, cascade={CascadeType.ALL})
#JoinColumn(name="LOCALIZATION_KEY")
List<Localization> field1;
#OneToMany(fetch = FetchType.EAGER, cascade={CascadeType.ALL})
#JoinColumn(name="LOCALIZATION_KEY")
List<Localization> field2; //can't be unique from field one as it links to the MyEntityWithLocalization id.
#OneToMany(fetch = FetchType.EAGER, cascade={CascadeType.ALL})
#JoinColumn(name="LOCALIZATION_KEY")
List<Localization> field3; //can't be unique from field one as it links to the MyEntityWithLocalization id.
}
#Entity
public class Localization {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
long id;
String language;
String string;
public Localization(String language, String string) {
this.language = language;
this.string = string;
}
public Localization(){
}
}
This creates a localization_key in the localization table but that is just keyed to the ID of the MyEntityWithLocalization - it needs to be another unique value which makes me believe a join table may make sense in this case.
create table localization (
id number(19,0) not null,
language varchar2(255),
string varchar2(255),
localization_key number(19,0),
primary key (id)
);
Hmm. Why not just split the entity into constant and localizable part? Something like this:
#Entity
class MyEntity{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
long id;
#OneToMany
#MapKeyColumn
Map<String, MyEntityLocalization> localizations;
}
#Embeddable
class MyEntityLocalization {
String field1;
String field2;
String field3;
}
Where the localizations field has the map from the language to the localization? The other way is using Hibernate-specific annotations:
#Entity
class MyEntityWithLocalization {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
long id;
#OneToMany
#MapKeyColumn(name="language")
#WhereJoinTable(clause = "key=1")
Map<String, String> field1;
#OneToMany
#MapKeyColumn(name="language")
#WhereJoinTable(clause = "key=2")
Map<String, String> field2;
}
#Entity
public class Localization {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
long id;
long key;
String language;
String string;
}

Help Mapping a Composite Foreign Key in JPA 2.0

I'm new to JPA and I'm trying to map a legacy database. The files load correctly individually but the relationships are not working correctly. Any help would be appreciated.
Java
#Entity
#IdClass(ParentKey.class)
public class Parent {
#Id
#Column(name="code")
private String code;
#Id
#Column(name="id")
private int id;
#OneToMany(mappedBy="parent")
private List<Child> children = new ArrayList<Child>();
}
public class ParentKey {
private String code;
private int id;
}
#Entity
#IdClass(ChildKey.class)
public class Child {
#Id
#JoinColumns({
#JoinColumn(name="code")
#JoinColumn(name="id")
})
private Parent parent;
#Id
#Column(name="index")
private int index;
}
public class ChildKey {
private String code;
private int id;
private int index;
}
SQL
create table Parent(
code char(4) not null,
id int not null,
primary key(code,id)
);
create table Child(
code char(4) not null,
id int not null,
index int not null,
primary key(code, id, index),
foreign key(code, id) references Parent(code,id)
);
edit 1:
add the ChildKey and ParentKey classes.
Here's a link to DataNucleus docs for compound identity 1-N relation. May help you identify what is wrong. For a start you have no IdClass defined on Child
http://www.datanucleus.org/products/accessplatform_3_0/jpa/orm/compound_identity.html#1_N_coll_bi
Here is what OpenJPA created using its ReverseMapping Tool and it appears to be working correctly.
#Entity
#Table(name="PARENT")
#IdClass(ParentId.class)
public class Parent {
#OneToMany(targetEntity=Child.class, mappedBy="parent", cascade=CascadeType.MERGE)
private Set childs = new HashSet();
#Id
#Column(length=4)
private String code;
#Id
private int id;
//omitted getters, setters
}
public class ParentId implements Serializable {
public String code;
public int id;
//omitted getters, setters, toString, equals, hashcode
}
#Entity
#Table(name="CHILD")
#IdClass(ChildId.class)
public class Child {
#Id
#Column(length=4)
private String code;
#Id
private int id;
#Id
private int index;
#ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.MERGE)
#JoinColumns({#JoinColumn(name="code"), #JoinColumn(name="id")})
private Parent parent;
//omitted getters, setters
}
public class ChildId implements Serializable {
public String code;
public int id;
public int index;
//omitted getters, setters, toString, equals, hashcode
}
See also http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#JPA_2.0
(add #Id to #ManyToOne field)