Hibernate grouping and result set transformation - sql

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
}

Related

How to use oracle keyword "desc" as a field name in Spring boot entity class

The table was not being created for the following model despite following the correct procedure
Model
#AllArgsConstructor
#NoArgsConstructor
#Data
#Entity
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Integer pid;
String name;
String desc;
double price;
}
So I was creating an entity class for JPA where there was a field name desc. I was using MySQL database. But for some reason, I was getting the following error.
The model
#AllArgsConstructor
#NoArgsConstructor
#Data
#Entity
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Integer pid;
String name;
String desc;
double price;
}
Later I changed the field name and the whole thing was working. The ORM was automatically creating the table.
The updated model that works
#AllArgsConstructor
#NoArgsConstructor
#Data
#Entity
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Integer pid;
String name;
String description;
double price;
}

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=?

SQL query to JPA specification

I have this simplified JPA entities
#Entity
#Table(name = "students")
public class Student {
#Id
private Integer id;
private String name;
//getters, setters
}
#Entity
#Table(name = "averages")
public class Averages {
#Id
private Integer id;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "student_id", referencedColumnName = "id")
private Student student;
private float value;
//getters, setters
}
How I can write this query using JPA Specification and CriteriaBuilder?
SELECT students.id
FROM students,
averages
WHERE averages.student_id = students.id
GROUP BY students.id
HAVING AVG(averages.value) > 6
It should be something like:
select student.id
from Averages average
join average.student student
group by student.id
having avg(average.value)>6
i have no way of testing this
Edit: this is using EntityManager#createQuery(String)

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)