I have a request table related to 2 tables where I save the request number according to the type of request that can be a request for water analysis and request for soil analysis, but when I try to delete or update the request table I get the error
Cannot delete or update a parent row: a foreign key constraint fails
My code that implements the relationships is the following is the following
//class for request
#Entity
#Table(name = "solicitud")
public class Solicitud implements Serializable{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
//#Column(unique=true)
//private String codigo;
#ManyToOne(fetch = FetchType.LAZY)
private Estado estado;
#DateTimeFormat(pattern = "yyyy-MM-dd")
#Temporal(TemporalType.DATE)
#NotNull
#Column(name="fecha")
private Date fecha;
#JsonIgnore
#ManyToOne(fetch = FetchType.LAZY)
private Usuario usuario;
#JsonIgnore
#ManyToOne(fetch = FetchType.LAZY)
private Usuario teclab;
#JsonIgnore
#ManyToOne(fetch = FetchType.LAZY)
private TipoMuestra tmuestra;
//#Min(value = 0L, message = "Debe ingresar un valor positivo")
//#Pattern(regexp = "[\\s]*[0-9]*[1-9]+",message="msg")
#NotNull
private Integer numMuestras;
int year = 0;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Estado getEstado() {
return estado;
}
public void setEstado(Estado estado) {
this.estado = estado;
}
public Date getFecha() {
return fecha;
}
public void setFecha(Date fecha) {
this.fecha = fecha;
}
public Usuario getUsuario() {
return usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
public TipoMuestra getTmuestra() {
return tmuestra;
}
public void setTmuestra(TipoMuestra tmuestra) {
this.tmuestra = tmuestra;
}
public Integer getNumMuestras() {
return numMuestras;
}
public void setNumMuestras(Integer numMuestras) {
this.numMuestras = numMuestras;
}
public Usuario getTeclab() {
return teclab;
}
public void setTeclab(Usuario teclab) {
this.teclab = teclab;
}
/*#PostPersist
public void generateCode() {
CodigoAgua agua=new CodigoAgua();
agua.setSolicitud(this);
agua.generateCode();
}*/
/**
*
*/
private static final long serialVersionUID = 1L;
}
//class for save number for type request water analysis
#Entity
#Table(name = "cagua")
public class CodigoAgua implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(unique=true)
private String codigo;
#OneToOne(fetch=FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name="solicitud_id")
private Solicitud solicitud;
int year = 0;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getCodigo() {
return codigo;
}
public void setCodigo(String codigo) {
this.codigo = codigo;
}
public Solicitud getSolicitud() {
return solicitud;
}
public void setSolicitud(Solicitud solicitud) {
this.solicitud = solicitud;
}
#PostPersist
public void generateCode() {
Date date = new Date();
LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
year = localDate.getYear();
this.codigo=year +" - "+id+" - A";
System.out.println("Codigo solicitud creado"+id+this.getSolicitud().getId());
}
/**
*
*/
private static final long serialVersionUID = 1L;
}
//class for save number for type request soil analysis
#Entity
#Table(name = "csuelo")
public class CodigoSuelo implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(unique=true)
private String codigo;
#OneToOne(fetch=FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name="solicitud_id")
private Solicitud solicitud;
int year = 0;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getCodigo() {
return codigo;
}
public void setCodigo(String codigo) {
this.codigo = codigo;
}
public Solicitud getSolicitud() {
return solicitud;
}
public void setSolicitud(Solicitud solicitud) {
this.solicitud = solicitud;
}
#PostPersist
public void generateCode() {
Date date = new Date();
LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
year = localDate.getYear();
this.codigo=year +" - "+id+" - S";
System.out.println("Codigo solicitud creado"+id+this.getSolicitud().getId());
}
/**
*
*/
private static final long serialVersionUID = 1L;
}
This message indicates that you want to delete a row from table1, while its primary key is present as a foreign key in table2.
To delete a record from table1, you must delete all the lines that refer to it in the other tables in order to be able to delete this record.
I hope I've helped you
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 make a table, let's say table's name is Car. It will has 3 column, brandId, typeId and sizeId. I want all of the columns to be primary key. typeId and sizeId are column from different table. I already try to make code using #IdClass. But, error "No supertype found" appear.
This is Entity clas :
#Entity
#IdClass(CarPk.class)
#Table(name = "CAR")
public class Car implements Serializable {
private static final long serialVersionUID = -1576946068763487642L;
public Car() {
}
public Car(String brandId, TypeId typeId, SizeId sizeId) {
this.brandId = brandId;
this.typeId = typeId;
this.sizeId = sizeId;
}
#Id
#Column(name = "BRAND_ID", nullable = false, length = 20)
private String brandId;
#Id
#ManyToOne
#JoinColumn(name = "TYPE_ID", nullable = false)
private TypeId typeId;
#Id
#ManyToOne
#JoinColumn(name = "SIZE_ID", nullable = false)
private SizeId sizeId;
public String getBrandId() {
return brandId;
}
public void setBrandId(String brandId) {
this.brandId= brandId;
}
public TypeId getTypeId() {
return typeId;
}
public void setTypeId (TypeId typeId) {
this.typeId= typeId;
}
public SizeId getSizeId() {
return sizeId;
}
public void setSizeId (SizeId sizeId) {
this.sizeId= sizeId;
}
}
And this is CarPk class :
public class CarPk implements Serializable {
private static final long serialVersionUID = -1576946068763487642L;
public CarPk() {
}
public CarPk(String brandId, TypeId typeId, SizeId sizeId) {
this.brandId = brandId;
this.typeId = typeId;
this.sizeId = sizeId;
}
private String brandId;
private TypeId typeId;
private SizeId sizeId;
public String getBrandId() {
return brandId;
}
public void setBrandId(String brandId) {
this.brandId= brandId;
}
public TypeId getTypeId() {
return typeId;
}
public void setTypeId (TypeId typeId) {
this.typeId= typeId;
}
public SizeId getSizeId() {
return sizeId;
}
public void setSizeId (SizeId sizeId) {
this.sizeId= sizeId;
}
}
What is wrong this code?
Thank you anyway
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 use Hibernate and
have two entities(City and Region) with OneToMany relation.
the First:
#Entity
#Table(name = "p_region")
public class Region implements Serializable{
#OneToMany(mappedBy = "region",fetch= FetchType.LAZY, cascade = CascadeType.MERGE)
private List<City> citys;
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
//++++++++++++++++++++ GETSET
public List<City> getCitys() {
return citys;
}
public void setCitys(List<City> citys) {
this.citys = citys;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and the second one:
#Entity
#Table(name = "p_city")
public class City implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#NotEmpty(message = "Название не должно быть пустым")
#Length(max = 10, min = 2, message = "Название должно быть менее 2 символов и не
более 100")
private String cityName;
#NotEmpty(message = "Код города не должно быть пустым")
private String cityCode;
#Column(name = "zone")
private Integer zone;
#Basic(optional = true)
#Temporal(javax.persistence.TemporalType.TIMESTAMP)
private Date entryDate = Calendar.getInstance().getTime();
#ManyToOne()
private Region region;
#Basic(optional = true)
private String zip_code;
// GET SET ::::::::::::::::::::::::::::::::::
public Integer getZone() {
return zone;
}
public void setZone(Integer zone) {
this.zone = zone;
}
public Region getRegion() {
return region;
}
public void setRegion(Region region) {
this.region = region;
}
public void delete() {
System.out.println("QQQQQQQQQQQQQQQQQQQQQQ");
}
public String getCityCode() {
return cityCode;
}
public void setCityCode(String cityCode) {
this.cityCode = cityCode;
}
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
public Date getEntryDate() {
return entryDate;
}
public void setEntryDate(Date entryDate) {
this.entryDate = entryDate;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getZip_code() {
return zip_code;
}
public void setZip_code(String zip_code) {
this.zip_code = zip_code;
}
}
When I try to get simple Object(City) with JSON it returns the cycle:
{"id":577,"region":{"name":"нет региона","id":15,"citys":[{"id":577,"region":
{"name":"нет региона","id":15,"citys":[{"id":577,"region":{"name":"нет
региона","id":15,"citys":[{"id":577,"region":{"name":"нет
региона","id":15,"citys":[{"id":577,"region":{"name":"нет
региона","id":15,"citys":[{"id":577,"region":{"name":"нет
региона","id":15,"citys":[{"id":577,"region":{"name":"нет......so on.
Are there any solutions for this issue?
You need to break the bi-directional relationship between your entity before converting to JSON.
I think there are two options:
Iterate the child collection, e.g. citys in Region and set Region to null. This way, circular dependency would be broken. You my want to add one name mapped attribute regionId in the City so that relational info is still available.
Create another set of POJO objects without circular dependency, copy the values from Entity Objects and then get the JSON using POJO objects.