Я использую Hibernate 3.3.1.
У меня есть таблица в дБ (2 поля: id
, name
).Используя Hibernate, я создал класс для этой таблицы.
@Entity
@Table(name = "table1")
public class QTable1 implements Serializable {
public QTable1() {
}
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.AUTO) //<- modification: to comment this line
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column(name = "name")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
После внесения изменений я хочу сохранить их, используя session.saveorUpdate
, и он сохраняет ALL строк, которые были загружены из базы данных.Даже если они не были изменены:
update table1 set name='a' where id=1
update table1 set name='b' where id=2
update table1 set name='cc' where id=3 // only this row changed
Код, изменяющий сущности:
final QTable1 item = (QTable1) listTable1.getSelectedValue();
if (item != null) {
item.setName(table1Name.getText());
}
Код транзакции:
final Session session = Commons.getSessionFactory().openSession();
session.beginTransaction();
for (Object o : pool.getTable1List().toArray()) {
final QTable1 item = (QTable1) o;
session.saveOrUpdate(item);
}
session.getTransaction().commit();
Почему он сохраняет все данные?
Если я изменю реализацию id (delete @GeneratedValue(strategy=GenerationType.AUTO)
):
@Id
@Column(name = "id")
private Long id;
Сохраняет только затронутые строки.И это то, что я ожидаю.Но без @GeneratedValue
, если я пытаюсь добавить новую строку в таблицу, я должен указать id
вручную, это не хорошо.
Во время отладки я увидел, что с помощью @GeneratedValue
у меня нет моегосущности в сеансе PersistanceContext
в entitySnapshotsByKey
, поэтому он считает, что мои сущности являются новыми и должны быть сброшены в дБ.
Как решить эту проблему?
ОБНОВЛЕНИЕ:
Если мы используем @GeneratedValue
, аннотация session.saveOrUpdate(item)
генерирует только update
или insert
запросов.Но если мы не используем @GeneratedValue
аннотацию session.saveOrUpdate(item)
генерирует 1) select
для запросов table1 2) сравнивает, равны ли объекты или нет 3) решает, нужно ли нам генерировать update
или insert
запросов.
Теперь я не могу понять, почему @GeneratedValue
запрещает запрашивать значения.Тем не менее, я не понимаю, почему он делает select
запросов, если в hibernate есть копия выбранных строк в памяти (entitySnapshotsByKey
).
Но я нашел решение, которое мне подходит просто отлично.Все, что мне нужно, это просто заменить session.saveOrUpdate(item)
на session.merge(item)
.Это гарантирует, что будет выполнен запрос select
и значения будут сравниваться (с использованием @GeneratedValue
или нет).Единственный недостаток - это потенциально большое количество запросов.
Спасибо всем.Будем рады, если вы поможете мне предотвратить генерацию select
запросов.