Jackson with Spring MVC duplicate nested objects not deserializing - java

I am trying to Convert following POJO to a JSON in #RestController:
#Entity
#Table(name="user_location")
#NamedQuery(name="UserLocation.findAll", query="SELECT u FROM UserLocation u")
public class UserLocation implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String addr1;
private String addr2;
private String landmark;
private BigDecimal lat;
private BigDecimal lng;
private String zipcode;
//bi-directional many-to-one association to City
#ManyToOne
private City city;
//bi-directional many-to-one association to State
#ManyToOne
private State state;
public UserLocation() {
}
//Getter - Setters
}
Nested City.java is as follow:
#Entity
#NamedQuery(name="City.findAll", query="SELECT c FROM City c")
#JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property="#id", scope = City.class)
public class City implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
//bi-directional many-to-one association to State
#ManyToOne
#JsonIgnore
private State state;
//bi-directional many-to-one association to UserLocation
#OneToMany(mappedBy="city")
#JsonIgnore
private List<UserLocation> userLocations;
public City() {
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#JsonProperty("state")
public State getState() {
return this.state;
}
public void setState(State state) {
this.state = state;
}
public List<UserLocation> getUserLocations() {
return this.userLocations;
}
public void setUserLocations(List<UserLocation> userLocations) {
this.userLocations = userLocations;
}
public UserLocation addUserLocation(UserLocation userLocation) {
getUserLocations().add(userLocation);
userLocation.setCity(this);
return userLocation;
}
public UserLocation removeUserLocation(UserLocation userLocation) {
getUserLocations().remove(userLocation);
userLocation.setCity(null);
return userLocation;
}
}
Another nested class State.java is as follow:
#Entity
#NamedQuery(name="State.findAll", query="SELECT s FROM State s")
#JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property="#id", scope = State.class)
public class State implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
//bi-directional many-to-one association to City
#OneToMany(mappedBy="state")
#JsonIgnore
private List<City> cities;
//bi-directional many-to-one association to UserLocation
#OneToMany(mappedBy="state")
#JsonIgnore
private List<UserLocation> userLocations;
public State() {
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public List<City> getCities() {
return this.cities;
}
public void setCities(List<City> cities) {
this.cities = cities;
}
public City addCity(City city) {
getCities().add(city);
city.setState(this);
return city;
}
public City removeCity(City city) {
getCities().remove(city);
city.setState(null);
return city;
}
public List<UserLocation> getUserLocations() {
return this.userLocations;
}
public void setUserLocations(List<UserLocation> userLocations) {
this.userLocations = userLocations;
}
public UserLocation addUserLocation(UserLocation userLocation) {
getUserLocations().add(userLocation);
userLocation.setState(this);
return userLocation;
}
public UserLocation removeUserLocation(UserLocation userLocation) {
getUserLocations().remove(userLocation);
userLocation.setState(null);
return userLocation;
}
}
The JSON converted from UserLocation.java is as follow:
{
id: 1,
addr1: "11905 Technology",
addr2: "Eden Prairie",
landmark: null,
lat: null,
lng: null,
zipcode: "55344",
city: {
#id: 1,
id: 2,
name: "Westborough",
state: {
#id: 1,
id: 2,
name: "MA"
}
},
state: 1
}
As you can see, the State object is coming as a whole object inside city. But outer state (property of 'UserLocationis showing just an id ofStateobject. I need to have a samestateobject as that ofcity` instead of just id.
I am relatively new to JackSon api. Please advice which approach I should follow to achieve this requirement.
Thanks

This is how jackson designed JsonIdentityInfo annotation logic.
* Annotation used for indicating that values of annotated type
* or property should be serializing so that instances either
* contain additional object identifier (in addition actual object
* properties), or as a reference that consists of an object id
* that refers to a full serialization. In practice this is done
* by serializing the first instance as full object and object
* identity, and other references to the object as reference values.
Jackson will run the full serialization first time and only id will be serialized when it find that object second time.
So, there is two ways how you can fix it:
1) you can simple remove the #JsonIdentityInfo annotation and Jackson will serialize object as you expected but it will remove the #id field from the response. This is probably fine because you still will have 'id' property.
2) I feel like you can simply restructure your objects and delete some references. I would say it is good to do these changes anyway. First of all you can delete reference to the State from UserLocation. I would say that it is not necessary to have the State in userLocation class because of the State is attached to the City.
By doing this you will access State from the City and your problem is solved.
Also I would delete the reference to the list of userLocations from the City class as well as from State class.
It will look like:
UserLocation has City and doesn't have State.
City has State and doesn't have userLocations
State doesn't have userLocations as well as cities.
Hope this helps

