Hibernate генерирует ненужные запросы - PullRequest
1 голос
/ 09 декабря 2011

Я использую 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 запросов.

Ответы [ 2 ]

0 голосов
/ 09 декабря 2011

Это ожидаемое и задокументированное поведение.saveOrUpdate принимает отсоединенный (с идентификатором) или временный объект (без идентификатора), а затем обновляет его (если он отсоединен) или сохраняет его (если он временный).

saveOrUpdate незнать, изменилось ли какое-либо поле или нет.Он просто берет сущность и записывает ее в базу данных.

Вы можете использовать merge, которая выбирает сущность с заданным идентификатором из базы данных, а затем копирует все поля из отсоединенной сущности в присоединенную.один (а затем записывает объект в базу данных во время сброса, если что-то изменилось).Но для этого потребуется выбор, чтобы получить базу данных и сравнить новое состояние со старым.

0 голосов
/ 09 декабря 2011

Где-то в более низкой 3-й версии гибернация изменила поведение - больше не требуется явное сохранение загруженных сущностей (конечно, без надлежащей документации - это оторвало мне большую задницу), если оно считает, что они были изменены. Вы также можете поиграть с несохраненным значением.

Если вы хотите запретить сохранение постоянных сущностей, вы должны отсоединить их от сеанса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...