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.
Related
I have a question about hibernate query. I am using hiberate 5.3.10.
First of all, I have domain Parent.java, ParentAlert.java and ParentAlertDetail.java like follow:
Parent:
public class Parent {
private String parentId;
private List<ParentAlert> parentAlerts;
#Id
#Column(name = "Parent_id", length = 12)
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
#OneToMany(
targetEntity = ParentAlert.class,
mappedBy = "parentAlert",
fetch = FetchType.LAZY)
public List<ParentAlert> getParentAlerts() {
return parentAlerts;
}
public void setParentAlerts(List<ParentAlert> parentAlerts) {
this.parentAlerts = parentAlerts;
}}
ParentAlert:
public class ParentAlert {
private String parentAlertID;
private Parent parent;
private Collection<ParentAlertDetail> parentAlertDetails;
private String status;
#Id
#Column(name = "Parent_Alert_ID", length = 12)
#NotEmpty
public String getParentAlertID() {
return parentAlertID;
}
public void setParentAlertID(String parentAlertID) {
this.parentAlertID = parentAlertID;
}
#OneToOne(targetEntity = Parent.class, fetch = FetchType.LAZY)
#JoinColumn(name = "Parent_id")
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
#OneToMany(targetEntity = ParentAlertDetail.class, mappedBy = "id.parentAlert", fetch = FetchType.LAZY, cascade = {
CascadeType.ALL })
public Collection<ParentAlertDetail> getParentAlertDetails() {
return parentAlertDetails;
}
public void setParentAlertDetails(Collection<ParentAlertDetail> parentAlertDetails) {
this.parentAlertDetails = parentAlertDetails;
}
#Column(name = "status", nullable = false, length = 1)
public String getStatus() {
return this.status;
}
public void setStatus(String status) {
this.status = status;
}}
ParentAlertDetail
public class ParentAlertDetail{
private ParentAlertDetailID id;
private String desc;
private String status;
#EmbeddedId
#AttributeOverrides(value = { #AttributeOverride(name = "parentAlert", column = #Column(name = "Parent_Alert_Id")),
#AttributeOverride(name = "parentAlertDetailId", column = #Column(name = "Parent_Alert_Detail_id")) })
public ParentAlertDetailID getId() {
return id;
}
public void setId(ParentAlertDetailID id) {
this.id = id;
}
#Column(name = "desc", length = 100)
public String getDesc() {
return this.desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
#Column(name = "Status", length = 1)
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}}
ParentAlertDetailID
public class ParentAlertDetailID{
private Integer parentAlertDetailId;
private ParentAlert parentAlert;
#Column(name = "Parent_Alert_Detail_id")
#NotEmpty
public Integer getParentAlertDetailId() {
return parentAlertDetailId;
}
public void setParentAlertDetailId(Integer parentAlertDetailId) {
this.parentAlertDetailId = parentAlertDetailId;
}
#ManyToOne(targetEntity = ParentAlert.class, fetch = FetchType.LAZY)
#JoinColumn(name = "Parent_Alert_ID", nullable = true)
public ParentAlert getParentAlert() {
return parentAlert;
}
public void setParentAlert(ParentAlert parentAlert) {
this.parentAlert = parentAlert;
} }
I would like to filter the parentAlert.status = 'A' and parentAlertDetail.status = 'A'.
The query is
String sql = "SELECT distinct parent FROM Parent parent"
+ " LEFT OUTER JOIN fetch parent.parentAlerts patientAlert"
+ " LEFT OUTER JOIN patientAlert.patientAlertDetails patientAlertDetail"
+ " WHERE (patientAlert.status ='A' or patientAlert.status is null) "
+ " and (patientAlertDetail.status ='A' or patientAlertDetail.status is null)";
Query query = getCurrentSession().createQuery(sql);
List<Parent> resultList = query.getResultList();
However, I found that the records under PatientAlertDetail cannot be filter (mean that patientAlertDetail.status = 'I' records selected also)
May I ask anything wrong in my query or domain?
Also, is it possible to fetch all tables in parent domain without using fetch in the query? This is because I have more than one child domain in Parent (e.g. ParentContact etc)
Thanks.
Hello I have a one to many relationship between a reservation and rooms and its unidirectional. A reservation might have one to several rooms. Now I'm trying to search if a room is available based on certain dates, and type of room(i.e a king or queen).
My solution:
Find Rooms that are not present in the reservation table based and also based on the date criteria.
Room model:
#Entity
#Table(name="room")
public class Room implements java.io.Serializable {
private static final long serialVersionUID = 10L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="roomId", nullable = false)
private long Id;
#Column(name="roomNumber", length = 4, nullable = false) //room number with max length of 4 digits
private String roomNumber;
#Column(name="type", nullable = false, length=10) //queen or king
private String roomType;
#Column(name="properties", nullable = false, length=15) //smoking or non-smoking
private String roomProperties;
#Column(name="price", columnDefinition = "DECIMAL(10,2)", nullable = false) //sets the precision of price to 2 decimal places
private double price;
public Room() {}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public long getId() {
return Id;
}
public void setId(long id) {
this.Id = id;
}
public String getRoomNumber() {
return roomNumber;
}
public void setRoomNumber(String roomNumber) {
this.roomNumber = roomNumber;
}
public String getRoomType() {
return roomType;
}
public void setRoomType(String roomType) {
this.roomType = roomType;
}
public String getRoomProperties() {
return roomProperties;
}
public void setRoomProperties(String roomProperties) {
this.roomProperties = roomProperties;
}
}
Reservation Table:
#Entity
#Table(name="Reservation")
public class Reservation implements Serializable {
private static final Long serialVersionUID = 100L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="reservation_Id", nullable = false)
private long Id;
public long getId() {
return Id;
}
public void setId(long id) {
Id = id;
}
#Column(name="CheckInDate")
private Date checkInDate;
#Column(name="CheckOutDate")
private Date checkOutDate;
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name = "guestId", nullable = false)
private Guest guest;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinTable(name = "ReservedRooms", joinColumns = {#JoinColumn(name="resId",
referencedColumnName = "reservation_Id")}, inverseJoinColumns = {#JoinColumn(name="roomId",
referencedColumnName = "roomId")})
private List<Room> roomList;
#Column(name="roomsWanted")
private int roomsWanted;
public int getRoomsWanted() {
return roomsWanted;
}
public void setRoomsWanted(int roomsWanted) {
this.roomsWanted = roomsWanted;
}
public Date getCheckInDate() {
return checkInDate;
}
public void setCheckInDate(Date checkInDate) {
this.checkInDate = checkInDate;
}
public Date getCheckOutDate() {
return checkOutDate;
}
public void setCheckOutDate(Date checkOutDate) {
this.checkOutDate = checkOutDate;
}
public Guest getGuest() {
return guest;
}
public void setGuest(Guest guest) {
this.guest = guest;
}
public List<Room> getRoomList() {
return roomList;
}
public void setRoomList(List<Room> roomList) {
this.roomList = roomList;
}
}
Now method to perform the search availability:
#Override
#Transactional
#SuppressWarnings("unchecked")
public boolean checkAvailability(SearchCriteria searchCriteria) {
String hql = "from Room as r where r.roomType = :roomType1 and r.roomProperties = :roomProperties1 " +
"and r.Id not in (Select res.roomList.Id from Reservation as res left outer join res.roomList " +
"where res.checkInDate <=:checkInDate1 and res.checkOutDate >= :checkOutDate1 " +
" and R.Id = res.roomList.Id) ";
Query query = getSession().createQuery(hql);
query.setParameter("roomType1", searchCriteria.getRoomType());
query.setParameter("roomProperties1", searchCriteria.getRoomProperties());
query.setParameter("checkInDate1", searchCriteria.getCheckInDate());
query.setParameter("checkOutDate1", searchCriteria.getCheckOutDate());
List<Room> roomList = query.list();
if(roomList.isEmpty()) {
return true;
}
return false;
}
But it complains and gives the error:
illegal attempt to dereference collection [reservatio1_.reservation_Id.roomList] with element property reference [Id]
Please what I'm doing wrong as I'm new to hibernate
When you join a collection, you have to name it. You can't use it directly (dereference).
in (Select ROOMS.Id from Reservation as res
left outer join res.roomList AS ROOMS
where res.checkInDate <=:checkInDate1 and res.checkOutDate >= :checkOutDate1
and R.Id = ROOMS.Id)
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);
I want to have fixed values for some fields on my DB, so I declared enums and I want to map them into the DB with that fixed values. What is the best solution for that?
Right now I've coded this (it doesn't work)
My table in the DB:
CREATE TABLE IF NOT EXISTS `sistemaFacturacion`.`formaPago` (
`id` INT NOT NULL AUTO_INCREMENT,
`tipo` INT NOT NULL,
`descripcion` VARCHAR(100) NOT NULL,
`fecha` DATETIME NOT NULL,
`plazo` INT NOT NULL,
`interes` DOUBLE NOT NULL,
`cancelado` TINYINT(1) NOT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB
POJO Class:
#Entity
#Table(name = "formaPago")
public class FormaPago implements Serializable {
/**
*
*/
private static final long serialVersionUID = -412540568702221226L;
private Integer id;
private FormaPagoEnum tipo;
#Id #GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Enumerated(EnumType.ORDINAL)
#Embedded
public FormaPagoEnum getTipo() {
return tipo;
}
public void setTipo(FormaPagoEnum tipo) {
this.tipo = tipo;
}
public FormaPago(){}
}
My enum class:
#Embeddable
public enum FormaPagoEnum {
EFECTIVO("EFECTIVO", PlazoEnum.CERO, true),
CREDITO_QUINCE("CREDITO A QUINCE DIAS", PlazoEnum.QUINCE, false),
CREDITO_TREINTA("CREDITO A TREINTA DIAS", PlazoEnum.TREINTA, false),
CREDITO_SESENTA("CREDITO A SESENTA DIAS", PlazoEnum.SESENTA, false);
private String descripcion;
private Calendar fecha;
private PlazoEnum plazo;
private boolean cancelado;
public void setDescripcion(String descripcion) {
this.descripcion = descripcion;
}
public void setFecha(Calendar fecha) {
this.fecha = fecha;
}
public void setPlazo(PlazoEnum plazo) {
this.plazo = plazo;
}
public void setCancelado(boolean cancelado) {
this.cancelado = cancelado;
}
#Column(name = "descripcion")
public String getDescripcion() {
return descripcion;
}
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "fecha", nullable = false)
public Calendar getFecha() {
return fecha;
}
#Enumerated(EnumType.ORDINAL)
#Embedded
#Column(name = "plazo")
public PlazoEnum getPlazo() {
return plazo;
}
#Column(name = "cancelado")
public boolean isCancelado() {
return cancelado;
}
FormaPagoEnum(){}
FormaPagoEnum(String descripcion, PlazoEnum plazo, boolean cancelado) {
this.descripcion = descripcion;
this.fecha = GregorianCalendar.getInstance();
this.plazo = plazo;
this.cancelado = cancelado;
}
}
if you have some other ideas that will work better, please teach me how I'm new at hibernate!
Thanks in advance!
I’m doing the following:
#Entity
#SqlResultSetMapping(name="getxxxx",
entities=#EntityResult(xxxx.class,
fields = {
#FieldResult(name="x1", column = "x1"),
#FieldResult(name="x2", column = "x2")}))
#NamedNativeQuery(name=" getxxxx ",
query="select x1, x2 from yyyy",
resultSetMapping=" getxxxx ")
} )public class xxxx{
.
.
.
public xxxx() {
}
i get an error:
"Table "xxxx" cannot be resolved", the class xxxx is not a table mapped into my source,
I’m trying to query the DB and return the results into my class
is it possible?
In this situation the first thing I would try would be to remove the #Entity annotation. And then change either the class name or the native query name so that one of them is "xxxx" and one of them is "zzzz," so that I was sure I knew which thing the runtime was complaining about.
It sounds like xxxx should not be an entity bean, since JPA is not happy with returning results in non-entity beans. You must instead call createNativeQuery with just the SQL String. Then call query.getResultList() to fetch the result as a List(Object[]) and use this to fill your non entity result bean.
A few years back I wrote a blog post, that might help you perform advanced native queries with JPA.
Yes, this is possible, but a little tricky. Here's a complex example that should cover most of the bases. In this example:
You have an INVOICE object with a due date;
Each INVOICE has a many-to-one relationship with a COMPANY;
Each INVOICE also has a zero- or one-to-many relationship with a set of ITEMS
Here is the schema:
CREATE TABLE "public"."invoice" (
id SERIAL,
company_id int,
due_date date,
PRIMARY KEY(id)
);
CREATE TABLE "public"."item" (
id SERIAL,
invoice_id int,
description text,
PRIMARY KEY(id)
);
CREATE TABLE "public"."company" (
id SERIAL,
name text,
PRIMARY KEY(id)
);
The INVOICE object (incredibly convoluted example for the sake of completeness):
#Entity
#Table(name = "invoice")
#Loader(namedQuery = "loadInvoiceObject")
#NamedNativeQuery(name="loadInvoiceObject",
query="SELECT " +
"inv.id," +
"inv.due_date," +
"co.*," +
"it.*," +
"FROM invoice inv " +
"JOIN company co ON co.id = inv.company_id " +
"LEFT OUTER JOIN item it ON it.invoice_id = inv.id " +
"WHERE inv.id = :id",
resultSetMapping = "invoicemap")
#SqlResultSetMapping(name = "invoicemap",
entities = {
#EntityResult(entityClass = Invoice.class),
#EntityResult(entityClass = Company.class),
#EntityResult(entityClass = Item.class)
}
)
public class Invoice {
private Integer id;
private Date dueDate;
private Company company;
private List<Item> items = new ArrayList<Item>();
public Invoice() { /* no-args constructor */ }
#Id
#Column(name = "id", nullable = false)
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
#Column(name = "due_date")
#Temporal(TemporalType.DATE)
public Date getDueDate() { return dueDate; }
public void setDueDate(Date dueDate) { this.dueDate = dueDate; }
#ManyToOne(optional = false)
#JoinColumn(name = "company_id", nullable = false)
public Company getCompany() { return company; }
public void setCompany(Company company) { this.company = company; }
#OneToMany(mappedBy = "invoice")
public List<Item> getItems() { return items; }
public void setItems(List<Item> items) { this.items = items; }
}
The ITEM object:
#Entity
#Table(name = "item")
public class Item {
private Integer id;
private String description;
private Invoice invoice;
public Item() { /* no-args constructor */ }
#Id
#Column(name = "id", nullable = false)
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
#Column(name = "description")
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
#ManyToOne(optional = false)
#JoinColumn(name = "invoice_id", nullable = false)
public Invoice getInvoice() { return invoice; }
public void setInvoice(Invoice invoice) { this.invoice = invoice; }
}
The COMPANY object:
#Entity
#Table(name = "company")
public class Company {
private Integer id;
private String name;
private List<Invoice> invoices = new ArrayList<Invoice>();
public Company() { /* no-args constructor */ }
#Id
#Column(name = "id", nullable = false)
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
#Column(name = "name")
public String getName() { return name; }
public void setName(String name) { this.name = name; }
#OneToMany(mappedBy = "company")
public List<Invoice> getInvoices() { return invoices; }
public void setInvoices(List<Invoice> invoices) { this.invoices = invoices; }
}