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();
Related
I'm new to Java and even more newer to Spring (Boot and JPA) but I was curious, I'm trying to debug an issue that says, "No identifier specified for entity".
For illustartion purposes, I've created the following tables from this diagram:
Originally, there was a M:N relationship between the user and vehicle table, so I created an associative entity (UserVehicleAsso) to split the two up. I was following this guide on M:N mapping in Java, http://viralpatel.net/blogs/hibernate-many-to-many-annotation-mapping-tutorial/
For the most part, it was pretty straight forward but my question is, within the associative entity (UserVehicleAsso), do I have to use the #Id annotation for each of the foreign keys? I assume that I didn't need to because those were automatically generated from each of the respective tables.
Let me know your thoughts or comments, thanks.
Also, below is the code that I used to generate these models:
For the User table/class:
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int userId;
private String fName;
private String lName;
#ManyToMany(cascade = {CascadeType.ALL})
#JoinTable(name="userVehicleAsso",
joinColumns={#JoinColumn(name="userID")},
inverseJoinColumns={#JoinColumn(name="vehicleID")})
private Set<Vehicle> vehicles = new HashSet<Vehicle>();
//constructor
protected User() {}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getFName() {
return fName;
}
public void setFName(String fName) {
this.fName = fName;
}
public String getLName() {
return lName;
}
public void setLName(String lName) {
this.lName = lName;
}
public Set<Vehicle> getVehicles() {
return vehicles;
}
public void setVehicles(Set<Vehicle> vehicles) {
this.vehicles = vehicles;
}
#Override
public String toString() {
return getFName() + "," + getLName();
}}
For the Vehicle table/class:
#Entity
public class Vehicle {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int vehicleId;
private String brand;
private String model;
//foreign key mappings
//mapping with associative
#ManyToMany(mappedBy="vehicles")
private Set<User> users = new HashSet<User>();
//constructors
protected Vehicle() {}
public Vehicle(int id) {
this.vehicleId = id;
}
public Vehicle (String brand, String model) {
this.brand = brand;
this.model = model;
}
/* public Vehicle() {
}*/
public int getVehicleId() {
return vehicleId;
}
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
public void setVehicleId(int vehicleId) {
this.vehicleId = vehicleId;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
#Override
public String toString() {
// + setBodyType() + "," +
return getBrand() + "," + getModel();
}
}
And then finally, my associtive table/class:
#Entity
public class UserVehicleAsso{
private int userID;
private int vehicleID;
public int getUserID() {
return userID;
}
public void setUserID(int userID) {
this.userID = userID;
}
public int getVehicleID() {
return vehicleID;
}
public void setVehicleID(int vehicleID) {
this.vehicleID = vehicleID;
}
}
In my opinion, it's not necessary to have an Entity class for the middle table in your case. The table will be generated automatically if configured correctly. In this table, there would not be column ID, only two columns with userID and vehicleID data.
Now, if your middle table has more than what are needed to establish the M:N relationship, then your middle Entity class is needed, and the ID of it, too. For example, if this class is intended to store the time stamp every time a relationship is established, you have to:
Create this Entity class,
Give it an ID field with proper generation strategy,
Map the time stamp with a field with adequate type, annotation/XML mapping and so on.
This part of JPA/Hibernate have confused me a lot and I used to get into them. If my memory serves me well this is the proper/perfect way how things should work.
You can specify a composite primary key class that is mapped to multiple fields or properties of the entity.
Here are sample codes:
public class ActivityRegPK implements Serializable {
private int activityId;
private int memberId;
public int getActivityId() {
return activityId;
}
public void setActivityId(int activityId) {
this.activityId = activityId;
}
public int getMemberId() {
return memberId;
}
public void setMemberId(int memberId) {
this.memberId = memberId;
}
}
associtive table/class:
#IdClass(ActivityRegPK.class)
#Entity
#Table(name="activity_reg")
#NamedQuery(name="ActivityReg.findAll", query="SELECT a FROM ActivityReg a")
public class ActivityReg implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name="activity_id")
private int activityId;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="ins_date")
private Date insDate;
#Id
#Column(name="member_id")
private int memberId;
}
Activity.class
#Entity
#NamedQuery(name="Activity.findAll", query="SELECT a FROM Activity a")
public class Activity implements Serializable {
// some attributes
}
While there is plenty of information around on how to model, in JPA (2), a one-to-one relationship OR an entity having a natural key, I haven't been able to find a clear / simple answer to how to model the situation where we have both, i.e. a one-to-one relationship where the parent table has a natural key. It could obviously be that I might have missed such a tutorial; if so, pointing me to one could also be the answer.
And, as many times with JPA and noobs such as I, the moment one needs a bit more than the most basic model, one can quickly hit the wall.
Hence, considering the following DB model:
What would be the corresponding JPA-annotated object model? (I'm sparing you guys of the things I've tried since I don't want to influence the answer...)
Performance recommendations are also welcome (e.g. "a one-to-many could perform faster", etc.)!
Thanks,
The composite identifier is built out of two numerical columns so the mapping looks like this:
#Embeddable
public class EmployeeId implements Serializable {
private Long companyId;
private Long employeeId;
public EmployeeId() {
}
public EmployeeId(Long companyId, Long employeeId) {
this.companyId = companyId;
this.employeeId = employeeId;
}
public Long getCompanyId() {
return companyId;
}
public Long getEmployeeId() {
return employeeId;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof EmployeeId)) return false;
EmployeeId that = (EmployeeId) o;
return Objects.equals(getCompanyId(), that.getCompanyId()) &&
Objects.equals(getEmployeeId(), that.getEmployeeId());
}
#Override
public int hashCode() {
return Objects.hash(getCompanyId(), getEmployeeId());
}
}
The parent class, looks as follows:
#Entity(name = "Employee")
public static class Employee {
#EmbeddedId
private EmployeeId id;
private String name;
#OneToOne(mappedBy = "employee")
private EmployeeDetails details;
public EmployeeId getId() {
return id;
}
public void setId(EmployeeId id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public EmployeeDetails getDetails() {
return details;
}
public void setDetails(EmployeeDetails details) {
this.details = details;
}
}
And the child like this:
#Entity(name = "EmployeeDetails")
public static class EmployeeDetails {
#EmbeddedId
private EmployeeId id;
#MapsId
#OneToOne
private Employee employee;
private String details;
public EmployeeId getId() {
return id;
}
public void setId(EmployeeId id) {
this.id = id;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
this.id = employee.getId();
}
public String getDetails() {
return details;
}
public void setDetails(String details) {
this.details = details;
}
}
And everything works just fine:
doInJPA(entityManager -> {
Employee employee = new Employee();
employee.setId(new EmployeeId(1L, 100L));
employee.setName("Vlad Mihalcea");
entityManager.persist(employee);
});
doInJPA(entityManager -> {
Employee employee = entityManager.find(Employee.class, new EmployeeId(1L, 100L));
EmployeeDetails employeeDetails = new EmployeeDetails();
employeeDetails.setEmployee(employee);
employeeDetails.setDetails("High-Performance Java Persistence");
entityManager.persist(employeeDetails);
});
doInJPA(entityManager -> {
EmployeeDetails employeeDetails = entityManager.find(EmployeeDetails.class, new EmployeeId(1L, 100L));
assertNotNull(employeeDetails);
});
doInJPA(entityManager -> {
Phone phone = entityManager.find(Phone.class, "012-345-6789");
assertNotNull(phone);
assertEquals(new EmployeeId(1L, 100L), phone.getEmployee().getId());
});
Code available on GitHub.
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
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.
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.