I have this model with 2 tables, "Cuenta" and "Movimien". When the merge () method of the Movimien table is called, it also attempts to insert into the Cuenta table. I am not sure if relationships are right. Could someone give me a hand with this?
Below, the model of the Movimien table, which when doing the update triggers the insert in the Cuenta table:
#Entity
#Table(name = "movimien")
public class Movimien implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private Date fecha;
private short cuentaid;
private float importe;
private String concepto;
#JoinColumn(name = "cuentaid", insertable = false, updatable = false)
#ManyToOne
private Cuenta cuenta;
public Movimien() {
this.cuenta = new Cuenta();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Date getFecha() {
return fecha;
}
public void setFecha(Date fecha) {
this.fecha = fecha;
}
public short getCuentaid() {
return cuentaid;
}
public void setCuentaid(short cuentaid) {
this.cuentaid = cuentaid;
}
public float getImporte() {
return importe;
}
public void setImporte(float importe) {
this.importe = importe;
}
public String getConcepto() {
return concepto;
}
public void setConcepto(String concepto) {
this.concepto = concepto;
}
public Cuenta getCuenta() {
return cuenta;
}
public void setCuenta(Cuenta cuenta) {
this.cuenta = cuenta;
}
#Override
public int hashCode() {
int hash = 7;
hash = 53 * hash + this.id;
return hash;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Movimien other = (Movimien) obj;
if (this.id != other.id) {
return false;
}
return true;
}}
And the model of the Cuenta table, to which the insert is triggered when an update is made in the Movimien table:
#Entity
#Table(name = "cuentas")
public class Cuenta implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String nombre;
private short tipo;
#OneToMany(mappedBy="cuenta")
private List<Movimien> movimien;
public Cuenta() {
this.nombre="";
this.tipo = 0;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public short getTipo() {
return tipo;
}
public void setTipo(short tipo) {
this.tipo = tipo;
}
#Override
public int hashCode() {
int hash = 7;
hash = 97 * hash + this.id;
return hash;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Cuenta other = (Cuenta) obj;
if (this.id != other.id) {
return false;
}
return true;
}}
Any idea what may be the reason for this behavior?,
thanks in advance!
Fernando
Persitence.xml
Database
Log of update and insert
Related
I am beginner using java and spring jpa (expecially Jhipster). I want to create object in object like this :
But I always get like this :
property buildingsDTO always empty, this is my code, please correct my code in order I get like first picture.
location.java (Domain)
public class Location implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
#Column(name = "content_location", nullable = false)
private String content_location;
#OneToMany(mappedBy = "location")
#JsonIgnore
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Building> buildings = new HashSet<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getContent_location() {
return content_location;
}
public Location content_location(String content_location) {
this.content_location = content_location;
return this;
}
public void setContent_location(String content_location) {
this.content_location = content_location;
}
public Set<Building> getBuildings() {
return buildings;
}
public Location buildings(Set<Building> buildings) {
this.buildings = buildings;
return this;
}
public Location addBuilding(Building building) {
this.buildings.add(building);
building.setLocation(this);
return this;
}
public Location removeBuilding(Building building) {
this.buildings.remove(building);
building.setLocation(null);
return this;
}
public void setBuildings(Set<Building> buildings) {
this.buildings = buildings;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Location location = (Location) o;
if (location.getId() == null || getId() == null) {
return false;
}
return Objects.equals(getId(), location.getId());
}
#Override
public int hashCode() {
return Objects.hashCode(getId());
}
#Override
public String toString() {
return "Location{" +
"id=" + getId() +
", content_location='" + getContent_location() + "'" +
"}";
}}
locationDTO.java
public class LocationDTO implements Serializable {
private Long id;
#NotNull
private String content_location;
private Set<BuildingDTO> buildings = new HashSet<>();
public Set<BuildingDTO> getBuildingsDTO() {
return buildings;
}
public void setBuildingsDTO(Set<BuildingDTO> buildings) {
this.buildings = buildings;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getContent_location() {
return content_location;
}
public void setContent_location(String content_location) {
this.content_location = content_location;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
LocationDTO locationDTO = (LocationDTO) o;
if(locationDTO.getId() == null || getId() == null) {
return false;
}
return Objects.equals(getId(), locationDTO.getId());
}
#Override
public int hashCode() {
return Objects.hashCode(getId());
}
#Override
public String toString() {
return "LocationDTO{" +
"id=" + getId() +
", content_location='" + getContent_location() + "'" +
"}";
}}
locationMapper.java
public interface LocationMapper extends EntityMapper <LocationDTO, Location> {
#Mapping(target = "buildings", ignore = true)
Location toEntity(LocationDTO locationDTO);
default Location fromId(Long id) {
if (id == null) {
return null;
}
Location location = new Location();
location.setId(id);
return location;
}}
buildingDTO.java
public class BuildingDTO implements Serializable {
private Long id;
#NotNull
private String content_building;
private Long locationId;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getContent_building() {
return content_building;
}
public void setContent_building(String content_building) {
this.content_building = content_building;
}
public Long getLocationId() {
return locationId;
}
public void setLocationId(Long locationId) {
this.locationId = locationId;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
BuildingDTO buildingDTO = (BuildingDTO) o;
if(buildingDTO.getId() == null || getId() == null) {
return false;
}
return Objects.equals(getId(), buildingDTO.getId());
}
#Override
public int hashCode() {
return Objects.hashCode(getId());
}
#Override
public String toString() {
return "BuildingDTO{" +
"id=" + getId() +
", content_building='" + getContent_building() + "'" +
"}";
}}
please anyone help me.
thanks.
By default jHipster will mark any OneToMany entity relationships as #JsonIgnore so that the Set of buildings is not returned in the JSON:
#OneToMany(mappedBy = "location")
#JsonIgnore
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Building> buildings = new HashSet<>();
If you want this to show up in the JSON then you should remove that annotation and also mark it with an eager loading strategy so that the set of buildings are loaded as you expect:
#OneToMany(mappedBy = "location", fetch = FetchType.EAGER)
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Building> buildings = new HashSet<>();
I have an entity question and an entity test with ManyToMany relationship between the two entitie.
when I want to view the questions of a test this error is occurred.
failed to lazily initialize a collection of role:
tn.esen.entities.Test.questions, could not initialize proxy - no Session
this is the JPA implementation of the two entities.
Question:
package tn.esen.entities;
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.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
#Entity
public class Question implements Serializable {
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((contenu == null) ? 0 :
contenu.hashCode());
result = prime * result + ((dateCreation == null) ? 0 :
dateCreation.hashCode());
result = prime * result + ((niveauDeDifficulte == null) ? 0 :
niveauDeDifficulte.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Question other = (Question) obj;
if (contenu == null) {
if (other.contenu != null)
return false;
} else if (!contenu.equals(other.contenu))
return false;
if (dateCreation == null) {
if (other.dateCreation != null)
return false;
} else if (!dateCreation.equals(other.dateCreation))
return false;
if (niveauDeDifficulte == null) {
if (other.niveauDeDifficulte != null)
return false;
} else if (!niveauDeDifficulte.equals(other.niveauDeDifficulte))
return false;
return true;
}
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id_question")
private int id;
private String contenu;
private String niveauDeDifficulte;
private Date dateCreation;
#OneToMany(mappedBy="question",fetch = FetchType.EAGER)
private Collection <Reponse> reponses;
#ManyToOne
private Categorie categorie;
#ManyToOne
private Administrateur administrateur;
#ManyToMany(mappedBy = "questions",fetch = FetchType.EAGER)
private Collection<Test> tests;
public Question(){
super();
}
#Override
public String toString() {
return "Question [id=" + id + ", contenu=" + contenu + ",
niveauDeDifficulte=" + niveauDeDifficulte + "]";
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getContenu() {
return contenu;
}
public void setContenu(String contenu) {
this.contenu = contenu;
}
public String getNiveauDeDifficulte() {
return niveauDeDifficulte;
}
public void setNiveauDeDifficulte(String niveauDeDifficulte) {
this.niveauDeDifficulte = niveauDeDifficulte;
}
public Date getDateCreation() {
return dateCreation;
}
public void setDateCreation(Date dateCreation) {
this.dateCreation = dateCreation;
}
public Collection<Reponse> getReponses() {
return reponses;
}
public void setReponses(Collection<Reponse> reponses) {
this.reponses = reponses;
}
public Categorie getCategorie() {
return categorie;
}
public void setCategorie(Categorie categorie) {
this.categorie = categorie;
}
public Administrateur getAdministrateur() {
return administrateur;
}
public void setAdministrateur(Administrateur administrateur) {
this.administrateur = administrateur;
}
public Collection<Test> getTest() {
return tests;
}
public void setTest(Collection<Test> tests) {
this.tests = tests;
}
public Question(String contenu, String niveauDeDifficulte, Date
dateCreation) {
super();
this.contenu = contenu;
this.niveauDeDifficulte = niveauDeDifficulte;
this.dateCreation = dateCreation;
}
Test:
package tn.esen.entities;
#Entity
public class Test implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String duree;
private String typeDePreparation;
private String lieu;
private int nbrQuestionFacile;
private int nbrQuestionMoyen;
private int nbrQuestionDifficle;
#OneToMany(mappedBy = "test")
private Collection<Resultat> resultats;
#ManyToMany
private Collection<Question> questions;
#ManyToOne
private ResponsableTechnique responsableTechnique;
public Test() {
super();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDuree() {
return duree;
}
public void setDuree(String duree) {
this.duree = duree;
}
public Collection<Question> getQuestions() {
return questions;
}
public void setQuestions(Collection<Question> questions) {
this.questions = questions;
}
public Test(String duree, String typeDePreparation, String lieu, int
nbrQuestionFacile, int nbrQuestionMoyen,
int nbrQuestionDifficle) {
super();
this.duree = duree;
this.typeDePreparation = typeDePreparation;
this.lieu = lieu;
this.nbrQuestionFacile = nbrQuestionFacile;
this.nbrQuestionMoyen = nbrQuestionMoyen;
this.nbrQuestionDifficle = nbrQuestionDifficle;
}
public ResponsableTechnique getRésponsableTechnique() {
return responsableTechnique;
}
public void setRésponsableTechnique(ResponsableTechnique
résponsableTechnique) {
this.responsableTechnique = résponsableTechnique;
}
public String getTypeDePreparation() {
return typeDePreparation;
}
public void setTypeDePreparation(String typeDePreparation) {
this.typeDePreparation = typeDePreparation;
}
public String getLieu() {
return lieu;
}
public void setLieu(String lieu) {
this.lieu = lieu;
}
public int getNbrQuestionFacile() {
return nbrQuestionFacile;
}
public void setNbrQuestionFacile(int nbrQuestionFacile) {
this.nbrQuestionFacile = nbrQuestionFacile;
}
public int getNbrQuestionMoyen() {
return nbrQuestionMoyen;
}
public void setNbrQuestionMoyen(int nbrQuestionMoyen) {
this.nbrQuestionMoyen = nbrQuestionMoyen;
}
public int getNbrQuestionDifficle() {
return nbrQuestionDifficle;
}
public void setNbrQuestionDifficle(int nbrQuestionDifficle) {
this.nbrQuestionDifficle = nbrQuestionDifficle;
}
public Collection<Resultat> getResultats() {
return resultats;
}
public void setRésultats(Collection<Resultat> resultats) {
this.resultats = resultats;
}
}
}
When you get Test and access Test.questions later, after leaving the transaction, you will get a lazy initialization exception when the Test entity is detached and questions has not been initialized/fetched yet. You can either do a specific fetch, or depending on your configuration, you can call Test.getQuestions().size() before you exit the transaction.
References: How to solve lazy initialization exception using JPA and Hibernate as provider
LazyInitializationException in JPA and Hibernate
Hibernate LazyInitializationException using Spring CrudRepository
I developed an application using Java Spring (backend api), mysql (DB) and Anguljar JS (frontend) that is designed to let users schedule an appointment. The endtime of each appointment is five minutes after its starttime, between 8 o’clock and 2 p.m.
In my data base I have the following information:
• A table named “turno” which contains the parameters time and date of the appointments given.
• Another table contains all the available appointments.
I want to substract both arrays so as to see which appointments have not been given yet. The objective is not to allow users to fix an appointment that has already been made by someone else.
Does anyone have any idea how to do this?
Data examples:
Java Example:
#Entity
#Table(name = "turno")
public class Turno implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String solicitante;
private String telefono;
private TipoDocumento tipoDocumento;
private String numeroDocumento;
private String email;
private Horario horario;
private String numeroTurno;
private String fecha;
private Date formatfecha;
private Date controlFecha;
#Id
#GeneratedValue
#Column(name = "id")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "solicitante")
public String getSolicitante() {
return solicitante;
}
public void setSolicitante(String solicitante) {
this.solicitante = solicitante;
}
#Column(name = "telefono")
public String getTelefono() {
return telefono;
}
public void setTelefono(String telefono) {
this.telefono = telefono;
}
#Column(name = "numero_documento")
public String getNumeroDocumento() {
return numeroDocumento;
}
public void setNumeroDocumento(String numeroDocumento) {
this.numeroDocumento = numeroDocumento;
}
#Column(name = "email")
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#ManyToOne(cascade = CascadeType.MERGE)
#JoinColumn(name = "horario", referencedColumnName = "id")
public Horario getHorario() {
return horario;
}
public void setHorario(Horario horario) {
this.horario = horario;
}
#Column(name = "numero_turno")
public String getNumeroTurno() {
return numeroTurno;
}
public void setNumeroTurno(String numeroTurno) {
this.numeroTurno = numeroTurno;
}
#Column(name = "fecha")
public String getFecha() {
return fecha;
}
public void setFecha(String fecha) {
this.fecha = fecha;
}
#Column(insertable = false, updatable = false, name = "fecha")
public Date getFormatFecha() {
return formatfecha;
}
public void setFormatFecha(Date formatfecha) {
this.formatfecha = formatfecha;
}
#ManyToOne(cascade = CascadeType.MERGE)
#JoinColumn(name = "tipoDocumento", referencedColumnName = "id")
public TipoDocumento getTipoDocumento() {
return tipoDocumento;
}
public void setTipoDocumento(TipoDocumento tipoDocumento) {
this.tipoDocumento = tipoDocumento;
}
#Column(name = "fecha_control")
public Date getControlFecha() {
return controlFecha;
}
public void setControlFecha(Date controlFecha) {
this.controlFecha = controlFecha;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((numeroTurno == null) ? 0 : numeroTurno.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Turno other = (Turno) obj;
if (numeroTurno == null) {
if (other.numeroTurno != null)
return false;
} else if (!numeroTurno.equals(other.numeroTurno))
return false;
return true;
}
}
Updated
Heres how I fixed it in case anyone is interested:
Method in the controller:
#RequestMapping(value = "/horario/{fecha}", method = RequestMethod.GET)
#ResponseBody
public Object queryHorariosLibres(#PathVariable("fecha") Date fecha) {
List<Long> horariosLibres = null;
List<Long> turnosTomados = turnoService.getTurnosTomados(fecha);
Calendar dia = new GregorianCalendar();
dia.setTime(fecha);
Horario horario = horarioRepository.findByDia(dia.get(Calendar.DAY_OF_WEEK));
horariosLibres = horario.getHorariosLibres(turnosTomados);
if (horariosLibres == null) {
return "hola";
}
else
return horariosLibres;
}
Local methods:
#Transient
public List<Long> getHorarios(){
List<Long> horarios = new ArrayList<Long>();
for(Long i = horarioInicio; i <= horarioFin; i+=300){
horarios.add(i);
}
return horarios;
}
#Transient
public List<Long> getHorariosLibres(List<Long> horariosTomados){
List<Long> horariosLibres = getHorarios();
horariosLibres.removeAll(horariosTomados);
return horariosLibres;
}
I have a Canteen class and a Course class (and a BaseEntity). The Canteen class has a set of courses. A course is unique if the composition of name, dateOfServing and the canteen id is unique. I tried to write a test case which should throw an exception if a non-unique course is added to a canteen. But the test doesn't throw any exception at all. Which leads me to believe that I'm doing me Canteen and Course class wrong. The test in question is addDuplicatedCourseToCanteenTest. Anyone got a clue about what I'm doing wrong?
I'm new to TDD as well so any critique in that area is very welcome as well.
BaseEntity.java
#MappedSuperclass
public class BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
long id;
private Date createdAt;
private Date updatedAt;
// TODO: http://stackoverflow.com/a/11174297/672009
// Using the above we wouldn't have to created a CommentRepository
// Is that a good idea?
/**
* http://www.devsniper.com/base-entity-class-in-jpa/
*/
/**
* Sets createdAt before insert
*/
#PrePersist
public void setCreationDate() {
this.setCreatedAt(new Date());
}
/**
* Sets updatedAt before update
*/
#PreUpdate
public void setChangeDate() {
this.setUpdatedAt(new Date());
}
public Date getCreatedAt() {
return createdAt;
}
protected void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getUpdatedAt() {
return updatedAt;
}
protected void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (id ^ (id >>> 32));
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BaseEntity other = (BaseEntity) obj;
if (id != other.id)
return false;
return true;
}
}
Canteen.java
#Entity
public class Canteen extends BaseEntity {
private String name;
// TODO: https://schuchert.wikispaces.com/JPA+Tutorial+1+-+Embedded+Entity
// http://docs.oracle.com/javaee/6/api/javax/xml/registry/infomodel/PostalAddress.html
//private Address address;
//private PostalAddress postalAddress;
/**
* In honor of KISS I simply use a simple string address as a holder for the restaurants address.
* The idea is that the string will contain an address which will be valid according to google maps.
* Same goes for openingHours, phoneNumber and homepage... KISS wise.
*/
private String address;
private String openingHours; // A string which will be presented within a pre tag
// Eg. <pre>Mandag - Torsdag 10-22
// Fredag - Lørdag 10-24
// Søndag 11-20</pre>
private String contact;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<Course> courses = new HashSet<>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getOpeningHours() {
return openingHours;
}
public void setOpeningHours(String openingHours) {
this.openingHours = openingHours;
}
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
public Set<Course> getCourses() {
return courses;
}
public void setCourses(Set<Course> courses) {
this.courses = courses;
}
public boolean addCourse(Course course)
{
return getCourses().add(course);
}
#Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((address == null) ? 0 : address.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
Canteen other = (Canteen) obj;
if (address == null) {
if (other.address != null)
return false;
} else if (!address.equals(other.address))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
Course.java
#Entity
public class Course extends BaseEntity {
private String name;
private Date dateOfServing;
#ManyToOne
private Canteen canteen;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDateOfServing() {
return dateOfServing;
}
public void setDateOfServing(Date dateOfServing) {
this.dateOfServing = dateOfServing;
}
public Canteen getCanteen() {
return canteen;
}
public void setCanteen(Canteen canteen) {
this.canteen = canteen;
}
#Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((canteen == null) ? 0 : canteen.hashCode());
result = prime * result
+ ((dateOfServing == null) ? 0 : dateOfServing.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
Course other = (Course) obj;
if (canteen == null) {
if (other.canteen != null)
return false;
} else if (!canteen.equals(other.canteen))
return false;
if (dateOfServing == null) {
if (other.dateOfServing != null)
return false;
} else if (!dateOfServing.equals(other.dateOfServing))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
CanteenHasCoursesTest.java
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = PersistenceConfig.class)
public class CanteenHasCoursesTest {
#Autowired
private CanteenRepository canteenRepository;
private String canteenName;
private String courseName;
private Canteen canteen;
private Course course;
#Before
public void setUp() {
// Generate unique random name
canteenName = UUID.randomUUID().toString();
// Generate unique random name
courseName = UUID.randomUUID().toString();
// Create new canteen
canteen = new Canteen();
canteen.setName(canteenName);
// Create new course
course = new Course();
course.setName(courseName);
}
#Test
public void addCourseToCanteenTest() {
// Add course
canteen.addCourse(course);
// Save canteen
canteenRepository.save(canteen);
// Find it again
Canteen c = canteenRepository.findOne(canteen.getId());
// Confirm attributes are as expected
assertNotNull(c);
Set<Course> courses = c.getCourses();
Iterator<Course> it = courses.iterator();
assertTrue(it.hasNext());
Course course = it.next();
assertEquals(courseName, course.getName());
}
// TODO: expect some data violation exception
// #Test(expected = IndexOutOfBoundsException.class)
#Test
public void addDuplicatedCourseToCanteenTest() {
// Add course
canteen.addCourse(course);
// Add it again
canteen.addCourse(course);
// Save canteen
canteenRepository.save(canteen);
}
#After
public void tearDown() {
canteenRepository = null;
canteenName = null;
courseName = null;
canteen = null;
course = null;
}
}
I'm trying persist a relationship #ManyToMany. I created an association class using #IdClass for association, but doesn't work using persist, works only using merge. I need add others registers but using merge doesn't work because the register is always updated.
I want my table in the database looks like this
id_aluno | id_graduacao | grau | date
1 1 FIRST 2014-08-02
1 1 SECOND 2014-08-02
1 1 THIRD 2014-08-02
Entities
#Entity
#Table(name="aluno")
public class Aluno implements Serializable{
private static final long serialVersionUID = 1L;
#Id #GeneratedValue
private Integer id;
//informacoes gerais
#NotNull
private String nome;
//historico de graduacao
#OneToMany(mappedBy = "aluno")
private List<HistoricoDeGraduacao> listaHistoricoGraduacao;
public Aluno(){}
/** adiciona lista de HistoricoDeGraduacao para aluno */
public void addListaHistoricoGraduacao(HistoricoDeGraduacao hdg){
if(listaHistoricoGraduacao == null){
listaHistoricoGraduacao = new ArrayList<HistoricoDeGraduacao>();
}
listaHistoricoGraduacao.add(hdg);
}
public List<HistoricoDeGraduacao> getListaHistoricoGraduacao() {
return listaHistoricoGraduacao;
}
///gets e sets
#Entity
#Table(name="graduacao")
public class Graduacao implements Serializable{
private static final long serialVersionUID = 1L;
#Id #GeneratedValue
private Integer id;
#NotNull #Column(unique = true)
private String graduacao;
#ElementCollection
#CollectionTable(name="graus_graduacao", joinColumns=#JoinColumn(name="id_graduacao"))
#Column(name="graus")
private List<String> graus;
#OneToMany(mappedBy = "graduacao")
private List<HistoricoDeGraduacao> listaHistoricoGraduacao;
public Graduacao() {
}
/** adiciona historicodegraduacao a graduacao */
public void addHistoricoDeGraduacao(HistoricoDeGraduacao hdg){
if(listaHistoricoGraduacao == null){
listaHistoricoGraduacao = new ArrayList<HistoricoDeGraduacao>();
}
listaHistoricoGraduacao.add(hdg);
}
public List<HistoricoDeGraduacao> getListaHistoricoGraduacao() {
return listaHistoricoGraduacao;
}
//gets e sets
public class HistoricoDeGraduacaoId implements Serializable {
private static final long serialVersionUID = 1L;
private Aluno aluno;
private Graduacao graduacao;
public Aluno getAluno() {
return aluno;
}
public void setAluno(Aluno aluno) {
this.aluno = aluno;
}
public Graduacao getGraduacao() {
return graduacao;
}
public void setGraduacao(Graduacao graduacao) {
this.graduacao = graduacao;
}
#Entity
#IdClass(HistoricoDeGraduacaoId.class)
public class HistoricoDeGraduacao implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#ManyToOne
#JoinColumn(name = "id_aluno")
private Aluno aluno;
#Id
#ManyToOne
#JoinColumn(name="id_graduacao")
private Graduacao graduacao;
private String grau;
#Temporal(TemporalType.DATE)
private Date dataGraduou;
public HistoricoDeGraduacao() {
}
//gets e sets
//persisting
public void insert(){
//doesn't work using persist, works only with merge but record is always updated and not added
em.getTransaction().begin();
Aluno a = new Aluno();
a.setId(1); //aluno have Id
Graduacao g = new Graduacao();
g.setId(1); //graduacao have Id
HistoricoDeGraduacao hdg1 = new HistoricoDeGraduacao();
hdg1.setAluno(a);
hdg1.setGraduacao(g);
hdg1.setDataGraduou(new Date());
hdg1.setGrau("FIRST");
a.addHistoricoDeGraduacao(hdg1);
g.addHistoricoDeGraduacao(hdg1);
em.persist(hdg1);
em.getTransaction().commit();
HistoricoDeGraduacao hdg2 = new HistoricoDeGraduacao();
hdg2.setAluno(a);
hdg2.setGraduacao(g);
hdg2.setDataGraduou(new Date());
hdg2.setGrau("SECOND");
a.addHistoricoDeGraduacao(hdg2);
g.addHistoricoDeGraduacao(hdg2);
em.persist(hdg2);
em.getTransaction().commit();
HistoricoDeGraduacao hdg3 = new HistoricoDeGraduacao();
hdg3.setAluno(a);
hdg3.setGraduacao(g);
hdg3.setDataGraduou(new Date());
hdg3.setGrau("THIRD");
a.addHistoricoDeGraduacao(hdg3);
g.addHistoricoDeGraduacao(hdg3);
em.persist(hdg3);
em.getTransaction().commit();
em.close();
}
Using persist doesn't work, using merge works but the record is always updated and not add new records how I need.
Any idea how to I do this ?
after days searching and trying some solution, finally works !
here how I did
#Entity
#Table(name="aluno")
public class Aluno implements Serializable{
private static final long serialVersionUID = 1L;
#Id #GeneratedValue
private Integer id;
//informacoes gerais
#NotNull
private String nome;
//historico de graduacao
#OneToMany(mappedBy = "aluno", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<HistoricoDeGraduacao> listaHistoricoGraduacao;
public Aluno() {
}
public void addListaHistoricoGraduacao(HistoricoDeGraduacao hdg){
if(listaHistoricoGraduacao == null){
listaHistoricoGraduacao = new ArrayList<HistoricoDeGraduacao>();
}
listaHistoricoGraduacao.add(hdg);
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public List<HistoricoDeGraduacao> getListaHistoricoGraduacao() {
return listaHistoricoGraduacao;
}
public void setListaHistoricoGraduacao(List<HistoricoDeGraduacao> listaHistoricoGraduacao) {
this.listaHistoricoGraduacao = listaHistoricoGraduacao;
}
#Override
public int hashCode() {
int hash = 7;
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Aluno other = (Aluno) obj;
return true;
}
}
#Entity
#Table(name="graduacao")
public class Graduacao implements Serializable{
private static final long serialVersionUID = 1L;
#Id #GeneratedValue
private Integer id;
#NotNull #Column(unique = true)
private String graduacao;
#ElementCollection
#CollectionTable(name="graus_graduacao", joinColumns=#JoinColumn(name="id_graduacao"))
#Column(name="graus")
private List<String> graus;
#OneToMany(mappedBy = "graduacao", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<HistoricoDeGraduacao> listaHistoricoGraduacao;
public Graduacao() {
}
public Graduacao(Integer id, String graduacao, List<String> graus) {
this.id = id;
this.graduacao = graduacao;
this.graus = graus;
}
/** adiciona historicodegraduacao a graduacao */
public void addHistoricoDeGraduacao(HistoricoDeGraduacao hdg){
if(listaHistoricoGraduacao == null){
listaHistoricoGraduacao = new ArrayList<HistoricoDeGraduacao>();
}
listaHistoricoGraduacao.add(hdg);
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getGraduacao() {
return graduacao;
}
public void setGraduacao(String graduacao) {
this.graduacao = graduacao;
}
public List<String> getGraus() {
return graus;
}
public void setGraus(List<String> graus) {
this.graus = graus;
}
public List<HistoricoDeGraduacao> getListaHistoricoGraduacao() {
return listaHistoricoGraduacao;
}
public void setListaHistoricoGraduacao(List<HistoricoDeGraduacao> listaHistoricoGraduacao) {
this.listaHistoricoGraduacao = listaHistoricoGraduacao;
}
public String toString(){
return graduacao;
}
}
#Embeddable
public class HistoricoDeGraduacaoId implements Serializable {
private static final long serialVersionUID = 1L;
#JoinColumn(name="EMP_ID")
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Override
public boolean equals(Object obj) {
return super.equals(obj); //To change body of generated methods, choose Tools | Templates.
}
#Override
public int hashCode() {
return super.hashCode(); //To change body of generated methods, choose Tools | Templates.
}
}
#Entity
public class HistoricoDeGraduacao implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
HistoricoDeGraduacaoId pk;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "id_aluno")
private Aluno aluno;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name="id_graduacao")
private Graduacao graduacao;
private String grau;
#Temporal(TemporalType.DATE)
private Date dataGraduou;
public HistoricoDeGraduacao() {
}
public void begin(){
//instancia pk
pk = new HistoricoDeGraduacaoId();
//aqui insiro o id
pk.setId(new HistoricoDeGraduacaoDAO().getIndex());
}
public HistoricoDeGraduacaoId getPk() {
return pk;
}
public void setPk(HistoricoDeGraduacaoId pk) {
this.pk = pk;
}
public Aluno getAluno() {
return aluno;
}
public void setAluno(Aluno aluno) {
this.aluno = aluno;
}
public Graduacao getGraduacao() {
return graduacao;
}
public void setGraduacao(Graduacao graduacao) {
this.graduacao = graduacao;
}
public String getGrau() {
return grau;
}
public void setGrau(String grau) {
this.grau = grau;
}
public Date getDataGraduou() {
return dataGraduou;
}
public void setDataGraduou(Date dataGraduou) {
this.dataGraduou = dataGraduou;
}
#Override
public int hashCode() {
int hash = 3;
hash = 59 * hash + Objects.hashCode(this.aluno);
hash = 59 * hash + Objects.hashCode(this.graduacao);
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final HistoricoDeGraduacao other = (HistoricoDeGraduacao) obj;
if (!Objects.equals(this.aluno, other.aluno)) {
return false;
}
if (!Objects.equals(this.graduacao, other.graduacao)) {
return false;
}
return true;
}
}
//aqui meu jframe com seus componentes, pegando valores montando tudo para ser salvo
historico.setDataGraduou(jdp_dataGraduou.getDate());
historico.setGrau(jl_graus.getSelectedValue().toString());
//pega graduacao do jcombobox
Graduacao g = (Graduacao)cbx_graduacao.getSelectedItem();
historico.setGraduacao(g);
//bean aluno
historico.setAluno(bean);
//add a listas
bean.addListaHistoricoGraduacao(historico);
g.addHistoricoDeGraduacao(historico);
//inicia instancia de pk e insere o proximo id
historico.begin();
//salva tudo
new HistoricoDeGraduacaoDAO().update(historico);
//aqui meu DAO
public class HistoricoDeGraduacaoDAO {
private EntityManager em;
public HistoricoDeGraduacaoDAO(){
em = Persistencia.getEntityManager();
}
/** pega o ultimo valor da tabela HistoricoDeGraduacao e adiciona + 1 para o proximo indice */
public Integer getIndex(){
int count = 0;
Query query = em.createQuery("SELECT MAX(hdg.pk.id) FROM HistoricoDeGraduacao hdg");
if(query.getSingleResult() == null){
++count;
}else{
count = (int)query.getSingleResult() + 1;
}
return count;
}
/** executa update */
public void update(HistoricoDeGraduacao historico){
try{
em.getTransaction().begin();
em.merge(historico);
em.getTransaction().commit();
}catch(PersistenceException e){
JOptionPane.showMessageDialog(null, e.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
}finally{
em.close();
}
}
}
And result is: