简体   繁体   中英

“object references an unsaved transient instance - save the transient instance before flushing” Caused no INSERT

UserRole.java:

@Entity
@Table(name="user_role")
public class UserRole implements Serializable {
private static final long serialVersionUID = 890345L;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long userRoleId;

public UserRole () {}

public UserRole (User user, Role role) {
    this.user = user;
    this.role = role;
}

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "user_id")
private User user;

@ManyToOne(fetch = FetchType.EAGER)
private Role role;

public long getUserRoleId() {
    return userRoleId;
}

Role.java:

 @Entity
 public class Role implements Serializable{

private static final long serialVersionUID = 890245234L;

@Id
private int roleId;

private String name;

@OneToMany(mappedBy = "role", cascade = CascadeType.ALL)
private Set<UserRole> userRoles = new HashSet<>();

public Role(){}

public int getRoleId() {
    return roleId;
}

UserServiceImpl.java:

@Service
public class UserServiceImpl implements UserService{

private static final Logger LOG = LoggerFactory.getLogger(UserService.class);

@Autowired
private UserRepository userRepository;

@Autowired
private RoleRepository roleRepository;

@Transactional
public User createUser(User user, Set<UserRole> userRoles) {
    User localUser = userRepository.findByUsername(user.getUsername());

    if(localUser != null) {
        LOG.info("User with username {} already exist. Nothing will be done. ", user.getUsername());
    } else {
        for (UserRole ur : userRoles) {

                           //too slow here
            roleRepository.save(ur.getRole());
        }
        user.getUserRoles().addAll(userRoles);

        localUser = userRepository.save(user);
    }

    return localUser;
}

}

Working hardcode:

@Override
    public void run(String... args) throws Exception {
        User user1 = new User();
        user1.setFirstName("John");
        user1.setLastName("Adams");
        user1.setUsername("j");
        user1.setPassword(SecurityUtility.passwordEncoder().encode("p"));
        user1.setEmail("JAdams@gmail.com");
        Set<UserRole> userRoles = new HashSet<>();
        Role role1 = new Role();
        role1.setRoleId(1);
        role1.setName("ROLE_USER");
//here it save the role data
        roleRepository.save(role1);
        userRoles.add(new UserRole(user1, role1));
        user1.setUserRoles(userRoles);
        userRepository.save(user1);

Exception Track:

    2018-10-02 16:08:51.251  INFO 19624 --- [           main] com.example.demo.ServerApplication       : Started ServerApplication in 2.161 seconds (JVM running for 2.526)
2018-10-02 16:08:51.521  INFO 19624 --- [           main] o.h.h.i.QueryTranslatorFactoryInitiator  : HHH000397: Using ASTQueryTranslatorFactory
Hibernate: select user0_.id as id1_1_, user0_.email as email2_1_, user0_.enabled as enabled3_1_, user0_.first_name as first_na4_1_, user0_.last_name as last_nam5_1_, user0_.password as password6_1_, user0_.phone as phone7_1_, user0_.username as username8_1_ from user user0_ where user0_.username=?
Hibernate: select role0_.role_id as role_id1_0_1_, role0_.name as name2_0_1_, userroles1_.role_role_id as role_rol2_2_3_, userroles1_.user_role_id as user_rol1_2_3_, userroles1_.user_role_id as user_rol1_2_0_, userroles1_.role_role_id as role_rol2_2_0_, userroles1_.user_id as user_id3_2_0_ from role role0_ left outer join user_role userroles1_ on role0_.role_id=userroles1_.role_role_id where role0_.role_id=?
Hibernate: select next_val as id_val from hibernate_sequence for update
2018-10-02 16:08:51.594 ERROR 19624 --- [           main] o.hibernate.id.enhanced.TableStructure   : could not read a hi value - you need to populate the table: hibernate_sequence
2018-10-02 16:08:51.607  INFO 19624 --- [           main] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2018-10-02 16:08:51.611 ERROR 19624 --- [           main] o.s.boot.SpringApplication               : Application run failed

java.lang.IllegalStateException: Failed to execute CommandLineRunner
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:821) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:802) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:341) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1277) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1265) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
    at com.example.demo.ServerApplication.main(ServerApplication.java:32) [classes/:na]
