23 ответов:
вы должны включить
cascade="all"(Если используется xml) илиcascade=CascadeType.ALL(при использовании аннотаций) в сопоставлении коллекции.это происходит потому, что у вас есть коллекция в сущности, и эта коллекция имеет один или несколько элементов, которые не присутствуют в базе. Указав вышеуказанные параметры, вы сообщаете hibernate, чтобы сохранить их в базе данных при сохранении их родителя.
я считаю, что это может быть просто повторный ответ, но просто чтобы уточнить, я получил это на
@OneToOneотображение, а также@OneToMany. В обоих случаях дело было в том, чтоChildобъект, который я добавлял кParentеще не был сохранен в базе данных. Поэтому, когда я добавилChildдоParent, потом спасParent, спящий будет бросать"object references an unsaved transient instance - save the transient instance before flushing"сообщение при сохранении родителя.добавить в
cascade = {CascadeType.ALL}наParent'sссылкаChildрешить проблему оба дела. Это спаслоChildиParent.извините за повторение ответы, просто хотел уточнить для людей.
@OneToOne(cascade = {CascadeType.ALL}) @JoinColumn(name = "performancelog_id") public PerformanceLog getPerformanceLog() { return performanceLog; }
Это происходит при сохранении объекта, когда Hibernate думает, что ему нужно сохранить объект, связанный с тем, который вы сохраняете.
У меня была эта проблема, и я не хотел сохранять изменения в ссылочном объекте, поэтому я хотел, чтобы тип каскада был NONE.
хитрость заключается в том, чтобы убедиться, что идентификатор и версия в ссылочном объекте установлены так, чтобы Hibernate не думал, что ссылочный объект является новым объектом, который нуждается в сохранении. Это сработало для мне.
просмотрите все отношения в классе, который вы сохраняете, чтобы разработать связанные объекты (и связанные объекты связанных объектов) и убедиться, что идентификатор и версия установлены во всех объектах дерева объектов.
или, если вы хотите использовать минимальные "полномочия" (например, если вы не хотите каскадного удаления), чтобы достичь того, что вы хотите, используйте
import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; ... @Cascade({CascadeType.SAVE_UPDATE}) private Set<Child> children;
в моем случае это было вызвано отсутствием
CascadeTypeна@ManyToOneсторона двунаправленного отношения. Если быть более точным, у меня былоCascadeType.ALLon@OneToManyсбоку и не было его на@ManyToOne. ДобавлениеCascadeType.ALLдо@ManyToOneрешен вопрос. один-ко-многим сторона:@OneToMany(cascade = CascadeType.ALL, mappedBy="globalConfig", orphanRemoval = true) private Set<GlobalConfigScope>gcScopeSet;многие в одну сторону (возникла проблема)
@ManyToOne @JoinColumn(name="global_config_id") private GlobalConfig globalConfig;многие-к-одному (исправлено путем добавления
CascadeType.PERSIST)@ManyToOne(cascade = CascadeType.PERSIST) @JoinColumn(name="global_config_id") private GlobalConfig globalConfig;
Это произошло для меня при сохранении сущности, в которой существующая запись в базе данных имела нулевое значение для поля с аннотацией @Version (для оптимистической блокировки). Обновление значения NULL до 0 в базе данных исправило это.
это не единственная причина ошибок. Я столкнулся с этим только сейчас для ошибки опечатки в моем кодировании, которая, как я считаю, установила значение сущности, которая уже была сохранена.
X x2 = new X(); x.setXid(memberid); // Error happened here - x was a previous global entity I created earlier Y.setX(x2);Я заметил ошибку, найдя точно, какая переменная вызвала ошибку (в этом случае
String xid). Я использовалcatchвокруг всего блока кода, который сохранил сущность и напечатал следы.{ code block that performed the operation } catch (Exception e) { e.printStackTrace(); // put a break-point here and inspect the 'e' return ERROR; }
не используйте
Cascade.Allпока вы действительно не должны.RoleиPermissionдвунаправленнаяmanyToManyотношения. Тогда следующий код будет работать нормальноPermission p = new Permission(); p.setName("help"); Permission p2 = new Permission(); p2.setName("self_info"); p = (Permission)crudRepository.save(p); // returned p has id filled in. p2 = (Permission)crudRepository.save(p2); // so does p2. Role role = new Role(); role.setAvailable(true); role.setDescription("a test role"); role.setRole("admin"); List<Permission> pList = new ArrayList<Permission>(); pList.add(p); pList.add(p2); role.setPermissions(pList); crudRepository.save(role);в то время как если объект просто "новый", то он будет выдавать ту же ошибку.
чтобы добавить мои 2 цента, я получил эту же проблему, когда я случайно отправляю
nullкак идентификатор. Ниже код изображает мой сценарий (и ОП не упомянул какой-либо конкретный сценарий).Employee emp = new Employee(); emp.setDept(new Dept(deptId)); // --> when deptId PKID is null, same error will be thrown // calls to other setters... em.persist(emp);здесь я устанавливаю существующий идентификатор отдела на новый экземпляр сотрудника, фактически не получая сначала объект отдела, так как я не хочу, чтобы другой запрос select срабатывал.
в некоторых случаях
deptIdPKID идет какnullот вызова метода и I m получаю ту же ошибку.Итак, смотрим на
nullзначения для PK ID
Я получаю эту ошибку, когда я использую
getSession().save(object)но он работает без проблем, когда я использую
getSession().saveOrUpdate(object)
помимо всех прочих хороших ответов, это может произойти, если вы используете
mergeчтобы сохранить объект и случайно забыть использовать объединенную ссылку на объект в родительском классе. рассмотрим следующий примерmerge(A); B.setA(A); persist(B);в этом случае, вы сливаетесь
Aно забудьте использовать объединенный объектA. чтобы решить эту проблему, вы должны переписать код следующим образом.A=merge(A);//difference is here B.setA(A); persist(B);
еще одна возможная причина: в моем случае, я пытался спасти ребенка от родителей, на новый объект.
код был что-то вроде этого пользователя.Ява модель:
this.lastName = lastName; this.isAdmin = isAdmin; this.accountStatus = "Active"; this.setNewPassword(password); this.timeJoin = new Date(); create();метод setNewPassword () создает запись PasswordHistory и добавляет ее в коллекцию history в User. Поскольку оператор create () еще не был выполнен для родителя, он пытался сохранить в коллекцию объекта, который еще не был создан. Все, Что Я пришлось сделать, чтобы исправить это, чтобы переместить setNewPassword() вызова после вызова для создания().
this.lastName = lastName; this.isAdmin = isAdmin; this.accountStatus = "Active"; this.timeJoin = new Date(); create(); this.setNewPassword(password);
есть еще одна возможность, которая может вызвать эту ошибку в спящий режим. Вы можете установить несохраненную ссылку на ваш объект
Aк присоединенному объектуBи хотите сохранить объектC. Даже в этом случае, вы получите вышеупомянутую ошибку.
Если вы используете Spring Data JPA, то добавление
@Transactionalаннотация к вашей реализации сервиса решит проблему.
для полноты картины: A
org.hibernate.TransientPropertyValueExceptionС
object references an unsaved transient instance - save the transient instance before flushingтакже произойдет, когда вы попытаетесь сохранить / объединить сущность со ссылкой на другую сущность, которая оказывается отдельно стоящее.
Я тоже столкнулся с такой же ситуацией. Установив следующую аннотацию выше, свойство заставило ее решить запрос на исключение.
исключение, с которым я столкнулся.
Exception in thread "main" java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.model.Car_OneToManyчтобы преодолеть, аннотацию я использовал.
@OneToMany(cascade = {CascadeType.ALL}) @Column(name = "ListOfCarsDrivenByDriver") private List<Car_OneToMany> listOfCarsBeingDriven = new ArrayList<Car_OneToMany>();что заставило Hibernate бросить исключение:
это исключение создается на консоли, потому что дочерний объект, который я прикрепляю к родительскому объекту, в данный момент отсутствует в базе данных.
путем предоставления
@OneToMany(cascade = {CascadeType.ALL}), он сообщает Hibernate, чтобы сохранить их в базе данных при сохранении родительского объекта.
простой способ решения этой проблемы-сохранить оба объекта. сначала сохраните дочернюю сущность, а затем сохраните родительскую сущность. Потому что родительская сущность зависит от дочерней сущности для значения внешнего ключа.
ниже простой экзамен один на один
insert into Department (name, numOfemp, Depno) values (?, ?, ?) Hibernate: insert into Employee (SSN, dep_Depno, firstName, lastName, middleName, empno) values (?, ?, ?, ?, ?, ?) Session session=sf.openSession(); session.beginTransaction(); session.save(dep); session.save(emp);
одной из возможных причин ошибки является отсутствие установки значения родительского объекта ; например, для отношения отдел-сотрудники Вы должны написать это, чтобы исправить ошибку:
Department dept = (Department)session.load(Department.class, dept_code); // dept_code is from the jsp form which you get in the controller with @RequestParam String department employee.setDepartment(dept);
есть так много возможностей этой ошибки некоторые другие возможности также находятся на странице добавления или редактирования. В моем случае я пытался сохранить объект AdvanceSalary. Проблема в том, что в edit сотрудник AdvanceSalary.employee_id имеет значение null, потому что при редактировании я не был установлен сотрудником.идентификатор сотрудника. Я сделал скрытое поле и установил его. мой код работает абсолютно нормально.
@Entity(name = "ic_advance_salary") @Table(name = "ic_advance_salary") public class AdvanceSalary extends BaseDO{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Integer id; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "employee_id", nullable = false) private Employee employee; @Column(name = "employee_id", insertable=false, updatable=false) @NotNull(message="Please enter employee Id") private Long employee_id; @Column(name = "advance_date") @DateTimeFormat(pattern = "dd-MMM-yyyy") @NotNull(message="Please enter advance date") private Date advance_date; @Column(name = "amount") @NotNull(message="Please enter Paid Amount") private Double amount; @Column(name = "cheque_date") @DateTimeFormat(pattern = "dd-MMM-yyyy") private Date cheque_date; @Column(name = "cheque_no") private String cheque_no; @Column(name = "remarks") private String remarks; public AdvanceSalary() { } public AdvanceSalary(Integer advance_salary_id) { this.id = advance_salary_id; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Employee getEmployee() { return employee; } public void setEmployee(Employee employee) { this.employee = employee; } public Long getEmployee_id() { return employee_id; } public void setEmployee_id(Long employee_id) { this.employee_id = employee_id; } }
Я столкнулся с этим исключением, когда я не сохранял родительский объект, но я спасал ребенка. Чтобы решить эту проблему, в том же сеансе я сохранил как дочерние, так и родительские объекты и использовал CascadeType.Все на родителя.
Я думаю, потому что вы пытаетесь сохранить объект, который имеет ссылку на другой объект, который еще не сохраняется, и поэтому он пытается в" стороне БД " поместить ссылку на строку, которая не существует
корпус 1: Я получал это исключение, когда пытался создать родителя и сохранить эту родительскую ссылку на своего ребенка, а затем какой-то другой запрос на удаление/обновление(JPQL). Поэтому я просто смываю () вновь созданный объект после создания родительского и после создания дочернего, используя ту же родительскую ссылку. Это сработало для меня.
Пример 2:
родительский класс
public class Reference implements Serializable { @Id @Column(precision=20, scale=0) private BigInteger id; @Temporal(TemporalType.TIMESTAMP) private Date modifiedOn; @OneToOne(mappedBy="reference") private ReferenceAdditionalDetails refAddDetails; . . . }Дочерний Класс:
public class ReferenceAdditionalDetails implements Serializable{ private static final long serialVersionUID = 1L; @Id @OneToOne @JoinColumn(name="reference",referencedColumnName="id") private Reference reference; private String preferedSector1; private String preferedSector2; . . }В приведенном выше случае, когда родитель(ссылка) и дочерний элемент (ReferenceAdditionalDetails), имеющий отношение OneToOne, и когда вы пытаетесь создать ссылочную сущность, а затем ее дочерний элемент(ReferenceAdditionalDetails), он даст вам то же исключение. Поэтому, чтобы избежать исключения, вы должны установить null для дочернего класса, а затем создать родительский.(Пример Кода)
. . reference.setRefAddDetails(null); reference = referenceDao.create(reference); entityManager.flush(); . .
Comments