First remove that annotations from your State.java and City.java
#JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property="#id", scope = State.class)
#JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property="#id", scope = City.class)
No need of these annotations and in RestController add return type as #ResponseBody UserLocation . It will give you json of that class.

Related

How to create a many to many relationship with extra columns in jhipster?

The jhipster doesn't support create many to many relationships with extra fields.
What is the best way to create many to many association with extra columns in jhispter? Should i create a two one-to-many relationship with extra fields?
Using JHipster Domain Language (JDL), a #ManytoMany holding extra properties (columns) can be easily achieved using an association entity and two ManyToOne relationships. See below:
entity Foo{
...
}
entity Bar{
...
}
entity FooBarAssociation{
extraProperty1 String
extraProperty2 String
...
}
relationship ManyToOne {
FooBarAssociation{foo} to Foo{bars}
FooBarAssociation{bar} to Bar{foos}
}
You will have to do it manually.
this post describes how: https://hellokoding.com/jpa-many-to-many-extra-columns-relationship-mapping-example-with-spring-boot-maven-and-mysql/
In general, as #Antares42 said, you should create an entity for the Many-To-Many table like so:
first entity:
#Entity
public class Book{
private int id;
private String name;
private Set<BookPublisher> bookPublishers;
public Book() {
}
public Book(String name) {
this.name = name;
bookPublishers = new HashSet<>();
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(mappedBy = "book", cascade = CascadeType.ALL, orphanRemoval = true)
public Set<BookPublisher> getBookPublishers() {
return bookPublishers;
}
public void setBookPublishers(Set<BookPublisher> bookPublishers) {
this.bookPublishers = bookPublishers;
}
}
secound entity:
#Entity
public class Publisher {
private int id;
private String name;
private Set<BookPublisher> bookPublishers;
public Publisher(){
}
public Publisher(String name){
this.name = name;
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(mappedBy = "publisher")
public Set<BookPublisher> getBookPublishers() {
return bookPublishers;
}
public void setBookPublishers(Set<BookPublisher> bookPublishers) {
this.bookPublishers = bookPublishers;
}
}
Join table entity:
#Entity
#Table(name = "book_publisher")
public class BookPublisher implements Serializable{
private Book book;
private Publisher publisher;
private Date publishedDate;
#Id
#ManyToOne
#JoinColumn(name = "book_id")
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
#Id
#ManyToOne
#JoinColumn(name = "publisher_id")
public Publisher getPublisher() {
return publisher;
}
public void setPublisher(Publisher publisher) {
this.publisher = publisher;
}
#Column(name = "published_date")
public Date getPublishedDate() {
return publishedDate;
}
public void setPublishedDate(Date publishedDate) {
this.publishedDate = publishedDate;
}
}
This entity describes the relationship between Book and Publisher and the extra field is published_date
Let's say you have entities like Movie, Rater and needs a join table Ratings. You can write a JDL script like the following:
entity Movie { title String}
entity Rater { name String}
entity Rating { value Integer} //the extra field
relationship ManyToMany {
Rating{rater(name)} to Rater,
Rating{movie(title)} to Movie
}
save it in file.jdl in the project folder, open cmd type
jhipster import-jdl file.jdl
and you have everything

Hibernate relationship foreign key constraint fails

I've put together two basic classes/tables in order to learn how the use Hibernate.
Upon execution of the following code;
Session hbSession = HibernateUtil.getSession();
Showroom showroom = new Showroom();
showroom.setLocation("London");
showroom.setManager("John Doe");
List<Car> cars = new ArrayList<Car>();
cars.add(new Car("Vauxhall Astra", "White"));
cars.add(new Car("Nissan Juke", "Red"));
showroom.setCars(cars);
hbSession.beginTransaction();
hbSession.save(showroom);
hbSession.getTransaction().commit();
I'm getting this error;
Cannot add or update a child row: a foreign key constraint fails (`ticket`.`Car`, CONSTRAINT `FK107B4D9254CE5` FOREIGN KEY (`showroomId`) REFERENCES `Showroom` (`id`))
I'm not really sure where it's going wrong. Here are the two annotated classes;
#Entity
public class Showroom {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#OneToMany
#JoinColumn(name="showroomId")
#Cascade(CascadeType.ALL)
private List<Car> cars = null;
private String manager = null;
private String location = null;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public List<Car> getCars() {
return cars;
}
public void setCars(List<Car> cars) {
this.cars = cars;
}
public String getManager() {
return manager;
}
public void setManager(String manager) {
this.manager = manager;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}
#Entity
public class Car {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
private String color;
private int showroomId;
public Car(String name, String color) {
this.setName(name);
this.setColor(color);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getShowroomId() {
return showroomId;
}
public void setShowroomId(int showroomId) {
this.showroomId = showroomId;
}
}
For the time being I've let Hibernate create the tables in the MySQL database. I've checked and the relationship between the database does exist in the Car table.
Is anyone able to tell my why this isn't working?
At a guess I'm saying it's because the showroom doesn't have an Id, as this is auto-generated by MySQL, so the cars cannot be saved? Is that right?
You have a couple problems here.
In Car, you have a field that is supposed to be a FK reference to the Showroom. However, this is a native int. That means that it has a value of zero.
If your Car object should reference your Showroom, then you would have to add a reference with #ManyToOne
#ManyToOne
#JoinColumn(name="showroomId")
private Showroom showroom;
Then your field in Showroom changes to
#OneToMany(mappedBy = "showroom")
#Cascade(value = { org.hibernate.annotations.CascadeType.ALL } )
private List<Car> cars = null;
If you do this, you need to set the reference in Car explicitly.
Either way, the showroomId (also a native int) needs to go. Either you shouldn't have the field in your Car object at all, and you have only the backref List, or you need to replace it with a properly mapped Entity reference (see above).
The other problem is that your generated Column is a native type. This becomes a value of 0, and Hibernate will not automatically/correctly generate the value.
Change your primary key reference in both Entities (along with the getters and setters)
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
In order to load the entities successfully from the DB, I also had to add a default constructor for Car.
protected Car() {
}
Then your example will work.
I've managed to get this working. The first problem was that I didn't have a showroom property in my Car class. The second was the way I was saving the objects didn't seem to be correct.
I've altered my classes to this..
#Entity
public class Showroom {
#Id
#GeneratedValue
private int id;
private String location;
private String manager;
#OneToMany(mappedBy="showroom")
private List<Car> cars;
public List<Car> getCars() {
return cars;
}
public void setCars(List<Car> cars) {
this.cars = cars;
}
}
#Entity
public class Car {
#Id
#GeneratedValue
private int Id;
private String name;
private String color;
#ManyToOne
#JoinColumn(name="showroomId")
private Showroom showroom;
public Car(String name, String color) {
this.name = name;
this.color = color;
}
}
And the save functions are now;
Session hbSession = HibernateUtil.getSession();
hbSession.beginTransaction();
// Create a showroom
Showroom showroom = new Showroom();
showroom.setManager("John Doe");
showroom.setLocation("London");
hbSession.save(showroom);
// Create car one, assign the showroom and save
Car car1 = new Car("Vauxhall Astra", "White");
car1.setShowroom(showroom);
hbSession.save(car1);
// Create car two, assign the showroom and save
Car car2 = new Car("Nissan Juke", "Red");
car2.setShowroom(showroom);
hbSession.save(car2);
hbSession.getTransaction().commit();

Getting #Id of lazy-loaded #ManyToOne entity allways returns null

I am using Hibernate 4.3.8.Final and have problem with retrieving #Id property of lazy fetched property: For attached classes calling aidConfiguration.getChipApplication().getId() allways returns null. Other properties, eg. aidConfiguration.getChipApplication().getVersion() returns correctly the value from DB. If chipApplication is not lazy loaded (see the comment in the code), then aidConfiguration.getChipApplication().getId() returns correct non-null value.
What am I dong wrong?
BTW I need it to be lazy.
BaseEntity:
#MappedSuperclass
public class BaseEntity implements Serializable {
#Id
#Column(name = "ID", unique = true)
#Size(min = 1, max = 255)
private String id;
#PrePersist
public final void generateUuid() {
if (this.getId() == null) {
this.setId(UUID.randomUUID().toString());
}
}
public final String getId() {
return id;
}
public final void setId(final String id) {
this.id = id;
}
}
AidConfiguration:
#Entity
#Audited
public class AidConfiguration extends BaseEntity {
#Column
#NotBlank
private String name;
#NotNull
#ManyToOne(fetch = FetchType.LAZY) // if it is EAGER (defaut) then then aidConfiguration.getChipApplication().getId() returns correctly non-null value
private ChipApplication chipApplication;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "aidConfiguration", cascade = CascadeType.ALL) // cascade for auto-saving and deleting items
private List<AidConfigurationItem> aidConfigurationItems;
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public ChipApplication getChipApplication() {
return chipApplication;
}
public void setChipApplication(final ChipApplication chipApplication) {
this.chipApplication = chipApplication;
}
public List<AidConfigurationItem> getAidConfigurationItems() {
return aidConfigurationItems;
}
public void setAidConfigurationItems(final List<AidConfigurationItem> aidConfigurationItems) {
this.aidConfigurationItems = aidConfigurationItems;
}
}
ChipApplication:
#Entity
#Audited
public class ChipApplication extends BaseEntity {
#Column
#NotBlank(message = "Aid can not be empty")
private String aid;
#Column
#NotBlank(message = "Product can not be empty")
private String product;
#Column
#NotBlank(message = "Version can not be empty")
private String version;
#NotNull(message = "Network is mandatory")
#ManyToOne(fetch = FetchType.LAZY)
private Network network;
#ManyToMany(fetch = FetchType.EAGER)
private List<AidTag> aidTags;
public String getAid() {
return aid;
}
public void setAid(final String aid) {
this.aid = aid;
}
public String getProduct() {
return product;
}
public void setProduct(final String product) {
this.product = product;
}
public String getVersion() {
return version;
}
public void setVersion(final String version) {
this.version = version;
}
public Network getNetwork() {
return network;
}
public void setNetwork(final Network network) {
this.network = network;
}
public List<AidTag> getAidTags() {
return aidTags;
}
public void setAidTags(final List<AidTag> aidTags) {
this.aidTags = aidTags;
}
}
Bit late, but the issue HH-9588 is still unresolved, and I just had the same issue (XML mapping rather than annotations, though).
Could not get the id from the getter when the binding was lazy. Got it when eager or fetch join.
Fixed it by getting rid of the "final" modifier on the getId() accessor. (final here was an attempt to protect the way primary keys/identifiers are defined in the superclass for all the entities)
before :
public abstract class Foo {
Long id;
public final Long getId() {
return id;
}
protected final void setId( Long id ){
this.id = id;
}
...
after :
public abstract class Foo {
Long id;
// No more final
public Long getId() {
return id;
}
// No more final
protected void setId( Long id ){
this.id = id;
}
...
Now, I can get the Id with a lazy binding as well.
Seems to me that this "final" modifier does not allow Hibernate to proxy this accessor as intended. The other accessors being not "final", one can access their values from the proxy.
So, I wonder whether HH-9588 is really a bug or a misunderstanding of the hibernate ways ?
That seems a bug, if you do not miss anything. I would report it on Hibernate's bug tracking system. It would be nice if you would update this answer afterwards with a link to the bug.

Correct XML annotations. Java. JAXB

There is a structure. I want to link the three entities in this way: the Company should contain id, name of company and the list of Departments, each Department has a list of Workers, id and name of department. Each worker has name, id.
+Company
-int companyId
-String companyName
-Set<Department> listOfDepartments = new HashSet<Department>();
+Department
-int departmentId
-String departmentName
-Set<Worker> listOfWorkers = new HashSet<Worker>();
+Worker
-int workerId
-String workerName
My attempt:
Company
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
#Entity
public class Company {
#Id #GeneratedValue(strategy = GenerationType.AUTO)
private int companyId;
private String companyName;
#XmlElementWrapper(name="listOfDepartments")
#XmlElement
#OneToMany(mappedBy = "company", cascade=CascadeType.PERSIST, fetch = FetchType.EAGER)
private Set<Department> listOfDepartments = new HashSet<Department>();
public Set<Department> getListOfDepartments() {
return listOfDepartments;
}
public void setListOfDepartments(Set<Department> listOfDepartments) {
this.listOfDepartments = listOfDepartments;
}
public Company(){}
public Company(String companyName){
this.companyName = companyName;
}
#XmlAttribute(name="id")
public int getCompanyId() {
return companyId;
}
public void setCompanyId(int companyId) {
this.companyId = companyId;
}
#XmlElement(name="companyName")
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
Department
#Entity
public class Department {
#Id #GeneratedValue(strategy = GenerationType.AUTO)
private int idDepartment;
private String departmentName;
#XmlAttribute(name="companyId")
#ManyToOne()
#JoinColumn(name="companyId")
private Company company;
#XmlElementWrapper(name="listOfWorkers")
#XmlElement
#OneToMany(mappedBy = "department", cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
private Set<Worker> listOfWorkers = new HashSet<Worker>();
public Set<Worker> getListOfWorkers() {
return listOfWorkers;
}
public void setListOfWorkers(Set<Worker> listOfWorkers) {
this.listOfWorkers = listOfWorkers;
}
public Department(){}
public Department(String departmentName, Company company){
this.departmentName = departmentName;
this.company = company;
}
#XmlAttribute(name="id")
public int getIdDepartment() {
return idDepartment;
}
public void setIdDepartment(int idDepartment) {
this.idDepartment = idDepartment;
}
#XmlElement(name="departmentName")
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
Worker
#Entity
public class Worker {
#Id #GeneratedValue(strategy = GenerationType.AUTO)
private int idWorker;
private String workerName;
#ManyToOne
#JoinColumn(name="departmentId")
private Department department;
public Worker(){}
public Worker(String workerName,Department department){
this.workerName = workerName;
this.department = department;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
#XmlAttribute(name="id")
public int getIdWorker() {
return idWorker;
}
public void setIdWorker(int idWorker) {
this.idWorker = idWorker;
}
#XmlElement(name="name")
public String getWorkerName() {
return workerName;
}
public void setWorkerName(String workerName) {
this.workerName = workerName;
}
}
I catched the error:
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 3 counts of IllegalAnnotationExceptions
Class has two properties of the same name "companyId"
this problem is related to the following location:
at public int ru.eldarkaa.dto.Company.getCompanyId()
at ru.eldarkaa.dto.Company
this problem is related to the following location:
at private int ru.eldarkaa.dto.Company.companyId
at ru.eldarkaa.dto.Company
Class has two properties of the same name "companyName"
this problem is related to the following location:
at public java.lang.String ru.eldarkaa.dto.Company.getCompanyName()
at ru.eldarkaa.dto.Company
this problem is related to the following location:
at private java.lang.String ru.eldarkaa.dto.Company.companyName
at ru.eldarkaa.dto.Company
Class has two properties of the same name "listOfWorkers"
this problem is related to the following location:
at public java.util.Set ru.eldarkaa.dto.Department.getListOfWorkers()
at ru.eldarkaa.dto.Department
at private java.util.Set ru.eldarkaa.dto.Company.listOfDepartments
at ru.eldarkaa.dto.Company
this problem is related to the following location:
at private java.util.Set ru.eldarkaa.dto.Department.listOfWorkers
at ru.eldarkaa.dto.Department
at private java.util.Set ru.eldarkaa.dto.Company.listOfDepartments
at ru.eldarkaa.dto.Company
GODs of XML Annotations please advise me a solution.
By default JAXB treats public fields and properties as mapped. When you annotate a non-public field it causes that to become mapped as well resulting in the conflict.
Solutions
Annotate the property (get or set method) instead of the field (instance variable).
Annotate the field and the class with #XmlAccessorType(XmlAccessType.FIELD).
For More Information
http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html

hibernate.hbm2ddl.auto=update don't work

I have model. there is this part:
model was mapped by jpa annotations.Everywhere I use fetchType = EAGER. If I load vacancy from database, I have 2 duplicates status_for_vacancy objects.
I use property hbm2ddl.auto = update.
If I make new schema of database and fill data, I haven't duplicates status_for_vacancy objects.
It really?
code:
vacancy:
#Entity
#Table(name = "vacancy")
#XmlRootElement(name="vacancy")
public class Vacancy {
private List<VacancyStatus> statusList = new LinkedList<VacancyStatus>();
#OneToMany(mappedBy = "vacancy", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
public List<VacancyStatus> getStatusList() {
return statusList;
}
public void setStatusList(List<VacancyStatus> statusList) {
this.statusList = statusList;
}
}
status_for_vacancy:
#Entity
#Table(name = "status_for_vacancy")
public class StatusForVacancy extends AbstractStatus {
public StatusForVacancy() {
super();
}
public StatusForVacancy(Integer id, String name) {
super(id, name);
}
}
#MappedSuperclass
#XmlRootElement
public abstract class AbstractStatus {
private Integer id;
private String name;
public AbstractStatus() {
super();
}
public AbstractStatus(String name) {
super();
this.name = name;
}
public AbstractStatus(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column (name ="id")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "name")
#NotEmpty
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
vacancy_status:
#Entity
#Table(name = "vacancy_status")
public class VacancyStatus extends AbstractHistoryStatus {
private Vacancy vacancy;
private StatusForVacancy status;
public VacancyStatus() {
super();
}
public VacancyStatus(Integer id, User author, Date date,
Vacancy vacancy, StatusForVacancy status) {
super(id, author, date);
this.vacancy = vacancy;
this.status = status;
}
#ManyToOne
#JoinColumn(name = "vacancy_id")
public Vacancy getVacancy() {
return vacancy;
}
public void setVacancy(Vacancy vacancy) {
this.vacancy = vacancy;
}
#ManyToOne
#JoinColumn(name = "status_id")
public StatusForVacancy getStatus() {
return status;
}
public void setStatus(StatusForVacancy status) {
this.status = status;
}
}
#MappedSuperclass
public abstract class AbstractHistoryStatus {
private Integer id;
private User author;
private Date date;
public AbstractHistoryStatus() {
}
public AbstractHistoryStatus(Integer id, User author, Date date) {
super();
this.id = id;
this.author = author;
this.date = date;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#ManyToOne
public User getAuthor() {
return author;
}
public void setAuthor(User author) {
this.author = author;
}
#Column(name="creation_date")
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
It is all mapping code for these entities.
in debugger:
both id==500 ==> hibernate understand, that it is same objects.
I try add all data from old database to new database - I get old error(
I fix cause of appearance of this problem. It appearances if I add record to note table:
I highly recommend you write equals() and hashCode() methods. The standard equals()/hashCode() implement referential equality (do 2 objects reference the same memory location). So if hibernate has 2 of the 'same' object in memory, but they don't reference the same memory location then you will see the object show up twice. But if you implement equals() based on primary key being equal, then even if there are two copies of the same object in memory, Hibernate won't give you duplicates.
See the JPA spec:
2.4 Primary Keys and Entity Identity
Every entity must have a primary key. ... The value of its primary key
uniquely identifies an entity instance within a persistence context
and to EntityManager operations
Also see this SO post.

Categories

Resources