Caused by: org.springframework.orm.jpa.JpaSystemException: could not read a hi value - you need to populate the table: hibernate_sequence; nested exception is org.hibernate.id.IdentifierGenerationException: could not read a hi value - you need to populate the table: hibernate_sequence
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:312) ~[spring-orm-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:223) ~[spring-orm-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:527) ~[spring-orm-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61) ~[spring-tx-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242) ~[spring-tx-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153) ~[spring-tx-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135) ~[spring-data-jpa-2.0.10.RELEASE.jar:2.0.10.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at com.sun.proxy.$Proxy87.save(Unknown Source) ~[na:na]
    at com.example.demo.Service.Impl.UserServiceImpl.createUser(UserServiceImpl.java:40) ~[classes/:na]
    at com.example.demo.Service.Impl.UserServiceImpl$$FastClassBySpringCGLIB$$a970b40f.invoke(<generated>) ~[classes/:na]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294) ~[spring-tx-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at com.example.demo.Service.Impl.UserServiceImpl$$EnhancerBySpringCGLIB$$7f8e6119.createUser(<generated>) ~[classes/:na]
    at com.example.demo.ServerApplication.run(ServerApplication.java:49) [classes/:na]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:818) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
    ... 5 common frames omitted
Caused by: org.hibernate.id.IdentifierGenerationException: could not read a hi value - you need to populate the table: hibernate_sequence
    at org.hibernate.id.enhanced.TableStructure$1$1.execute(TableStructure.java:142) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.id.enhanced.TableStructure$1$1.execute(TableStructure.java:126) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.jdbc.WorkExecutor.executeReturningWork(WorkExecutor.java:55) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.jdbc.AbstractReturningWork.accept(AbstractReturningWork.java:34) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:57) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.id.enhanced.TableStructure$1.getNextValue(TableStructure.java:125) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.id.enhanced.NoopOptimizer.generate(NoopOptimizer.java:40) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.id.enhanced.SequenceStyleGenerator.generate(SequenceStyleGenerator.java:452) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:105) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:67) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:189) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:132) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:783) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:768) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:305) ~[spring-orm-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at com.sun.proxy.$Proxy85.persist(Unknown Source) ~[na:na]
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:490) ~[spring-data-jpa-2.0.10.RELEASE.jar:2.0.10.RELEASE]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
    at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:377) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:200) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:641) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:605) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:590) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294) ~[spring-tx-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    ... 26 common frames omitted

**Hibernate: select user0_.id as id1_1_, user0_.email as email2_1_, user0_.enabled as enabled3_1_, user0_.first_name as first_na4_1_, user0_.last_name as last_nam5_1_, user0_.password as password6_1_, user0_.phone as phone7_1_, user0_.username as username8_1_ from user user0_ where user0_.username=?

Hibernate: select role0_.role_id as role_id1_0_1_, role0_.name as name2_0_1_, userroles1_.role_role_id as role_rol2_2_3_, userroles1_.user_role_id as user_rol1_2_3_, userroles1_.user_role_id as user_rol1_2_0_, userroles1_.role_role_id as role_rol2_2_0_, userroles1_.user_id as user_id3_2_0_ from role role0_ left outer join user_role userroles1_ on role0_.role_id=userroles1_.role_role_id where role0_.role_id=?

Hibernate: select next_val as id_val from hibernate_sequence for update**

I found the reason why this exception happen is that when user need to be saved, Role hasn't finish save.

I add the data by hard code with roleRepository and userRepository directly and it works.

I want to know how to let user save after role finish save.

If you are not maintaining any sequence in database, then Use @GeneratedValue(strategy = javax.persistence.GenerationType.IDENTITY ) It will automatically maintain a unique Identification for your table.

For User Role Entity use below:

@Entity
@Table(name="user_role")
public class UserRole implements Serializable {
private static final long serialVersionUID = 890345L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long userRoleId;

You can use cascade All on UserRole entity for many to one mapping of role and you can do the same in your user entity. you don't have to call roleRepository and userRepository then you just have to call userRepository and set values for user role in user and role in userRole.

Also for your error, you have to add Generation type as Auto on @Id in Role entity.

@Entity
@Table(name="user_role")
public class UserRole implements Serializable {
private static final long serialVersionUID = 890345L;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long userRoleId;

public UserRole () {}

public UserRole (User user, Role role) {
    this.user = user;
    this.role = role;
}

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "user_id")
private User user;

@ManyToOne(fetch = FetchType.EAGER,cascade = CascadeType.ALL)
private Role role;

public long getUserRoleId() {
    return userRoleId;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM