#java #mysql #sql #hibernate #jpa
#java #mysql #sql #спящий режим #jpa
Вопрос:
Предыстория
В моем проекте есть две сущности. Один называется «Объект», а другой — отношение. Я использую их для имитации связи между объектами в моей игре. Итак, в моей базе данных есть какое-то дерево / иерархия… но в моей игре это не так. Мои объекты выглядят так…
@Entity
@Table(name = "entity")
@Access(AccessType.FIELD)
public class EntityPojo implements Serializable {
@Id public long id;
@OneToMany(mappedBy = "owner", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
public Set<RelationshipPojo> relations = new LinkedHashSet<>();
}
@Entity
@Table(name = "relationship")
@Access(AccessType.FIELD)
public class RelationshipPojo {
@Id
public long id;
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "entity_id")
public EntityPojo owner;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
public Set<EntityPojo> targets = new LinkedHashSet<>();
}
Проблема
Может случиться так, что один из моих игровых объектов сохраняется, когда он ссылается на несохраненный объект. Представьте себе этот сценарий… Во время моей игры я создаю несколько игровых объектов и их сущностей-pojo. Затем один из них (плитка) сохраняется, но не может получить прокси для несохраненного объекта, что вызывает исключение ObjectNotFoundException.
var tile = new EntityPojo();
tile.id = 1;
var player = new EntityPojo();
player.id = 2;
var proxy = session.getReference(EntityPojo.class, 2L); // Reference to unsaved player
var inTileRelation = new RelationshipPojo();
inTileRelation.name = "inTile";
inTileRelation.owner = tile;
inTileRelation.targets.add(proxy); // ObjectNotFoundException
tile.relations.add(inTileRelation);
// Tile gets saved before player was saved...
syncDatabase.save(tile);
Вопрос
Почему именно это происходит и как я могу это предотвратить? Возможно ли вообще сохранить ссылку на другой объект, используя прокси? Просто имея его идентификатор, который будет иметь объект в будущем? Как я мог бы заставить это работать?
В SQL я бы просто удалил ограничения для вставки самого идентификатора … возможно ли это в режиме гибернации?
Ответ №1:
Как указано в документации:
Получение ссылки на объект без инициализации его данных
Иногда называемая отложенной загрузкой, возможность получить ссылку на объект без необходимости загружать его данные чрезвычайно важна. Наиболее распространенным случаем является необходимость создания связи между сущностью и другой существующей сущностью.
Book book = new Book(); book.setAuthor( entityManager.getReference( Person.class, personId ) );
Приведенное выше работает в предположении, что объект определен так, чтобы разрешать отложенную загрузку, как правило, с помощью прокси-серверов времени выполнения. В обоих случаях исключение будет выдано позже, если данный объект не ссылается на фактическое состояние базы данных, когда приложение пытается использовать возвращенный прокси-сервер любым способом, требующим доступа к его данным.
Таким образом, вы можете использовать entityManager.getReference
только в том случае, если вы знаете, что в вашей базе данных есть запись с указанным идентификатором, и вы просто хотите установить связь без фактической загрузки объекта.
Комментарии:
1. Спасибо ^^ все работает должным образом, когда я сохраняю объект, прежде чем ссылаться на него.