Currently I'm learning Hibernate and so I created database in MySQL with three tables in following way (MWE)
create database `fakturowanie`;
use `fakturowanie`;
drop table if exists `wykupione_uslugi`; #table 'bought services'
drop table if exists `uslugi`; #table 'services'
drop table if exists `kontrahenci`; table 'contractors'
create table `kontrahenci`(
`kontrahent_id` int unsigned auto_increment primary key,
`nazwisko` varchar(80), #surname
`imie` varchar(30), #name
`firma_nazwa` varchar(100), #company name
`nip_pesel` varchar(20) not null unique, #person ID
`ulica_nr_mieszkania` varchar(100), #street
`kod_pocztowy` varchar(6), #postal code
`miejscowosc` varchar(30), #city
`sposob_zaplaty` varchar(7) not null default 'gotówka', #payment method default cash
`uwzglednij_numer_faktury` bool not null default true, #include invoice number
`alias` varchar(30) not null
)engine = InnoDB
default charset = utf8
collate = utf8_polish_ci;
create table `uslugi`(
`usluga_id` int unsigned auto_increment primary key,
`nazwa` varchar(80) not null, #name
`symbol_PKWIU/PKOB` varchar(10),
`jednostka` varchar(10) not null, #unit
`cena_jednostkowa_netto` decimal(6, 2) not null, #unit price
`stawka_vat` int(2) unsigned not null #tax rate
)engine = InnoDB
default charset = utf8
collate = utf8_polish_ci;
create table `wykupione_uslugi`(
`id` int unsigned auto_increment primary key,
`kontrahent_id` int unsigned not null,
`usluga_id` int unsigned not null,
foreign key(kontrahent_id) references kontrahenci(kontrahent_id),
foreign key(usluga_id) references uslugi(usluga_id)
)engine = InnoDB
default charset = utf8
collate = utf8_polish_ci;
insert into `kontrahenci` (
nazwisko, imie, firma_nazwa, nip_pesel, ulica_nr_mieszkania, kod_pocztowy, miejscowosc, sposob_zaplaty, uwzglednij_numer_faktury, alias)
values ('Best', 'John', 'Best Inc.', 111-111-111, 'Best Street 5', 11-111, 'Best Valley', 'cash', 1, 'test');
insert into `uslugi` (
nazwa, jednostka, cena_jednostkowa_netto, stawka_vat)
values (
'Best tutoring', 'hour', 1000.00, 0);
insert into `wykupione_uslugi` (kontrahent_id, usluga_id) values (1, 1);
What I'm trying to do using Hibernate is equivalent of this SQL query
select
`uslugi`.`nazwa`,
`uslugi`.`symbol_PKWIU/PKOB`,
`uslugi`.`jednostka`,
`uslugi`.`cena_jednostkowa_netto`,
`uslugi`.`stawka_vat`
from
`wykupione_uslugi`
left join `kontrahenci` on `wykupione_uslugi`.`kontrahent_id` = `kontrahenci`.`kontrahent_id`
left join `uslugi` on `wykupione_uslugi`.`usluga_id` = `uslugi`.`usluga_id`
where
`kontrahenci`.`alias` = 'test';
I created mapped classes like this:
Service class
#Entity
#Table(name="uslugi", schema = "fakturowanie")
public class Service
{
private int serviceID;
private String serviceName;
private String symbol;
private String unit;
private BigDecimal unitPrice;
private int tax;
private Collection<ServicesList> servicesLists;
#Id
#Column(name = "usluga_id", nullable = false)
#GeneratedValue(generator="increment")
#GenericGenerator(name="increment", strategy = "increment")
public int getServiceID()
{
return serviceID;
}
public void setServiceID(int serviceID)
{
this.serviceID = serviceID;
}
#Basic
#Column(name = "nazwa", nullable = false, length = 80)
public String getServiceName()
{
return serviceName;
}
public void setServiceName(String serviceName)
{
this.serviceName = serviceName;
}
#Basic
#Column(name = "symbol_PKWIU/PKOB", nullable = false, length = 10)
public String getSymbol()
{
return symbol;
}
public void setSymbol(String symbol)
{
this.symbol = symbol;
}
#Basic
#Column(name = "jednostka", nullable = false, length = 10)
public String getUnit()
{
return unit;
}
public void setUnit(String unit)
{
this.unit = unit;
}
#Basic
#Column(name = "cena_jednostkowa_netto", nullable = false, precision = 2)
public BigDecimal getUnitPrice()
{
return unitPrice;
}
public void setUnitPrice(BigDecimal unitPrice)
{
this.unitPrice = unitPrice;
}
#Basic
#Column(name = "stawka_vat", nullable = false)
public int getTax()
{
return tax;
}
public void setTax(int tax)
{
this.tax = tax;
}
#OneToMany(mappedBy = "servicesMapping")
public Collection<ServicesList> getServicesLists()
{
return servicesLists;
}
public void setServicesLists(Collection<ServicesList> servicesLists)
{
this.servicesLists = servicesLists;
}
}
Contractor class
#Entity
#Table(name = "kontrahenci", schema = "fakturowanie")
public class Contractor
{
private int contractorID;
private String surname;
private String name;
private String companyName;
private String taxpayerINum;
private String street;
private String postalCode;
private String city;
private PaymentMethod paymentMethod;
private byte includeInvoiceNum;
private String alias;
private Collection<ServicesList> servicesList;
#Id
#Column(name = "kontrahent_id", nullable = false)
#GeneratedValue(generator="increment")
#GenericGenerator(name="increment", strategy = "increment")
public int getContractorID()
{
return contractorID;
}
public void setContractorID(int contractorID)
{
this.contractorID = contractorID;
}
#Basic
#Column(name = "nazwisko", nullable = true, length = 80)
public String getSurname()
{
return surname;
}
public void setSurname(String surname)
{
this.surname = surname;
}
#Basic
#Column(name = "imie", nullable = true, length = 30)
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
#Basic
#Column(name = "firma_nazwa", nullable = true, length = 100)
public String getCompanyName()
{
return companyName;
}
public void setCompanyName(String companyName)
{
this.companyName = companyName;
}
#Basic
#Column(name = "nip_pesel", unique = true, length = 20, nullable = false)
public String getTaxpayerINum()
{
return taxpayerINum;
}
public void setTaxpayerINum(String taxpayerINum)
{
this.taxpayerINum = taxpayerINum;
}
#Basic
#Column(name = "ulica_nr_mieszkania", nullable = true, length = 100)
public String getStreet()
{
return street;
}
public void setStreet(String street)
{
this.street = street;
}
#Basic
#Column(name = "kod_pocztowy", nullable = true, length = 6)
public String getPostalCode()
{
return postalCode;
}
public void setPostalCode(String postalCode)
{
this.postalCode = postalCode;
}
#Basic
#Column(name = "miejscowosc", nullable = true, length = 30)
public String getCity()
{
return city;
}
public void setCity(String city)
{
this.city = city;
}
#Enumerated(EnumType.STRING)
#Column(name = "sposob_zaplaty", nullable = false, length = 7)
public PaymentMethod getPaymentMethod()
{
return paymentMethod;
}
public void setPaymentMethod(PaymentMethod paymentMethod)
{
this.paymentMethod = paymentMethod;
}
#Basic
#Column(name = "uwzglednij_numer_faktury", nullable = false)
public byte getIncludeInvoiceNum()
{
return includeInvoiceNum;
}
public void setIncludeInvoiceNum(byte includeInvoiceNum)
{
this.includeInvoiceNum = includeInvoiceNum;
}
#Basic
#Column(name = "alias", nullable = false, length = 30)
public String getAlias()
{
return alias;
}
public void setAlias(String alias)
{
this.alias = alias;
}
#OneToMany(mappedBy = "contractorMapping")
public Collection<ServicesList> getServicesList()
{
return servicesList;
}
public void setServicesList(Collection<ServicesList> servicesList)
{
this.servicesList = servicesList;
}
}
ServicesList class
#Entity
#Table(name = "wykupione_uslugi", schema = "fakturowanie")
public class ServicesList
{
private int id;
private int contractorID;
private int serviceID;
private Contractor contractorMapping;
private Service servicesMapping;
#Id
#Column(name = "id", nullable = false)
#GeneratedValue(generator="increment")
#GenericGenerator(name="increment", strategy = "increment")
public int getId()
{
return id;
}
public void setId(int id) {
this.id = id;
}
#Basic
#Column(name = "kontrahent_id", nullable = false)
public int getContractorID() {
return contractorID;
}
public void setContractorID(int contractorID) {
this.contractorID = contractorID;
}
#Basic
#Column(name = "usluga_id", nullable = false)
public int getServiceID() {
return serviceID;
}
public void setServiceID(int serviceID) {
this.serviceID = serviceID;
}
#ManyToOne
#JoinColumn(name = "kontrahent_id", referencedColumnName = "kontrahent_id", insertable = false, updatable = false)
public Contractor getContractorMapping() {
return contractorMapping;
}
public void setContractorMapping(Contractor contractorMapping) {
this.contractorMapping = contractorMapping;
}
#ManyToOne
#JoinColumn(name = "usluga_id", referencedColumnName = "usluga_id", insertable = false, updatable = false)
public Service getServicesMapping() {
return servicesMapping;
}
public void setServicesMapping(Service servicesMapping) {
this.servicesMapping = servicesMapping;
}
}
I also created HibernateUtil class to handle SessionFactory
public class HibernateUtil
{
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
try {
Configuration configuration = new Configuration();
configuration.configure();
StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
.configure()
.build();
return configuration.buildSessionFactory(standardRegistry);
}
catch(Exception e) {
throw new ExceptionInInitializerError(e);
}
}
public static Session getSession()
{
return sessionFactory.openSession();
}
public static void close()
{
sessionFactory.close();
}
}
And Main class looks like this:
public class Main
{
public static void main(String[] args)
{
Session session = HibernateUtil.getSession();
session.beginTransaction();
List<Service> services = session.createQuery(
"select Service.serviceName, Service.symbol, Service.unit, Service.unitPrice, Service.tax " +
"from ServicesList " +
"left join ServicesList.contractorMapping left join ServicesList.servicesMapping " +
"where Contractor.alias = 'test'").list();
for(Service s : services)
{
System.out.println(s.getServiceID() + "\t" + s.getServiceName() + "\t" + s.getSymbol() + "\t" + s.getUnit() +
"\t" + s.getUnitPrice() + "\t" + s.getTax());
}
session.getTransaction().commit();
session.close();
}
}
but the error says that's something wrong with query and I don't really know what can be wrong
Exception in thread "main" java.lang.NullPointerException
at java.lang.String$CaseInsensitiveComparator.compare(String.java:1192)
at java.lang.String$CaseInsensitiveComparator.compare(String.java:1186)
at java.util.TreeMap.getEntryUsingComparator(TreeMap.java:376)
at java.util.TreeMap.getEntry(TreeMap.java:345)
at java.util.TreeMap.get(TreeMap.java:278)
at org.hibernate.dialect.function.SQLFunctionRegistry.findSQLFunction(SQLFunctionRegistry.java:45)
at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.findSQLFunction(SessionFactoryHelper.java:369)
at org.hibernate.hql.internal.ast.tree.IdentNode.getDataType(IdentNode.java:374)
at org.hibernate.hql.internal.ast.HqlSqlWalker.lookupProperty(HqlSqlWalker.java:652)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.propertyRef(HqlSqlBaseWalker.java:1140)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.joinElement(HqlSqlBaseWalker.java:3838)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3701)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:3579)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromClause(HqlSqlBaseWalker.java:718)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:574)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:311)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:259)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:261)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:189)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:141)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:153)
at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:545)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:654)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:102)
at Main.main(Main.java:12)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
EDIT
Answer by Maciej Kowalski helped but still I'm getting some weird and unwanted output, btw main does not exit (as it supposed to) but is 'hanging'. I highlited yellow correct output.
There are a few things here..
First, you are trying to make projection (which is a good thing if you want to work on the returned data, but not update it) and expecting to get a List of entities. Does not work that way.
Second, you are referencing the columns in a wrong way. The standard is to use an alias and go on from there (so much easier to read and maintain).
So, having those in mind i would:
1) Create a special result class for the projection, so that it would be easier to work with that query. It will also save you tons of boiler plate code parsing:
package com.mypkg;
public class ServiceResult{
private String serviceName;
private String symbol;
private String unit;
private BigDecimal unitPrice;
private int tax;
public ServiceResult(String serviceName, String symbol
,String unit, BigDecimal unitPrice, int tax){
// set the field values
}
}
2) Change the query to the following:
List<ServiceResult> services = session.createQuery(
"select new com.mypkg.ServiceResult(service.serviceName
,service.symbol, service.unit
, service.unitPrice, service.tax) " +
"from ServicesList serviceList" +
" left join serviceList.contractorMapping contractor" +
" left join serviceList.servicesMapping service" +
"where contractor.alias = 'test'")
.list();
3) IF your intention was to actually get the whole Service entities, then use this query:
List<Service> services = session.createQuery(
"select service " +
"from Service service" +
" left join service.servicesLists servicesLists" +
" left join servicesLists.contractorMapping contractor" +
"where contractor.alias = 'test'")
.list();
On the side
As there are a few joins going on here, so you might need to add distinct to not get redundant results.
I have fetched a list of objects of type Company from the database. But when trying to serialize the list using Jackson to JSON, throws an error
com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: com.zerosolutions.repository.entity.CompanySector.companies, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->com.zerosolutions.repository.entity.Company["sector"]->com.zerosolutions.repository.entity.CompanySector["companies"])
Company:
#Entity
#Table(name = "company")
public class Company {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "name")
private String name;
#ManyToOne(cascade = CascadeType.PERSIST)
#JoinColumn(name = "sector")
private CompanySector sector;
#OneToOne
#JoinColumn(name = "id")
private CompanyProfile profile;
#OneToOne
#JoinColumn(name = "id")
private CompanyAddress address;
#OneToMany(mappedBy = "company", cascade = CascadeType.ALL)
private List<Job> jobs = new ArrayList<>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public CompanySector getSector() {
return sector;
}
public void setSector(CompanySector sector) {
this.sector = sector;
}
public CompanyProfile getProfile() {
return profile;
}
public void setProfile(CompanyProfile profile) {
this.profile = profile;
}
public CompanyAddress getAddress() {
return address;
}
public void setAddress(CompanyAddress address) {
this.address = address;
}
public List<Job> getJobs() {
return jobs;
}
public void setJobs(List<Job> jobs) {
this.jobs = jobs;
}
}
CompanySector:
#Entity
#Table(name = "sectors")
public class CompanySector {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
#Column(name="sector")
private String sector;
#OneToMany(mappedBy="sector", cascade=CascadeType.PERSIST)
private List<Company> companies = new ArrayList<>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getSector() {
return sector;
}
public void setSector(String sector) {
this.sector = sector;
}
public List<Company> getCompanies() {
return companies;
}
}
Conversion code:
#RequestMapping(value = "/getCompanyList", method = RequestMethod.GET, produces={ "application/json"})
public #ResponseBody String getCompanyList() {
ObjectMapper mapper = new ObjectMapper();
try {
List<Company> companyList = companyServices.getCompanyList();
String companyListString = mapper.writeValueAsString(companyList); // this line throws error
return companyListString;
} catch (JsonProcessingException e) {
logger.error(e);
return null;
}
}
Any Suggestions what might be wrong here ?
Fetching list:
public List<Company> getCompanyList(){
Session session = sessionFactory.openSession();
Transaction tx = null;
try{
tx = session.beginTransaction();
List<Company> companies = session.createCriteria(Company.class).list();
logger.debug(companies);
tx.commit();
System.out.println("companies fetched");
return companies;
} catch(Exception e){
logger.error("Exceptino thrown: " + e);
tx.rollback();
return null;
} finally{
session.close();
}
}
If you know that you'll want to see all Companies every time you retrieve a CompanySector then change your field mapping for Companies to:
#OneToMany(fetch = FetchType.EAGER, mappedBy="sector", cascade=CascadeType.PERSIST)
private List<Company> companies = new ArrayList<>();
Another approach use Hibernate.initialize :
Hibernate.initialize(companySector.getCompany());
Also see this link it's very helpful
I have the following entities and I'm trying to save them using hibernate cascade:
Entity Usuario:
#Entity
#Table(schema="system", name="usuarios")
public class Usuario {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Column(nullable = false)
private String nome;
#Column(name = "data_nascimento")
private Date dataNascimento;
private String sexo;
#OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "usuario")
private DadosFuncionario dadosFuncionario;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public Date getDataNascimento() {
return dataNascimento;
}
public void setDataNascimento(Date dataNascimento) {
this.dataNascimento = dataNascimento;
}
public String getSexo() {
return sexo;
}
public void setSexo(String sexo) {
this.sexo = sexo;
}
public DadosFuncionario getDadosFuncionario() {
return dadosFuncionario;
}
public void setDadosFuncionario(DadosFuncionario dadosFuncionario) {
this.dadosFuncionario = dadosFuncionario;
}
}
Table structure for usuarios:
CREATE TABLE "system"."usuarios" (
"id" int4 NOT NULL,
"data_nascimento" date,
"nome" varchar(255) COLLATE "default" NOT NULL,
"sexo" varchar(255) COLLATE "default"
)
Entity DadosFuncionario:
#Entity
#Table(schema = "system", name = "dados_funcionario")
public class DadosFuncionario {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Column(unique = true)
private String matricula;
#Column(name = "pref_reg", nullable = true)
private int prefReg;
#Column(name = "pref_dep", nullable = false)
private int prefDep;
#Column(nullable = true)
private String telefone;
#OneToOne
#JoinColumn(name = "id_usuario")
private Usuario usuario;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getMatricula() {
return matricula;
}
public void setMatricula(String matricula) {
this.matricula = matricula;
}
public int getPrefReg() {
return prefReg;
}
public void setPrefReg(int prefReg) {
this.prefReg = prefReg;
}
public int getPrefDep() {
return prefDep;
}
public void setPrefDep(int prefDep) {
this.prefDep = prefDep;
}
public String getTelefone() {
return telefone;
}
public void setTelefone(String telefone) {
this.telefone = telefone;
}
public Usuario getUsuario() {
return usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
}
Table structure for dados_funcionario:
CREATE TABLE "system"."dados_funcionario" (
"id" int4 NOT NULL,
"matricula" varchar(255) COLLATE "default",
"pref_dep" int4 NOT NULL,
"pref_reg" int4,
"telefone" varchar(255) COLLATE "default",
"id_usuario" int4
)
And then to test if it was saving everything the way it was supposed to, I'm doing this:
Usuario novoUsuario = new Usuario();
DadosFuncionario novoDadosFuncionario = new DadosFuncionario();
novoDadosFuncionario.setMatricula("XXXXXXXXX");
novoDadosFuncionario.setPrefDep(9999);
novoUsuario.setNome("XXXXX XXXXX");
novoUsuario.setDadosFuncionario(novoDadosFuncionario);
Transaction tx = session.beginTransaction();
session.save(novoUsuario);
tx.commit();
It insert the correct data into the correct tables, but it does not save the foreign key of usuarios in dados_funcionario (its filling the column id_usuario with null). So, it understands the relationship (it saved in cascade, because I only used the session.save() with novoUsuario and it saved the data from novoDadosFuncionario) but it doesn't insert the foreign key and I can't figure out why.
You are not setting the other side of the relation anywhere, which you should in bidirectional relationships. Add this
novoDadosFuncionario.setUsuario(novoUsuario);
Please help me in accessing Employee object in the below code using JAXB annotations. The application was developed in JPA SPRING. We are unable to access sub-object properties i.e, Employee properties
RESOURCE CORE FILE
#XmlAccessorType(XmlAccessType.PROPERTY)
#XmlRootElement(name="resource")
#Entity
#Table(name = "resource")
public class Resource implements java.io.Serializable {
private Integer resourceId;
private String resourceCode;
private String resourceName;
private String resourceNumber;
private Employee employee;
public Resource() {
}
public Resource(Employee employee,String resourceCode, String resourceName,
String resourceNumber
) {
this.employee = employee;
this.resourceCode = resourceCode;
this.resourceName = resourceName;
this.resourceNumber = resourceNumber;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "resource_id", unique = true, nullable = false)
public Integer getResourceId() {
return this.resourceId;
}
public void setResourceId(Integer resourceId) {
this.resourceId = resourceId;
}
#Column(name = "resource_code")
public String getResourceCode() {
return this.resourceCode;
}
public void setResourceCode(String resourceCode) {
this.resourceCode = resourceCode;
}
#Column(name = "resource_number")
public String getResourceNumber() {
return this.resourceNumber;
}
public void setResourceNumber(String resourceNumber) {
this.resourceNumber = resourceNumber;
}
#Column(name = "resource_name")
public String getResourceName() {
return this.resourceName;
}
public void setResourceName(String resourceName) {
this.resourceName = resourceName;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "employee_id")
public Employee getEmployee() {
return this.employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
}
EMPLOYEE CORE FILE
#XmlAccessorType(XmlAccessType.PROPERTY)
#XmlRootElement(name="employee")
#Entity
#Table(name = "employee")
public class Employee implements java.io.Serializable {
private Integer employeeId;
private String employeeCode;
private String employeeName;
private List<Resource> resources = new ArrayList<Resource>(0);
public Employee() {
}
public Employee(String employeeCode, String employeeName,List<Resource> resources
) {
this.employeeCode = employeeCode;
this.employeeName = employeeName;
this.resources = resources;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "employee_id", unique = true, nullable = false)
public Integer getEmployeeId() {
return this.employeeId;
}
public void setEmployeeId(Integer employeeId) {
this.employeeId = employeeId;
}
#Column(name = "employee_code")
public String getEmployeeCode() {
return this.employeeCode;
}
public void setEmployeeCode(String employeeCode) {
this.employeeCode = employeeCode;
}
#Column(name = "employee_name")
public String getEmployeeName() {
return this.employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "employee")
public List<Resource> getResources() {
return this.resources;
}
public void setResources(List<Resource> resources) {
this.resources = resources;
}
}
You have to use the FetchType : Eager in RESOURCE CORE FILE of getEmployee() Method. Lazy fetch type is pulling only the parent object. Eager is pulling both.
Here I have a table named receipt and its primary key is a composite key referred with other class Receipt_compoundKey with two variables named voucher_id and company_id,
How I retrive data from receipt with condition like company_id=1;
Receipt :
#Entity
#Table(name = AMAM_Constants.tb_name.RECEIPT_FROM, catalog = AMAM_Constants.db_name)
public class Receipt implements Serializable {
#Id
private Receipt_CompoundKey id;
#OneToOne
#JoinColumn(name = "FROM_LEDGER")
private Ledger fromLedger;
#Column(name = "VOU_DATE")
private Date voucher_Date;
#Column(name = "TOTAL_AMOUNT")
private double total_amount;
#Column(name = "ACTIVE")
private char active;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinTable(name = AMAM_Constants.tb_name.RECEIPT_FROM_LINK_TO, joinColumns = {
#JoinColumn(name = "COMPANY_ID"),
#JoinColumn(name = "VOUCHER_ID")
}, inverseJoinColumns = {
#JoinColumn(name = "RECP_TO")})
private List<Receipt_To> recptToList = new ArrayList<Receipt_To>();
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name = AMAM_Constants.tb_name.RECEIPT_FROM_LINK_ADJMTS, joinColumns = {
#JoinColumn(name = "COMPANY_ID"),
#JoinColumn(name = "VOUCHER_ID")
}, inverseJoinColumns = {
#JoinColumn(name = "RECPT_ADJS")})
private List<Receipt_Adj> recptAdjments = new ArrayList<Receipt_Adj>();
public List<Receipt_Adj> getRecptAdjments() {
return recptAdjments;
}
public void setRecptAdjments(List<Receipt_Adj> recptAdjments) {
this.recptAdjments = recptAdjments;
}
public List<Receipt_To> getRecptToList() {
return recptToList;
}
public void setRecptToList(List<Receipt_To> recptToList) {
this.recptToList = recptToList;
}
public char getActive() {
return active;
}
public void setActive(char active) {
this.active = active;
}
public double getTotal_amount() {
return total_amount;
}
public void setTotal_amount(double total_amount) {
this.total_amount = total_amount;
}
public Ledger getFromLedger() {
return fromLedger;
}
public void setFromLedger(Ledger fromLedger) {
this.fromLedger = fromLedger;
}
public Receipt_CompoundKey getId() {
return id;
}
public void setId(Receipt_CompoundKey id) {
this.id = id;
}
public Date getVoucher_Date() {
return voucher_Date;
}
public void setVoucher_Date(Date voucher_Date) {
this.voucher_Date = voucher_Date;
}
}
Receipt_CompoundKey :
#Embeddable
public class Receipt_CompoundKey implements Serializable {
#Column(name = "VOUCHER_ID")
private long voucher_Id;
#Column(name = "COMPANY_ID")
private long company_Id;
public Receipt_CompoundKey() {
}
public Receipt_CompoundKey(long voucher_Id) {
this.voucher_Id = voucher_Id;
}
public Receipt_CompoundKey(long voucher_Id, long company_Id) {
this.company_Id = company_Id;
this.voucher_Id = voucher_Id;
}
public long getCompany_Id() {
return company_Id;
}
public void setCompany_Id(long company_Id) {
this.company_Id = company_Id;
}
public long getVoucher_Id() {
return voucher_Id;
}
public void setVoucher_Id(long voucher_Id) {
this.voucher_Id = voucher_Id;
}
}
Query :
String query = "from Receipt where active='Y' and id=:id ";
begin();
objList = getSession().createQuery(query).setLong("id", key.getCompany_Id()).setLong("id", key.getVoucher_Id()).list();
commit();
You do it as you would with a single-column ID:
getSession().createQuery(query).setParameter("id", key);
You could also query on individual values of the key, but it's unnecessary here:
String query = "select r from Receipt r where r.active = 'Y'"
+ " and id.company_Id = :companyId"
+ " and id.voucher_Id = :voucherId";
objList = getSession().createQuery(query)
.setLong("companyId", key.getCompany_Id())
.setLong("voucherId", key.getVoucher_Id())
.list();
Please please, respect the Java naming conventions: voucherId and not voucher_Id, ReceiptCompoundKey and not Receipt_CompoundKey, etc.
First you have to do a select not just "from Receipt where active='Y' and id=:id " (I assume that this is unmeant mistake but just in case it is't):
String query = "
SELECT receipt
FROM Receipt receipt
WHERE receipt.id = :yourId "
For creating a query I use EntityManager. Here is some example class and how it works for me.
public class EntityManagerUtil {
private static EntityManagerFactory entityManagerFactory = null;
private static final ThreadLocal<EntityManager> entitymanager =
new ThreadLocal<EntityManager>();
private static final ThreadLocal<Map<Class<?>, Set<Serializable>>>collectionFieldNameValues =
new ThreadLocal<Map<Class<?>, Set<Serializable>>>();
public static EntityManagerFactory initializeEntityManagerFactory( String persistenceUnit ) {
if ( entityManagerFactory == null ) {
entityManagerFactory = Persistence.createEntityManagerFactory( persistenceUnit );
}
return entityManagerFactory;
}
public static EntityManager getEntityManager() {
EntityManager entityManager = entitymanager.get();
// Create a new EntityManager
if ( entityManager == null || !entityManager.isOpen()) {
entityManager = entityManagerFactory.createEntityManager();
entitymanager.set( entityManager );
}
return entityManager;
}
public static void close() {
final EntityManager entityManager = entitymanager.get();
entitymanager.set( null );
if ( entityManager != null && entityManager.isOpen()) {
entityManager.close();
}
if ( entityManagerFactory != null && entityManagerFactory.isOpen()) {
entityManagerFactory.close();
}
}
}
And in your class that you want to get the data you first initialize the EntityManagerFactory with your persistence unit (lest say it is called ReceiptPersistence). Here is how would it looks like:
EntityManagerUtil.initializeEntityManagerFactory("ReceiptPersistence");
EntityManagerUtil.getEntityManager().getTransaction().begin();
Query getReceiptWithId = EntityManagerUtil.getEntityManager().createQuery(query);
getReceiptWithId.setParameter("yourId", idThatYouWant);
Now when your query is ready you can get a single result from it with getSingleResult() :
Receipt receipt = (Receipt) getReceiptWithId.getSingleResult();
EntityManagerUtil.getEntityManager().getTransaction().commit();
EntityManagerUtil.getEntityManager().close();
if you do this is try/catch (recommended) you can do the EntityManagerUtil.getEntityManager().getTransaction().rollback(); It's needed when you are doing some changes on the DB.
I use ThreadLocal to be sure that there will be 1 thread for every user.