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);
Related
I have 2 entities (User and Group) in a many-to-many relantionship. Therefore, I created the table IsIn, which is composed by userId, groupId (composed primary key) and 2 extra fields (typeId and isBlocked). I followed Vlad Mihalcea's tutorial on how to map the entities in such a situation -> see here
However, when I try to delete a user or a group, it doesn't work. I get the following error:
ERROR: Unknown column 'groups0_.user_userId' in 'field list'
javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
I will post below my classes.
UserGroupId (Embedded)
package Embedded;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import java.io.Serializable;
import java.util.Objects;
#Embeddable
public class UserGroupId implements Serializable {
#Column(name = "userId")
private int userId;
#Column(name = "groupId")
private int groupId;
public UserGroupId() {}
public UserGroupId(int userId, int groupId) {
this.userId = userId;
this.groupId = groupId;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass())
return false;
UserGroupId that = (UserGroupId) o;
return Objects.equals(userId, that.userId) &&
Objects.equals(groupId, that.groupId);
}
#Override
public int hashCode() {
return Objects.hash(userId, groupId);
}
}
IsIn
package entity;
import Embedded.UserGroupId;
import javax.persistence.*;
import java.util.Objects;
#Entity
#Table(name = "isin")
public class IsIn {
#EmbeddedId
private UserGroupId id;
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("userId")
private User user;
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("groupId")
private Group group;
#OneToOne
#JoinColumn(name = "typeId")
private UserType typeId;
#Column(name = "isBlocked", nullable = false)
private boolean isBlocked;
public IsIn() {}
public IsIn(User user, Group group) {
this.user = user;
this.group = group;
this.id = new UserGroupId(user.getUserId(), group.getGroupId());
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass())
return false;
IsIn that = (IsIn) o;
return Objects.equals(user, that.user) &&
Objects.equals(group, that.group);
}
#Override
public int hashCode() {
return Objects.hash(user, group);
}
public User getUser() {
return user;
}
public Group getGroup() {
return group;
}
public void setUser(User user) {
this.user = user;
}
public void setGroup(Group group) {
this.group = group;
}
public UserType getTypeId() {
return typeId;
}
public void setTypeId(UserType typeId) {
this.typeId = typeId;
}
public boolean isBlocked() {
return isBlocked;
}
public void setBlocked(boolean blocked) {
isBlocked = blocked;
}
}
User
package entity;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
#Entity
#Table(name = "`user`")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "userId" ,unique = true, nullable = false)
private int userId;
#OneToMany(
mappedBy = "user",
cascade={CascadeType.ALL},
orphanRemoval = true
)
private List<IsIn> groups = new ArrayList<>();
#Column(name = "customerName", nullable = false)
private String customerName;
#Column(name = "password", nullable = false)
private String password;
#Column(name = "email", nullable = false, unique = true)
private String email;
#Column(name = "is_active", nullable = false)
private boolean is_active;
#Column(name = "notificationType", nullable = false)
private String notificationType;
#Column(name = "create_date", nullable = false)
private String create_date;
public User() { }
public User(String customerName, String password, String email, boolean is_active, String notificationType, String create_date) {
this.customerName = customerName;
this.password = password;
this.email = email;
this.is_active = is_active;
this.notificationType = notificationType;
this.create_date = create_date;
}
public void addGroup(Group group) {
IsIn isIn = new IsIn(this, group);
groups.add(isIn);
}
public void removeGroup(Group group) {
for (Iterator<IsIn> iterator = groups.iterator();
iterator.hasNext(); ) {
IsIn isIn = iterator.next();
if (isIn.getUser().equals(this) &&
isIn.getGroup().equals(group)) {
iterator.remove();
isIn.setUser(null);
isIn.setGroup(null);
}
}
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public boolean isIs_active() {
return is_active;
}
public void setIs_active(boolean is_active) {
this.is_active = is_active;
}
public String getNotificationType() {
return notificationType;
}
public void setNotificationType(String notificationType) {
this.notificationType = notificationType;
}
public String getCreate_date() {
return create_date;
}
public void setCreate_date(String create_date) {
this.create_date = create_date;
}
}
Group
package entity;
import org.hibernate.annotations.NaturalIdCache;
import javax.persistence.*;
import java.util.Objects;
#Entity
#Table(name = "`group`")
#NaturalIdCache
public class Group {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "groupId")
private int groupId;
#Column(name = "groupName")
private String groupName;
#Column(name = "create_date", nullable = false)
private String create_date;
#OneToOne(fetch=FetchType.EAGER, cascade=CascadeType.ALL, orphanRemoval=true)
#JoinColumn(name = "created_by", nullable = false)
private User user;
#Column(name = "isPrivate")
private boolean isPrivate;
public Group() { }
public Group(String groupName, String create_date, User user, boolean isPrivate) {
this.groupName = groupName;
this.create_date = create_date;
this.user = user;
this.isPrivate = isPrivate;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass())
return false;
Group group = (Group) o;
return Objects.equals(groupId, group.getGroupId());
}
#Override
public int hashCode() { return Objects.hash(groupId); }
public int getGroupId() {
return groupId;
}
public void setGroupId(int groupId) {
this.groupId = groupId;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public String getCreate_date() {
return create_date;
}
public void setCreate_date(String create_date) {
this.create_date = create_date;
}
public boolean isPrivate() {
return isPrivate;
}
public void setPrivate(boolean aPrivate) {
isPrivate = aPrivate;
}
public User getCreated_by() {
return user;
}
public void setCreated_by(User user) {
this.user = user;
}
}
And here is my delete method (which works for other entities, except for User and Group).
public static void deleteUserById(int userId) {
Session session = sessionFactory.openSession();
try{
session.beginTransaction();
User u = UserDAO.getUserById(userId);
session.delete(u);
session.flush();
session.getTransaction().commit();
} catch (HibernateException he) {
he.printStackTrace();
}
finally {
session.close();
}
}
Any kind of help is highly appreciated, thank you for your time.
Table DDLs
CREATE TABLE IF NOT EXISTS `chatapp`.`user` (
`userId` INT NOT NULL UNIQUE AUTO_INCREMENT,
`customerName` VARCHAR(50) NOT NULL,
`password` VARCHAR(50) NOT NULL,
`email` VARCHAR(255) NOT NULL unique,
`is_active` boolean NOT NULL,
`notificationType` VARCHAR(50) NOT NULL,
`create_date` VARCHAR(50) NOT NULL,
PRIMARY KEY (`userId`),
INDEX `userId_idx` (`userId` ASC)
);
CREATE TABLE IF NOT EXISTS `chatapp`.`group` (
`groupId` INT NOT NULL UNIQUE AUTO_INCREMENT,
`groupName` VARCHAR(255) NULL,
`create_date` VARCHAR(50) NOT NULL,
`created_by` INT NOT NULL,
`isPrivate` boolean NOT NULL,
PRIMARY KEY (`groupId`),
INDEX `groupId_idx` (`groupId` ASC),
FOREIGN KEY (`created_by`) REFERENCES `user` (`userId`)
);
CREATE TABLE IF NOT EXISTS `chatapp`.`isin` (
`userId` INT NOT NULL,
`groupId` INT NOT NULL,
`typeId` INT NOT NULL,
`isBlocked` boolean NOT NULL,
PRIMARY KEY (`userId`,`groupId`),
FOREIGN KEY (`userId`) REFERENCES `user` (`userId`),
FOREIGN KEY (`groupId`) REFERENCES `group` (`groupId`),
FOREIGN KEY (`typeId`) REFERENCES `usertype` (`typeId`)
);
Full StackTrace
here
Complete Database design
here
The #JoinColumn annotations are missing in the IsIn class.
It should look like
#Entity
#Table(name = "isin")
public class IsIn {
#EmbeddedId
private UserGroupId id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn("userId")
private User user;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn("groupId")
private Group group;
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 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 have 2 problems with data insertion into MySQL-tables throug Hibernate. There are 4 tables:
Client, Account, Bank and Bank_Client. Client sets many-to-many association with Bank and one-to-many with Account. Bank_Client is intermediate join table betwen Client and Bank. Here it is issues:
a. If I save clientA and clientB only (take a look on Main.java) then there is only their properties' values are saved in tables. I pointed out cascade attribute in #ManyToMany and, If I understand correctly, it obliges save() to persist all the entities on which client-entity has references. But it doesn't. If I save all the objects(clientA, clientB, bankA, bankB, accountAClientA, accountBClientA) - everything works out. But the question - how to save all the referenced objects by saving the client-entity only;
b. In any abovementioned cases the data are not saved in Bank_Account.
I would appreciate any pieces of advice. Thank you in advance.
CREATE TABLE client(client_id INT(3) AUTO_INCREMENT,
first_name VARCHAR(15) NOT NULL,
second_name VARCHAR(15) NOT NULL,
PRIMARY KEY(client_id));
CREATE TABLE account(account_id INT(3) AUTO_INCREMENT,
account_number VARCHAR(12) NOT NULL,
amount DECIMAL(10,2) NOT NULL,
currency VARCHAR(3) NOT NULL,
client_id INT(3) NOT NULL,
PRIMARY KEY(account_id),
FOREIGN KEY(client_id) REFERENCES client(client_id));
CREATE TABLE bank(bank_id INT(3) AUTO_INCREMENT,
bank_name VARCHAR(15) NOT NULL,
PRIMARY KEY(bank_id));
CREATE TABLE bank_client(client_id INT(3) NOT NULL,
bank_id INT(3) NOT NULL,
PRIMARY KEY(client_id, bank_id),
FOREIGN KEY(client_id) REFERENCES client(client_id),
FOREIGN KEY(bank_id) REFERENCES bank(bank_id));
Account.java
#Entity
#Table(name = "account")
public class Account {
private int accountID;
private String accountNumber;
private float amount;
private String currency;
private Client clientID;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "account_id")
public int getAccountID() {
return accountID;
}
public void setAccountID(int accountID) {
this.accountID = accountID;
}
#Column(name = "account_number")
public String getAccountNumber() {
return accountNumber;
}
public void setAccountNumber(String accountNumber) {
this.accountNumber = accountNumber;
}
#Column(name = "amount")
public float getAmount() {
return amount;
}
public void setAmount(float amount) {
this.amount = amount;
}
#Column(name = "currency")
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "client_id")
public Client getClientID() {
return clientID;
}
public void setClientID(Client clientID) {
this.clientID = clientID;
}
}
Bank.java
#Entity
#Table(name = "bank")
public class Bank {
private int bankID;
private String bankName;
private Set<Client> setOfClients;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "bank_id")
public int getBankID() {
return bankID;
}
public void setBankID(int bankID) {
this.bankID = bankID;
}
#Column(name = "bank_name")
public String getBankName() {
return bankName;
}
public void setBankName(String bankName) {
this.bankName = bankName;
}
#ManyToMany(mappedBy = "setOfBanks")
public Set<Client> getSetOfClients() {
return setOfClients;
}
public void setSetOfClients(Set<Client> setOfClients) {
this.setOfClients = setOfClients;
}
}
Client.java
#Entity
#Table(name = "client")
public class Client {
private int clientID;
private String firstName;
private String secondName;
private Set<Account> setOfAccounts;
private Set<Bank> setOfBanks;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "client_id")
public int getClientID() {
return clientID;
}
public void setClientID(int clientID) {
this.clientID = clientID;
}
#Column(name = "first_name")
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#Column(name = "second_name")
public String getSecondName() {
return secondName;
}
public void setSecondName(String secondName) {
this.secondName = secondName;
}
#OneToMany(mappedBy = "clientID")
public Set<Account> getSetOfAccounts() {
return setOfAccounts;
}
public void setSetOfAccounts(Set<Account> setOfAccounts) {
this.setOfAccounts = setOfAccounts;
}
#ManyToMany(targetEntity = Bank.class, cascade = {CascadeType.ALL})
#JoinTable(
name = "bank_client",
joinColumns = {#JoinColumn(name = "client_id", nullable = false, referencedColumnName = "client_id")},
inverseJoinColumns = {#JoinColumn(name = "bank_id", nullable = false, referencedColumnName = "bank_id")}
)
public Set<Bank> getSetOfBanks() {
return setOfBanks;
}
public void setSetOfBanks(Set<Bank> setOfBanks) {
this.setOfBanks = setOfBanks;
}
}
Main.java
public class Main {
public static void main(final String[] args) throws Exception {
Session session = SessionFactoryUtil.getSessionFactory().openSession();
Bank bankA = new Bank();
Bank bankB = new Bank();
Client clientA = new Client();
Client clientB = new Client();
Account accountAClientA = new Account();
Account accountBClientA = new Account();
bankA.setBankID(1);
bankA.setBankName("Deutch Bank AG");
bankA.setBankID(2);
bankB.setBankName("Barclays");
clientA.setClientID(1);
clientA.setFirstName("Alex");
clientA.setSecondName("Modoro");
clientB.setClientID(2);
clientB.setFirstName("Fedor");
clientB.setSecondName("Fokin");
accountAClientA.setAccountID(1);
accountAClientA.setAccountNumber("123456789120");
accountAClientA.setAmount(12000.00f);
accountAClientA.setCurrency("USD");
accountAClientA.setClientID(clientA);
accountBClientA.setAccountID(2);
accountBClientA.setAccountNumber("123456789156");
accountBClientA.setAmount(56020.00f);
accountBClientA.setCurrency("EUR");
accountBClientA.setClientID(clientA);
HashSet<Account> setOfAccountsClientA = new HashSet<Account>();
HashSet<Bank> setOfBanksClientA = new HashSet<Bank>();
HashSet<Account> setOfAccountsClientB = new HashSet<Account>();
HashSet<Bank> setOfBanksClientB = new HashSet<Bank>();
HashSet<Client> setOfClientsBankA = new HashSet<Client>();
HashSet<Client> setOfClientsBankB = new HashSet<Client>();
setOfAccountsClientA.add(accountAClientA);
setOfAccountsClientA.add(accountBClientA);
setOfBanksClientA.add(bankA);
setOfBanksClientA.add(bankB);
setOfClientsBankA.add(clientA);
setOfClientsBankA.add(clientB);
try {
session.getTransaction().begin();
// session.save(bankA);
// session.save(bankB);
session.save(clientA);
session.save(clientB);
// session.save(accountAClientA);
// session.save(accountBClientA);
session.getTransaction().commit();
} catch (Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}
SessionFactoryUtil.java
public class SessionFactoryUtil {
private static SessionFactory sessionFactory;
private static ServiceRegistry serviceRegistry;
private static ServiceRegistryBuilder registryBuilder;
private static SessionFactory buildSessionFactory() {
try {
Configuration configuration = new Configuration().configure();
registryBuilder = new ServiceRegistryBuilder().applySettings(configuration.getProperties());
serviceRegistry = registryBuilder.buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (HibernateException e) {
e.printStackTrace();
}
return sessionFactory;
}
public static SessionFactory getSessionFactory() {
return buildSessionFactory();
}
public static void closeSessionFactory() {
if (sessionFactory != null) {
sessionFactory.close();
}
}
}
To answer your question. To make cascading work you need to set all related objects to each other. You're not adding any of Banks to Clients. I suppose you should have method that adds Bank to Client's setOfBanks, and do clientA.addBank(bankA) before saving clientA.
And you really need to think about how your objects related to each other. In normal world you got the bank first, then people become clients of the bank and open their accounts in it. So bank should not be saved by cascading. It should already exist before saving client.
I'm getting data from database as below in my Java EE app.
WdLeavesSupplier supplier = entityManager.getEntityManager()
.find(WdLeavesSupplier.class,
Integer.parseInt(supplier_id));
There is a column as active in this entity. I have inserted some data into this and value of active column is on in those records. When i'm retrieving data as above, i'm getting null as value of active column. Other columns(name, address, etc..) values getting correctly.
Database record like this.
supplier_id, supplier_code, supplier_first_name, supplier_last_name, supplier_phone, supplier_address_a, supplier_address_b, center_id, active, comment, created_date
14, 't1', 'Mark', 'Smith', '0711234224', 'g45, new town', 'Galle', 41, 'on', 'test comment', '2014-06-24 17:06:38'
Here is the table structure.
CREATE TABLE `wdtccdb`.`wd_leaves_supplier` (
`supplier_id` int(10) unsigned NOT NULL auto_increment,
`supplier_code` varchar(45) NOT NULL default '',
`supplier_first_name` varchar(45) NOT NULL default '',
`supplier_last_name` varchar(45) default NULL,
`supplier_phone` varchar(45) default NULL,
`supplier_address_a` varchar(45) default NULL,
`supplier_address_b` varchar(45) default NULL,
`center_id` int(10) unsigned NOT NULL default '0',
`active` varchar(5) default NULL,
`comment` varchar(100) default NULL,
`created_date` timestamp NOT NULL default CURRENT_TIMESTAMP,
PRIMARY KEY (`supplier_id`),
UNIQUE KEY `supp_code_un` (`supplier_code`),
KEY `FK_wd_leaves_supplier_center_id` (`center_id`),
CONSTRAINT `FK_wd_leaves_supplier_center_id` FOREIGN KEY (`center_id`) REFERENCES `wd_collection_center` (`center_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Entity Class Link
Entity Class Code
package com.wd.entity;
import java.io.Serializable;
import javax.persistence.*;
import java.sql.Timestamp;
import java.util.List;
/**
* The persistent class for the wd_leaves_supplier database table.
*
*/
#Entity
#Table(name = "wd_leaves_supplier")
#NamedQueries({
#NamedQuery(name = "WdLeavesSupplier.findAll", query = "SELECT u FROM WdLeavesSupplier u"),
#NamedQuery(name = "WdLeavesSupplier.findByCode", query = "SELECT u FROM WdLeavesSupplier u WHERE u.supplierCode = :code") })
public class WdLeavesSupplier implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "supplier_id")
private int supplierId;
private String active;
private String comment;
#Column(name = "created_date")
private Timestamp createdDate;
#Column(name = "supplier_address_a")
private String supplierAddressA;
#Column(name = "supplier_address_b")
private String supplierAddressB;
#Column(name = "supplier_code")
private String supplierCode;
#Column(name = "supplier_first_name")
private String supplierFirstName;
#Column(name = "supplier_last_name")
private String supplierLastName;
#Column(name = "supplier_phone")
private String supplierPhone;
// bi-directional many-to-one association to WdLeafPurchase
#OneToMany(mappedBy = "wdLeavesSupplier")
private List<WdLeafPurchase> wdLeafPurchases;
// bi-directional many-to-one association to WdCollectionCenter
#ManyToOne
#JoinColumn(name = "center_id")
private WdCollectionCenter wdCollectionCenter;
// bi-directional many-to-one association to WdSupplierLoan
#OneToMany(mappedBy = "wdLeavesSupplier")
private List<WdSupplierLoan> wdSupplierLoans;
public WdLeavesSupplier() {
}
public int getSupplierId() {
return this.supplierId;
}
public void setSupplierId(int supplierId) {
this.supplierId = supplierId;
}
public String getActive() {
return this.active;
}
public void setActive(String active) {
this.active = active;
}
public String getComment() {
return this.comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public Timestamp getCreatedDate() {
return this.createdDate;
}
public void setCreatedDate(Timestamp createdDate) {
this.createdDate = createdDate;
}
public String getSupplierAddressA() {
return this.supplierAddressA;
}
public void setSupplierAddressA(String supplierAddressA) {
this.supplierAddressA = supplierAddressA;
}
public String getSupplierAddressB() {
return this.supplierAddressB;
}
public void setSupplierAddressB(String supplierAddressB) {
this.supplierAddressB = supplierAddressB;
}
public String getSupplierCode() {
return this.supplierCode;
}
public void setSupplierCode(String supplierCode) {
this.supplierCode = supplierCode;
}
public String getSupplierFirstName() {
return this.supplierFirstName;
}
public void setSupplierFirstName(String supplierFirstName) {
this.supplierFirstName = supplierFirstName;
}
public String getSupplierLastName() {
return this.supplierLastName;
}
public void setSupplierLastName(String supplierLastName) {
this.supplierLastName = supplierLastName;
}
public String getSupplierPhone() {
return this.supplierPhone;
}
public void setSupplierPhone(String supplierPhone) {
this.supplierPhone = supplierPhone;
}
public List<WdLeafPurchase> getWdLeafPurchases() {
return this.wdLeafPurchases;
}
public void setWdLeafPurchases(List<WdLeafPurchase> wdLeafPurchases) {
this.wdLeafPurchases = wdLeafPurchases;
}
public WdCollectionCenter getWdCollectionCenter() {
return this.wdCollectionCenter;
}
public void setWdCollectionCenter(WdCollectionCenter wdCollectionCenter) {
this.wdCollectionCenter = wdCollectionCenter;
}
public List<WdSupplierLoan> getWdSupplierLoans() {
return this.wdSupplierLoans;
}
public void setWdSupplierLoans(List<WdSupplierLoan> wdSupplierLoans) {
this.wdSupplierLoans = wdSupplierLoans;
}
}
How can i fix this error ?