I'm trying to save a Entity with relationship many to many with extra column but I've received an error
Band.java
package it.entities;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
/**
* The persistent class for the band database table.
*
*/
#Entity
#Table(name="BAND")
#NamedQuery(name="Band.findAll", query="SELECT b FROM Band b")
public class Band implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID", unique = true, nullable = false)
private int id;
#Column(name="DESCRIZIONE")
private String descrizione;
#Column(name="NOME")
private String nome;
//bi-directional many-to-one association to Audio
#ManyToOne
#JoinColumn(name="AUDIO_ID")
private Audio audio;
//bi-directional many-to-one association to Video
#ManyToOne
#JoinColumn(name="VIDEO_ID")
private Video video;
//bi-directional many-to-one association to Citta
#ManyToOne
#JoinColumn(name="CITTA_ID")
private Citta citta;
#OneToMany(mappedBy="pk.band", fetch = FetchType.LAZY, cascade={CascadeType.ALL})
private List<BandHasMusicista> bandHasMusicista = new ArrayList<BandHasMusicista>();
public Band() {
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getDescrizione() {
return this.descrizione;
}
public void setDescrizione(String descrizione) {
this.descrizione = descrizione;
}
public String getNome() {
return this.nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public Audio getAudio() {
return this.audio;
}
public void setAudio(Audio audio) {
this.audio = audio;
}
public Video getVideo() {
return this.video;
}
public void setVideo(Video video) {
this.video = video;
}
public Citta getCitta() {
return this.citta;
}
public void setCitta(Citta citta) {
this.citta = citta;
}
// #OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.band")
public List<BandHasMusicista> getBandHasMusicista() {
return bandHasMusicista;
}
public void setBandHasMusicista(List<BandHasMusicista> bandHasMusicista) {
this.bandHasMusicista = bandHasMusicista;
}
}
BandHasMusicista.java
package it.entities;
import java.io.Serializable;
import javax.persistence.AssociationOverride;
import javax.persistence.AssociationOverrides;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Transient;
/**
* The persistent class for the band_has_musicista database table.
*
*/
#Entity
#Table(name="BAND_HAS_MUSICISTA")
#AssociationOverrides({
#AssociationOverride(name = "pk.musicista", joinColumns = #JoinColumn(name = "MUSICISTA_ID")),
#AssociationOverride(name = "pk.band", joinColumns = #JoinColumn(name = "BAND_ID"))})
#NamedQuery(name="BandHasMusicista.findAll", query="SELECT b FROM BandHasMusicista b")
public class BandHasMusicista implements Serializable {
private static final long serialVersionUID = 1L;
private BandHasMusicistaPK pk = new BandHasMusicistaPK();
private Band band;
private Musicista musicista;
private boolean bandAccept;
private boolean musicistaAccept;
public BandHasMusicista() {
}
#EmbeddedId
public BandHasMusicistaPK getPk() {
return pk;
}
public void setPk(BandHasMusicistaPK pk) {
this.pk = pk;
}
#Column(name="BAND_ACCEPT", nullable=false)
public boolean getBandAccept() {
return this.bandAccept;
}
public void setBandAccept(boolean bandAccept) {
this.bandAccept = bandAccept;
}
#Column(name="MUSICISTA_ACCEPT", nullable=false)
public boolean getMusicistaAccept() {
return this.musicistaAccept;
}
public void setMusicistaAccept(boolean musicistaAccept) {
this.musicistaAccept = musicistaAccept;
}
#Transient
// #JoinColumn(name="BAND_ID")
public Band getBand() {
return this.band;
}
public void setBand(Band band) {
this.band = band;
}
#Transient
// #JoinColumn(name="MUSICISTA_ID")
public Musicista getMusicista() {
return this.musicista;
}
public void setMusicista(Musicista musicista) {
this.musicista = musicista;
}
}
BandHasMusicistaPK.java
package it.entities;
import java.io.Serializable;
import javax.persistence.*;
/**
* The primary key class for the band_has_musicista database table.
*
*/
#Embeddable
public class BandHasMusicistaPK implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
private Band band;
private Musicista musicista;
public BandHasMusicistaPK() {
}
#ManyToOne
// #JoinColumn(name="BAND_ID")
public Band getBand() {
return this.band;
}
public void setBand(Band band) {
this.band = band;
}
#ManyToOne
// #JoinColumn(name="MUSICISTA_ID")
public Musicista getMusicista() {
return this.musicista;
}
public void setMusicista(Musicista musicista) {
this.musicista = musicista;
}
}
Musicista.java
package it.entities;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
/**
* The persistent class for the MUSICISTA database table.
*
*/
#Entity
#Table(name="MUSICISTA")
#NamedQuery(name="Musicista.findAll", query="SELECT m FROM Musicista m")
public class Musicista implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(generator="SharedPrimaryKeyGenerator")
#GenericGenerator(name="SharedPrimaryKeyGenerator", strategy="foreign", parameters = #Parameter(name="property", value="account"))
#Column(name = "ID", unique = true, nullable = false)
private int id;
#Column(name="COGNOME", nullable=false, length=155)
private String cognome;
#Temporal(TemporalType.DATE)
#Column(name="DATA_NASCITA")
private Date dataNascita;
#Column(name="NOME", nullable=false, length=155)
private String nome;
//bi-directional one-to-one association to Account
#OneToOne
#PrimaryKeyJoinColumn
private Account account;
#OneToMany(mappedBy="pk.musicista", fetch = FetchType.LAZY, cascade={CascadeType.ALL})
private List<BandHasMusicista> bandHasMusicista = new ArrayList<BandHasMusicista>();
public Musicista() {
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getCognome() {
return this.cognome;
}
public void setCognome(String cognome) {
this.cognome = cognome;
}
public Date getDataNascita() {
return this.dataNascita;
}
public void setDataNascita(Date dataNascita) {
this.dataNascita = dataNascita;
}
public String getNome() {
return this.nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public Account getAccount() {
return this.account;
}
public void setAccount(Account account) {
this.account = account;
}
// #OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.musicista")
public List<BandHasMusicista> getBandHasMusicista() {
return bandHasMusicista;
}
public void setBandHasMusicista(List<BandHasMusicista> bandHasMusicista) {
this.bandHasMusicista = bandHasMusicista;
}
}
BandLogic.java
package it.logic;
import it.entities.Band;
import it.entities.BandHasMusicista;
import it.entities.Citta;
import it.entities.Musicista;
import it.interfaces.ServiceBean;
import it.invo.AddBandInVO;
import javax.persistence.EntityManager;
public class BandLogic {
EntityManager em = null;
/**
* Default constructor.
*/
public BandLogic() {
em = ServiceBean.getEm();
}
public boolean addBand(AddBandInVO inVO) {
System.out.println("IN - addBand() INPUT = " + inVO);
Musicista musicista = em.find(Musicista.class, inVO.getAccountId());
Citta citta = em.find(Citta.class, inVO.getCitta());
if(musicista != null){
Band band = new Band();
band.setNome(inVO.getNome());
band.setDescrizione(inVO.getDescrizione());
band.setCitta(citta);
BandHasMusicista bandHasMusicista = new BandHasMusicista();
bandHasMusicista.setBand(band);
bandHasMusicista.setMusicista(musicista);
bandHasMusicista.setBandAccept(true);
bandHasMusicista.setMusicistaAccept(true);
band.getBandHasMusicista().add(bandHasMusicista);
em.persist(band);
em.flush();
em.clear();
}else{
System.out.println("Account is not Musicista");
return false;
}
System.out.println("OUT - addBand()");
return true;
}
}
The stack trace:
javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:614)
at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:307)
at it.logic.BandLogic.addBand(BandLogic.java:46)
at it.interfaces.ServiceBean.addBand(ServiceBean.java:184)
at it.test.BandTest.testAddBand(BandTest.java:25)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:176)
at junit.framework.TestCase.runBare(TestCase.java:141)
at junit.framework.TestResult$1.protect(TestResult.java:122)
at junit.framework.TestResult.runProtected(TestResult.java:142)
at junit.framework.TestResult.run(TestResult.java:125)
at junit.framework.TestCase.run(TestCase.java:129)
at junit.framework.TestSuite.runTest(TestSuite.java:255)
at junit.framework.TestSuite.run(TestSuite.java:250)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:84)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:94)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:304)
... 22 more
Caused by: java.sql.BatchUpdateException: Column 'BAND_ID' cannot be null
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2054)
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1467)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
... 28 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'BAND_ID' cannot be null
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1041)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4187)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4119)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2570)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2731)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2815)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2458)
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2006)
... 31 more
In this code:
if(musicista != null){
Band band = new Band();
band.setNome(inVO.getNome());
band.setDescrizione(inVO.getDescrizione());
band.setCitta(citta);
BandHasMusicista bandHasMusicista = new BandHasMusicista();
bandHasMusicista.setBand(band);
bandHasMusicista.setMusicista(musicista);
bandHasMusicista.setBandAccept(true);
bandHasMusicista.setMusicistaAccept(true);
band.getBandHasMusicista().add(bandHasMusicista);
em.persist(band);
em.flush();
em.clear();
}
you are creating a new Band and then you are trying to add a Musicista to band. The problem is that at the moment you do em.persist(band) the generated SQL is trying to save the Musicista before saving the Band, therefore BAND_ID which is generated automatically is still null. Save the Band as
if(musicista != null){
Band band = new Band();
band.setNome(inVO.getNome());
band.setDescrizione(inVO.getDescrizione());
band.setCitta(citta);
band = em.persist(band);
BandHasMusicista bandHasMusicista = new BandHasMusicista();
bandHasMusicista.setBand(band);
bandHasMusicista.setMusicista(musicista);
bandHasMusicista.setBandAccept(true);
bandHasMusicista.setMusicistaAccept(true);
band.getBandHasMusicista().add(bandHasMusicista);
em.persist(band);
em.flush();
em.clear();
}
should work (I think you can also do simply em.persist(band); also in the first save, but I am not sure).
Related
So im implmenting an API using springboot, spring-data and Jackson, but im having some troubles when im trying to POST a request to an endpoint who have a Bidirection relationship of #OneToMany.
I dont have so much background so i need really help.
I have two Entities:
Partida
package lucas.duarte.jazz.model.bean;
import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import com.fasterxml.jackson.annotation.JsonProperty;
#Entity
public class Partida implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String timeA;
private String timeB;
private boolean visitante;
#OneToMany(mappedBy = "partida", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<Set> sets;
public List<Set> getSets() {
return sets;
}
public void setSets(List<Set> sets) {
this.sets = sets;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTimeA() {
return timeA;
}
// Mocado o valor pois o Time A sempre e a Sao Judas
public void setTimeA(String timeA) {
this.timeA = timeA;
}
public String getTimeB() {
return timeB;
}
public void setTimeB(String timeB) {
this.timeB = timeB;
}
public boolean isVisitante() {
return visitante;
}
public void setVisitante(boolean visitante) {
this.visitante = visitante;
}
}
and SET
package lucas.duarte.jazz.model.bean;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
#Entity
#Table(name = "meu_set")
public class Set implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "ponto_a")
private long pontoA;
#Column(name = "ponto_b")
private long pontoB;
#Column(name = "set_finalizado")
private boolean setFinalizado;
#ManyToOne
#JoinColumn(name = "partida_id")
private Partida partida;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public long getPontoA() {
return pontoA;
}
public void setPontoA(long pontoA) {
this.pontoA = pontoA;
}
public long getPontoB() {
return pontoB;
}
public void setPontoB(long pontoB) {
this.pontoB = pontoB;
}
public boolean isSetFinalizado() {
return setFinalizado;
}
public void setSetFinalizado(boolean setFinalizado) {
this.setFinalizado = setFinalizado;
}
public Partida getPartida() {
return partida;
}
public void setPartida(Partida partida) {
this.partida = partida;
}
}
This is my SetControler
package lucas.duarte.jazz.controller;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.util.UriComponentsBuilder;
import lucas.duarte.jazz.model.bean.Set;
import lucas.duarte.jazz.model.service.SetService;
#Controller
#RequestMapping("/api")
public class SetController {
private SetService setServ;
#RequestMapping(value = "/set/", method = RequestMethod.POST)
public ResponseEntity<?> salvarSet(#RequestBody Set set, UriComponentsBuilder ucBuilder) {
System.out.println("Vou cadastrar um set vinculado a uma partida");
System.out.println(set.getPartida().getId());
setServ.salvarSet(set);
return new ResponseEntity(HttpStatus.CREATED);
}
}
When i POST to the URL, i get the following return
{
"timestamp": "2019-03-28T04:17:46.857+0000",
"status": 400,
"error": "Bad Request",
"message": "JSON parse error: Cannot construct instance of `lucas.duarte.jazz.model.bean.Partida` (although at least one Creator exists): no int/Int-argument constructor/factory method to deserialize from Number value (1); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `lucas.duarte.jazz.model.bean.Partida` (although at least one Creator exists): no int/Int-argument constructor/factory method to deserialize from Number value (1)\n at [Source: (PushbackInputStream); line: 5, column: 14] (through reference chain: lucas.duarte.jazz.model.bean.Set[\"partida\"])",
"path": "/api/set/"
}
I Already have a Partida inside my database, but i cannot POST to this method, need really help.
This issue has nothing to do with JPA bi-directional mapping. Its raising error at the time of de serializing.
Partida -> should have zero argument constructor
Request payload should have { "partida":{"id":123}} in order to populate partida object property.
for details check this link Jackson library.
#Entity
public class Partida implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String timeA;
private String timeB;
private boolean visitante;
public Partida(){
//Default constructor required here
}
#OneToMany(mappedBy = "partida", fetch = FetchType.LAZY, cascade =
CascadeType.ALL)
private List<Set> sets;
public List<Set> getSets() {
return sets;
}
public void setSets(List<Set> sets) {
this.sets = sets;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTimeA() {
return timeA;
}
// Mocado o valor pois o Time A sempre e a Sao Judas
public void setTimeA(String timeA) {
this.timeA = timeA;
}
public String getTimeB() {
return timeB;
}
public void setTimeB(String timeB) {
this.timeB = timeB;
}
public boolean isVisitante() {
return visitante;
}
public void setVisitante(boolean visitante) {
this.visitante = visitante;
}
}
if issue not not resolved then try JSON creator
#JsonCreator
public Partida(#JsonProperty("id") Long id, #JsonProperty("timeA") String
timeA, #JsonProperty("timeB") String timeB, #JsonProperty("desc") boolean
visitante) {
this.id = id;
this.timeA = timeA;
this.timeB= timeB;
this.visitante= visitante;
}
I'm having problems in mapping foreign keys as the primary key.
My tables are:
client:
PK: id_client
games:
PK: id_game
tickets:
PK: (id_game_fk references game(id_game), id_client_fk references client(id_client))
And here are the classes I have defined as entities:
Client.java:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "client")
public class Client {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id_client")
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
Games.java:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "games")
public class Games {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id_game")
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
Ticket.java:
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import Client;
import Games;
#Entity
#Table(name = "tickets")
public class Ticket implements Serializable {
private static final long serialVersionUID = 3287868602749718327L;
#EmbeddedId
private TicketId ticketId;
#ManyToOne
#JoinColumn(name = "id_game")
private Games games;
#ManyToOne
#JoinColumn(name = "id_client")
private Client client;
public TicketId getId() {
return ticketId;
}
public void setId(TicketId id) {
this.ticketId = id;
}
public Games getGames() {
return games;
}
public void setGames(Games games) {
this.games = games;
}
public Client getClient() {
return client;
}
public void setClient(Client client) {
this.client = client;
}
}
TicketId.java:
import java.io.Serializable;
import javax.persistence.Embeddable;
#Embeddable
public class TicketId implements Serializable {
private static final long serialVersionUID = 6220676431741410239L;
private int idGameFk;
private int idClientFk;
public TicketId(int idGameFk, int idClientFk) {
this.idGameFk = idGameFk;
this.idClientFk = idClientFk;
}
public int getIdGameFk() {
return idGameFk;
}
public void setIdGameFk(int idGameFk) {
this.idGameFk = idGameFk;
}
public int getIdClientFk() {
return idClientFk;
}
public void setIdClientFk(int idClientFk) {
this.idClientFk = idClientFk;
}
}
I have tried all the advices I have found so far, but none of them helped. Also, I need this PK to be composed by foreign keys, so I really need help to solve out, how should I map it correctly.
You can use #MapsId :
#Entity
#Table(name = "tickets")
public class Ticket implements Serializable {
private static final long serialVersionUID = 3287868602749718327L;
#EmbeddedId
private TicketId ticketId;
#ManyToOne
#MapsId("idGameFk")
#JoinColumn(name = "id_game_fk")
private Games games;
#ManyToOne
#MapsId("idClientFk")
#JoinColumn(name = "id_client_fk")
private Client client;
....
}
More info here : http://docs.oracle.com/javaee/6/api/javax/persistence/MapsId.html
These are my pojo class
Orderdetail.java
package online.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name = "orderdetail")
public class OrderDetail {
#Id
#Column(name="order_detail_id")
private int order_detail_id;
#Column(name="bill")
private float bill;
#ManyToOne
#JoinColumn(name = "p_id" )
private Product p_id;
#ManyToOne
#JoinColumn(name = "o_id" )
private Order o_id;
public int getOrder_detail_id() {
return order_detail_id;
}
public void setOrder_detail_id(int order_detail_id) {
this.order_detail_id = order_detail_id;
}
public float getBill() {
return bill;
}
public void setBill(float bill) {
this.bill = bill;
}
public Product getP_id() {
return p_id;
}
public void setP_id(Product p_id) {
this.p_id = p_id;
}
public Order getO_id() {
return o_id;
}
public void setO_id(Order o_id) {
this.o_id = o_id;
}
}
My Order.java
package online.model;
import java.util.Date;
import java.util.List;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
#Entity
#Table(name = "ordertable")
public class Order {
#Id
#Column(name = "order_id")
private int order_id;
#OneToMany(mappedBy = "o_id",cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<OrderDetail> orderdetail;
#ManyToOne
#JoinColumn(name = "u_id")
private UserDetail u_id;
public UserDetail getU_id() {
return u_id;
}
public void setU_id(UserDetail u_id) {
this.u_id = u_id;
}
#Column(name = "date")
#Temporal(TemporalType.TIMESTAMP)
private Date date;
#Column(name = "totalbill")
private Float totalbill;
public Float getTotalbill() {
return totalbill;
}
public void setTotalbill(Float totalbill) {
this.totalbill = totalbill;
}
public List<OrderDetail> getOrderdetail() {
return orderdetail;
}
public void setOrderdetail(List<OrderDetail> orderdetail) {
this.orderdetail = orderdetail;
}
public int getOrder_id() {
return order_id;
}
public void setOrder_id(int order_id) {
this.order_id = order_id;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
When ever I am trying to save order class I want my orderdetail class also get saved but when I am trying to save the List in order,Is is not getting saved and there is not error provided by hibernate that can help...
Thanks for the help
when i am trying to to persist the order class
Hibernate: select orderdetai_.order_detail_id, orderdetai_.bill as bill7_, orderdetai_.o_id as o3_7_, orderdetai_.p_id as p4_7_ from orderdetail orderdetai_ where orderdetai_.order_detail_id=?
This what I am getting output.
This is my code which save the class
#Override
public boolean payment(String username, Integer ordernumber, Date date,
Float totalbill, List<Integer> list) {
Session session = sessionFactory.openSession();
Transaction tranction = session.beginTransaction();
try {
Query query = session
.createQuery("from UserDetail where user_username = :username");
query.setParameter("username", username);
List<UserDetail> userdetaillist = query.list();
UserDetail userdetail = userdetaillist.get(0);
query = session
.createQuery("from ProductDetail where product_detail_id in(:list)");
query.setParameterList("list", list);
List<ProductDetail> productdetail = query.list();
Order order = new Order();
order.setOrder_id(ordernumber);
order.setDate(date);
order.setU_id(userdetail);
order.setTotalbill(totalbill);
List<OrderDetail> orderdetail = new ArrayList<OrderDetail>();
OrderDetail ordetail = new OrderDetail();
for (ProductDetail pro : productdetail) {
ordetail.setO_id(order);
ordetail.setP_id(pro.getProduct_id());
ordetail.setBill(pro.getProduct_id().getProduct_sell_price());
orderdetail.add(ordetail);
}
System.out.print("totalbill" + totalbill);
System.out.println(orderdetail);
order.setOrderdetail(orderdetail);
session.save(order);
tranction.commit();
return true;
} catch (Exception e) {
tranction.rollback();
e.getStackTrace();
}
return false;
}
I think ordetail has to be created inside the for.. You are modifying the same object for each productdetail. Should be like this:
List<OrderDetail> orderdetail = new ArrayList<OrderDetail>();
OrderDetail ordetail = null;
for (ProductDetail pro : productdetail) {
ordetail = new OrderDetail();
ordetail.setO_id(order);
ordetail.setP_id(pro.getProduct_id());
ordetail.setBill(pro.getProduct_id().getProduct_sell_price());
orderdetail.add(ordetail);
}
Hey I have recheck my pojo class and I found out the mistake I have done. I have made change and it work properly now.
I was not setting the the id for Orderdetail table. It was auto increment in database.
So it was giving me error ""
So I have made change in orderdetail iD
"#GeneratedValue(strategy=GenerationType.AUTO)" So now It is working fine cause now hibernate know that the id will get value from database.
Thanks for the help and for your time
My database has two table. One of University, another is Faculty. They are one to many relationship
package server.hibernate.domain;
import static javax.persistence.GenerationType.IDENTITY;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Version;
#Entity
#Table(name = "UNIVERSITY")
public class University implements Serializable{
private Long _id;
private int _version;
private String _universityName;
private String _countryLocated;
private Set<Faculty> _faculties = new HashSet<Faculty>();
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "ID")
public Long getId() {
return _id;
}
public void setId(Long _id) {
this._id = _id;
}
#Version
#Column(name = "VERSION")
public int getVersion() {
return _version;
}
public void setVersion(int _version) {
this._version = _version;
}
#Column(name = "UNIVERSITY_NAME", nullable=false)
public String getUniversityName() {
return _universityName;
}
public void setUniversityName(String _universityName) {
this._universityName = _universityName;
}
#Column(name = "COUNTRY_LOCATED")
public String getCountryLocated() {
return _countryLocated;
}
public void setCountryLocated(String _countryLocated) {
this._countryLocated = _countryLocated;
}
#OneToMany(mappedBy="university", targetEntity=Faculty.class, orphanRemoval=true, fetch=FetchType.EAGER, cascade=CascadeType.ALL)
public Set<Faculty> getFaculties() {
return _faculties;
}
public void setFaculties(Set<Faculty> faculties) {
this._faculties = faculties;
}
public String toString(){
return new String("UniversityID:"+_id
+ " UniversityName:"+_universityName
+" CountryLocated:"+_countryLocated);
}
}
This is what I have set in University class.
package server.hibernate.domain;
import static javax.persistence.GenerationType.IDENTITY;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Version;
#Entity
#Table(name="FACULTY")
public class Faculty implements Serializable{
private Long _id;
private int _version;
private String _facultyName;
private String _deanName;
private University _university;
private Set<Student> _students = new HashSet<Student>();
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "ID")
public Long getId() {
return _id;
}
public void setId(Long id) {
this._id = id;
}
#Version
#Column(name = "VERSION")
public int getVersion() {
return _version;
}
public void setVersion(int version) {
this._version = version;
}
#Column(name="FACULTY_NAME", nullable=false)
public String getFacultyName() {
return _facultyName;
}
public void setFacultyName(String facultyName) {
this._facultyName = facultyName;
}
#Column(name="DEAN_NAME")
public String getDeanName() {
return _deanName;
}
public void setDeanName(String dean_name) {
this._deanName = dean_name;
}
#ManyToOne
#JoinColumn(name = "UNIVERSITY_ID", nullable=false)
public University getUniversity() {
return _university;
}
public void setUniversity(University university) {
this._university = university;
}
#OneToMany(mappedBy="faculty", targetEntity=Student.class, orphanRemoval=true, cascade=CascadeType.ALL, fetch=FetchType.EAGER)
public Set<Student> getStudents() {
return _students;
}
public void setStudents(Set<Student> students) {
this._students = students;
}
public String toString(){
return new String("FacultyID:"+_id
+" FacultyName:"+_facultyName
+" DeanName:"+_deanName);
}
}
This is my faculty class
But when I use sessionFactory.delete(university). I still have this exception
Exception in thread "main" org.springframework.dao.DataIntegrityViolationException: could not delete: [server.hibernate.domain.University#1]; SQL [delete from UNIVERSITY where ID=? and VERSION=?]; constraint ["FKE9B72644368E5BBD: PUBLIC.FACULTY FOREIGN KEY(UNIVERSITY_ID) REFERENCES PUBLIC.UNIVERSITY(ID)"; SQL statement:
delete from UNIVERSITY where ID=? and VERSION=? [23503-160]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not delete: [server.hibernate.domain.University#1]
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:643)
at org.springframework.orm.hibernate3.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:793)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:664)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy19.removeUniversity(Unknown Source)
at main.TestHibernateMain.test(TestHibernateMain.java:73)
at main.TestHibernateMain.main(TestHibernateMain.java:22)
Caused by: org.hibernate.exception.ConstraintViolationException: could not delete: [server.hibernate.domain.University#1]
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2710)
at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2893)
at org.hibernate.action.EntityDeleteAction.execute(EntityDeleteAction.java:97)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:189)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656)
... 9 more
Caused by: org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "FKE9B72644368E5BBD: PUBLIC.FACULTY FOREIGN KEY(UNIVERSITY_ID) REFERENCES PUBLIC.UNIVERSITY(ID)"; SQL statement:
delete from UNIVERSITY where ID=? and VERSION=? [23503-160]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:329)
at org.h2.message.DbException.get(DbException.java:169)
at org.h2.message.DbException.get(DbException.java:146)
at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:398)
at org.h2.constraint.ConstraintReferential.checkRowRefTable(ConstraintReferential.java:415)
at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:291)
at org.h2.table.Table.fireConstraints(Table.java:861)
at org.h2.table.Table.fireAfterRow(Table.java:878)
at org.h2.command.dml.Delete.update(Delete.java:98)
at org.h2.command.CommandContainer.update(CommandContainer.java:73)
at org.h2.command.Command.executeUpdate(Command.java:219)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:143)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:129)
at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2692)
... 20 more
Can anyone suggest a solution?
Thanks!
I solved my problem by myself.
It is a fetch problem.
When I try remove University by using sessionFactory.delete(university), this university does not fetch any faculties. So the removal will not be cascade enabled.
This because you are trying to delete the UNIVERSITY which is associated with other faculties
thus you have to first delete associated faculties before deleting the university.
I have the following problem.
Here are my entities.
TestTeam.java
package utils;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name = "TEST_TEAM")
public final class TestTeam implements Serializable {
/**
*
*/
private static final long serialVersionUID = -7275223441128447981L;
#Id
#Column(name = "NAME")
private String name;
#OneToMany(mappedBy = "playerId", cascade = CascadeType.ALL)
private List<TestPlayer> test1List;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<TestPlayer> getTest1List() {
return test1List;
}
public void setTest1List(List<TestPlayer> test1List) {
this.test1List = test1List;
}
public TestTeam() {
}
public TestTeam(final String name, final List<TestPlayer> test1List) {
this.name = name;
this.test1List = new ArrayList<>(test1List);
}
}
TestPlayer.java
package utils;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name = "TEST_PLAYER")
public class TestPlayer implements Serializable {
/**
*
*/
private static final long serialVersionUID = -2792602076488917813L;
#Id
private long playerId;
#Column(name = "NAME", nullable = false)
private String playerName;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "TEAM_NAME")
private TestTeam team;
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "PREVIOUS_TEST_TEAM")
private Map<Integer, TestTeam> previousTests = Collections.emptyMap();
public TestPlayer() {
// TODO Auto-generated constructor stub
}
public TestPlayer(final long playerId) {
this.playerId = playerId;
}
public String getName() {
return playerName;
}
public void setName(String name) {
this.playerName = name;
}
/**
* #return the team
*/
public TestTeam getTeam() {
return team;
}
/**
* #param team the team to set
*/
public void setTeam(TestTeam team) {
this.team = team;
}
public Map<Integer, TestTeam> getPreviousTests() {
return previousTests;
}
public void setPreviousTests(Map<Integer, TestTeam> previousTests) {
this.previousTests = previousTests;
}
public TestPlayer(final String name,
final Map<Integer, TestTeam> previousTests) {
this.playerName = name;
this.previousTests = new HashMap<>(previousTests);
}
}
The following annotated collection.
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "PREVIOUS_TEST_TEAM")
private Map<Integer, TestTeam> previousTests = Collections.emptyMap();
produces by default a unique constraint for the foreign key from TestTeam entity.
create table PLAYERS_PREVIOUS_TEAMS (
Player_ID bigint not null,
previousTeamMap_NAME varchar(255) not null,
previousTeamMap_KEY integer,
primary key (Player_ID, previousTeamMap_KEY)
)
alter table PLAYERS_PREVIOUS_TEAMS
add constraint UK_f7nfahws0ttuhe5p7lpxt3vfv unique (previousTeamMap_NAME)
I do not need this constraint and I would like to switch off this behaviour so that Hibernate does not generate it. I have spent some time looking on the internet but I did not find anything. I do not want to introduce #OneToMany and many #ManyToOne by introducing another entity. Did anyone face a similar problem in the past?
I worked around my issue by changing #ElementCollection to #ManyToMany annotation.
#ManyToMany(fetch = FetchType.EAGER)
#CollectionTable(name = "PREVIOUS_TEST_TEAM")
private Map<Integer, TestTeam> previousTests = Collections.emptyMap();