问题
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();
}
回答1:
although the row exists it creates a new one
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:
- In
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. - In
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:
- Obtain the fields that you want to use (e.g. from a web form) - in your case, this includes "det" field.
- See if the record already exists in the database. Retrieve the object using hibernate via
session.find()
orsession.get()
, in your case using the "det" field. - If the object cannot be found, then create a new object.
- For retrieved objects, you can optionally detach the object from the session before modification, (e.g. via
session.clear()
). Newly created objects are already in a detached state. - Modify the object (set it's fields).
- If the object is detached, then attach via
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()
. - flush/commit the transaction.
You're missing (2).
回答2:
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:
session.update(recordEntity);// or save
int id=recordEntity.getId();
回答3:
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).
回答4:
Have you configured this way. Please share ur code if its not this way.
@Entity
@Table(name = "example", catalog = "example_catalog")
@org.hibernate.annotations.Entity(
dynamicUpdate = true
)
来源:https://stackoverflow.com/questions/17080864/how-to-avoid-creating-a-new-row-if-similar-row-exists