Спящий режим, вставка или обновление без выбора

У меня есть объекты продуктов, которые относятся к определенным категориям, то есть к классическим отношениям много к одному.

@Entity
public class Product{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    Long id;

    String name;
    Double price;
    @ManyToOne(fetch = FetchType.LAZY)
    Category category;
...
}

@Entity
public class Category implements Identifiable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;
...
}

Я хочу вставлять и обновлять продукты без предварительного выбора категорий. Вот так:

Product product = dao.get(productId);
Category category = dao.get(categoryId);
product.setCategory(category);
dao.update(product);

или

Product product = new Product(somename);
Category category = dao.get(categoryId);
product.setCategory(category);
dao.insert(product);

Можно ли обновить и вставить без выбора категории? Я не хочу использовать для этого HQL или прямые запросы.

Ответ 1

session.load() существует специально для таких случаев. Следующее:

Category category = session.load(categoryId);
product.setCategory(category);

не попадет в базу данных. Тем не менее, он будет генерировать исключение на более позднем этапе (во время flush, более или менее), если нет категории, доступной с данным идентификатором.

Использование load() быстрее, чем merge() и не имеет побочных эффектов (каскадирование и т.д.)

Ответ 2

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

Решение заключается в загрузке категорий при запуске, настройке кэширующего провайдера, такого как ehcache для этого класса, и затем использования этого кода:

Product product = new Product(somename);
product.setCategory(session.merge(category));

Это не вызовет каких-либо переходов DB, ​​если вы настроите кеш, которые не могут изменить эти категории.

Ответ 3

Я только что попробовал следующее:

Category category = new Category(categoryId);
product.setCategory(category);

И это сработало, я имею в виду, что запись продукта в db получила правильную ссылку на категорию и категорию с id

categoryId

не изменились.