I need to configure hibernate to avoid creating duplicate rows, (although the row exists it creates a new one, and since only one filed is set it set all the rest to NULL)
Lets say I have a row as following
id des index age
1 MyName 2 23
Although I just set MyName as des and it already exists in the Name table hibernate create a new row as following
id des index age
1 MyName 2 23
2 MyName Null Null << new row with null values will be created
rather than updating the previous one
When I want to sa . So I have added the following annotation to my class but it crossed the Entity, and dynamicUpdate.
@org.hibernate.annotations.Entity(
dynamicUpdate = true
)
I used @DynamicUpdate
as well, although hibernate accept it but still I have the same problem.
Is there any other method to do it ? Version of my hibernate is as following
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.2.1.Final</version>
<type>jar</type>
</dependency>
*Based on Ray's comment blew, By assigning a value to Id of child class it works properly but how about if I do not have the ID? do I have to do a select to find the id first ? Is there any method to force hibernate to do it automatically r based on values of child class rahter than doing a separate select to find the id? *
User.Java
....
import org.hibernate.annotations.DynamicUpdate;
@Entity
@Table(name = "user")
@DynamicUpdate
public class User implements Serializable {
private int ID;
private Name name;
private String type;
public User() {
}
@Id
@GeneratedValue
@Column(name = "id")
public int getID() {
return ID;
}
public void setID(int ID) {
this.ID = ID;
}
@ManyToOne(cascade = CascadeType.ALL)
public Name getName() {
return name;
}
public void setName(Name name) {
this.name = name;
}
.....
Name.Java
@Entity()
@Table(name = "Name")
public class Name implements Serializable {
private int id;
private String des;
private String index;
private String age;
public Name() {
}
@Id
@GeneratedValue
@Column(name="id", unique= true, nullable = false)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
.....
Model.java
public void addMyUsers(){
Name name = new Name();
name.setDes("MyName");
While( ..... )
{
User user = new User();
user.setName(name);
user.setType(X);
addUser(user);
}
}
public void addUser(User user) {
session = Util.getSession();
session.beginTransaction();
session.merge(user);
//session.saveOrUpdate(user);
session.getTransaction().commit();
session.close();
}
That's not quite right. It's not just hibernate automatically deciding to create a new user. Hibernate is doing what your code tells it to:
addMyUsers()
, you createnew Name()
andnew User()
, and you give neither of these a pre-existing ID. You have made these objects look like new ones, rather than pre-existing ones to be updated.addMyUser()
, you callsession.merge(user)
. Hibernate sees the objects have no ID - so it merges them and assigns them the NEW status. When the transaction is flushed & committed, hibernate generates SQL to create new IDs and store the objects as new records.If you want to determine whether an object is pre-existing, and operate on the previous record where possible:
session.find()
orsession.get()
, in your case using the "det" field.session.clear()
). Newly created objects are already in a detached state.session.merge()
. Merge works for both pre-existing detached objects (obtained via retrieval) and new detached objects (vianew <Object>()
). Alternatively, for pre-existing detached objects you can callsession.update()
and for new detached objects you can callsession.save()/persist()
.You're missing (2).
Have you configured this way. Please share ur code if its not this way.
Its primary key that plays important role here. you should use name as primary key in this case but i will not suggest you to do that, take id as primary key.
Update:
Also in case of update id should be same with the record you want to update, but in case of insertion, id should be null and you will get it inserted in db.
Answer to your comments :
you need to fetch the primary key and track it this way:
you must get the Name first, not new Name().
so use menu like "search user"/dropdown or something for user to choose the Name they want, then you can add that Name to new User.name
or if you dont want to search for Name first(from the thin air#lol), you should not use User.name with the type of Name in the first place, use string then. but it's more risky. and the relationship cant be build that way(you must query again if you want to get Name from the User that have name x).