对象引用了一个未保存的瞬时实例 - 在刷新之前保存瞬时实例:com.entity.Role。

3

我在使用hibernate相关依赖项尝试向表中插入一些值时,出现了对象引用未保存的瞬态实例 - 在刷新之前保存瞬态实例:com.entity.Role异常。

pom.xml中相关的依赖关系如下:

<!-- Hibernate -->
    <dependency>
        <groupId>org.hsqldb</groupId>
        <artifactId>hsqldb</artifactId>
        <version>2.3.2</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>4.3.4.Final</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-jpa</artifactId>
        <version>1.8.1.RELEASE</version>
    </dependency>

Role.java 是

@Entity
public class Role {
@Id
@GeneratedValue
private Integer id = 0;

private String name = null;

@ManyToMany
@JoinTable
private List<User> users = null;

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public List<User> getUsers() {
    return users;
}

public void setUsers(List<User> users) {
    this.users = users;
} }

User.java is

@Entity
public class User {

@Id
@GeneratedValue
private Integer id = 0;

private String name = null;
private String email = null;
private String password = null;

@ManyToMany
private List<Role> roles = null;

@OneToMany(mappedBy="user")
private List<Blog> blogs = null;

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getEmail() {
    return email;
}

public void setEmail(String email) {
    this.email = email;
}

public String getPassword() {
    return password;
}

public void setPassword(String password) {
    this.password = password;
}

public List<Role> getRoles() {
    return roles;
}

public void setRoles(List<Role> roles) {
    this.roles = roles;
}

public List<Blog> getBlogs() {
    return blogs;
}

public void setBlogs(List<Blog> blogs) {
    this.blogs = blogs;
}}

我正在使用视频 这里提到的 仓库,
它与IT技术有关。

import org.springframework.data.jpa.repository.JpaRepository;

import com.entity.Role;

public interface RoleRepository extends JpaRepository<Role, Integer> {

}

并且。
import org.springframework.data.jpa.repository.JpaRepository;

import com.entity.User;

public interface UserRepository extends JpaRepository<User, Integer> {

}

而 InitDbService.java 是

@Transactional
@Service
public class InitDbService {

    @Autowired
    private BlogRepository blogRepository = null;

    @Autowired
    private ItemRepository itemRepository = null;

    @Autowired
    private RoleRepository roleRepository = null;

    @Autowired
    private UserRepository userRepository = null;

    @PostConstruct
    private void init() {
        Role roleUser = new Role();
        roleUser.setName("ROLE_USER");
        roleRepository.save(roleUser);

        Role roleAdmin = new Role();
        roleAdmin.setName("ROLE_ADMIN");
        roleRepository.save(roleAdmin);

        User userAdmin = new User();
        userAdmin.setName("admin");

        List<Role> roles = new ArrayList<Role>();       
        roles.add(roleAdmin);
        roles.add(roleUser);

        userAdmin.setRoles(roles);
        userRepository.save(userAdmin);

        //Test insert in to DB
        Blog javaBlog = new Blog();
        javaBlog.setName("Java Blog");
        javaBlog.setUrl("http://security.stackexchange.com/");
        javaBlog.setUser(userAdmin);
        blogRepository.save(javaBlog);

        Item item1 = new Item();
        item1.setTitle("Java Blog");
        item1.setBlog(javaBlog);
        item1.setLink("http://security.stackexchange.com/");
        item1.setPublishedDate(new Date());
        itemRepository.save(item1);


        Item item2 = new Item();
        item2.setTitle("Java Blog two");
        item2.setBlog(javaBlog);
        item2.setLink("http://security.stackexchange.com/");
        item2.setPublishedDate(new Date());
        itemRepository.save(item2);
    }

}

我看过这个SO答案,但仍然在控制台输出中看到这个错误信息:

INFO: Initializing Spring root WebApplicationContext
Hibernate: alter table Blog drop constraint FK_thdkoy0q7vcgc5hay9wb99vnh
Hibernate: alter table Item drop constraint FK_il3204s0mf6d1m8am8f5768ah
Hibernate: alter table Role_User drop constraint FK_iha4m965rutefhrl4f2pvko39
Hibernate: alter table Role_User drop constraint FK_1rtsbyk364hixsho0345aj4sd
Hibernate: alter table User_Role drop constraint FK_tc5k40i3kit8944syrd366vy1
Hibernate: alter table User_Role drop constraint FK_dv4w2xni693cg4ibi3fo1fkk6
Hibernate: drop table Blog if exists
Hibernate: drop table Item if exists
Hibernate: drop table Role if exists
Hibernate: drop table Role_User if exists
Hibernate: drop table User if exists
Hibernate: drop table User_Role if exists
Hibernate: create table Blog (id integer generated by default as identity (start with 1), name varchar(255), url varchar(255), user_id integer, primary key (id))
Hibernate: create table Item (id integer generated by default as identity (start with 1), description varchar(255), link varchar(255), published_date timestamp, title varchar(255), blog_id integer, primary key (id))
Hibernate: create table Role (id integer generated by default as identity (start with 1), name varchar(255), primary key (id))
Hibernate: create table Role_User (Role_id integer not null, users_id integer not null)
Hibernate: create table User (id integer generated by default as identity (start with 1), email varchar(255), name varchar(255), password varchar(255), primary key (id))
Hibernate: create table User_Role (User_id integer not null, roles_id integer not null)
Hibernate: alter table Blog add constraint FK_thdkoy0q7vcgc5hay9wb99vnh foreign key (user_id) references User
Hibernate: alter table Item add constraint FK_il3204s0mf6d1m8am8f5768ah foreign key (blog_id) references Blog
Hibernate: alter table Role_User add constraint FK_iha4m965rutefhrl4f2pvko39 foreign key (users_id) references User
Hibernate: alter table Role_User add constraint FK_1rtsbyk364hixsho0345aj4sd foreign key (Role_id) references Role
Hibernate: alter table User_Role add constraint FK_tc5k40i3kit8944syrd366vy1 foreign key (roles_id) references Role
Hibernate: alter table User_Role add constraint FK_dv4w2xni693cg4ibi3fo1fkk6 foreign key (User_id) references User
Hibernate: insert into Role (id, name) values (default, ?)
Hibernate: insert into Role (id, name) values (default, ?)
Hibernate: insert into User (id, email, name, password) values (default, ?, ?, ?)
Hibernate: insert into User_Role (User_id, roles_id) values (?, ?)
Jul 9, 2015 3:29:43 PM org.apache.catalina.core.StandardContext listenerStart
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'initDbService': Invocation of init method failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.entity.Role; nested exception is java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.entity.Role
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:136)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:408)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1566)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:5014)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5528)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1575)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1565)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
    at java.util.concurrent.FutureTask.run(FutureTask.java:166)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:717)
Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.entity.Role; nested exception is java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.entity.Role
    at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:378)
    at org.springframework.orm.jpa.DefaultJpaDialect.translateExceptionIfPossible(DefaultJpaDialect.java:122)
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:521)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:478)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:272)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke(CrudMethodMetadataPostProcessor.java:122)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at $Proxy34.save(Unknown Source)
    at com.service.InitDbService.init(InitDbService.java:56)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:613)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:349)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:300)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:133)
    ... 24 more
Caused by: java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.entity.Role
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1760)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677)
    at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:82)
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517)
    ... 46 more
Caused by: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.entity.Role
    at org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:294)
    at org.hibernate.type.EntityType.getIdentifier(EntityType.java:537)
    at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:165)
    at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:899)
    at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1308)
    at org.hibernate.action.internal.CollectionRecreateAction.execute(CollectionRecreateAction.java:67)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:461)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:347)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1222)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425)
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
    at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:77)
    ... 47 more

有没有更好的解决方案呢?针对这个问题。
2个回答

2
您可能需要在类似于@Entity的类中进行更改,例如以下内容
@Entity
public class Role {
@Id
@GeneratedValue
private Integer id = 0;

private String name = null;

@ManyToMany(cascade = {CascadeType.ALL}) 
@JoinTable
private List<User> users = null;

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public List<User> getUsers() {
    return users;
}

public void setUsers(List<User> users) {
    this.users = users;
} }

User.java

@Entity
public class User {

@Id
@GeneratedValue
private Integer id = 0;

private String name = null;
private String email = null;
private String password = null;

@ManyToMany(cascade = {CascadeType.ALL})
private List<Role> roles = null;

@OneToMany(mappedBy="user")
private List<Blog> blogs = null;

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getEmail() {
    return email;
}

public void setEmail(String email) {
    this.email = email;
}

public String getPassword() {
    return password;
}

public void setPassword(String password) {
    this.password = password;
}

public List<Role> getRoles() {
    return roles;
}

public void setRoles(List<Role> roles) {
    this.roles = roles;
}

public List<Blog> getBlogs() {
    return blogs;
}

public void setBlogs(List<Blog> blogs) {
    this.blogs = blogs;
}}

如上所述,可以参考这里。它可能解决你的问题!试一下并告诉我是否有任何问题或成功。


1
有一些关于这个话题的帖子,大多数指向 CASCADE = ALL 作为答案。但对我来说没有用,我只是偶尔会收到错误报告。我开始怀疑级联操作不起作用,然后偶然发现了这篇 article,它指向了 spring.jpa.open-in-view=true,从而引导我找到了这篇 article
所以,我把 open-in-view 设置为 false,然后得到了一堆 LazyInitializationException 错误,这就引导我找到了这篇 article。为了快速解决 LazyInitializationExceptions,我将 FETCH 设置为 EAGER,看看是否有效……结果有效了。我想。因为这个错误总是偶尔出现,很难确定。
我正在调查情况,但是想提出这个问题,以防有人对设置级联的标准答案感到困惑。
我的实体模型非常标准,一个父实体对应多个子实体。
@Entity
@Table(name="TRIP", schema="HIKES")
public class Trip implements Serializable {
...
    @OneToMany(mappedBy = "trip", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
    private List<EquipListItem> equipmentList;
...

我调用的方法导致了未保存的瞬态实例异常,该方法在父级上运行,并会创建一个新的子级实例并将其添加到集合中。
public void addEquipment(int wanted, final GearItem item) {
    if(null == equipmentList) {
        // Create list.
        equipmentList = new ArrayList<EquipListItem>();
    }
    equipmentList.add(new EquipListItem(this, item, wanted));
}

有时它工作,有时它不工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接