简体   繁体   中英

Hibernate @ManyToOne do not update table

I have 2 entities - User and Role with mapping @ManyToOne . I want to change role in user, but Role want's to be updated too.

User entity:

@ManyToOne
@JoinColumn(name = "role_id", insertable =  false, updatable = false)
private Role role;

role entity:

@OneToMany(mappedBy = "role")
private Set<User> users;

The error I get is:

java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance beforeQuery flushing: com.spring.model.Role at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:144) at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155) at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:162) at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1434)

My tables in DB are not set with CASCADE UPDATE or INSERT. I wasn't able to find appropriate solution. Thanks for your help

EDIT:

This is how I update User

public void update(User user) {
        User entity = dao.findById(user.getId());
        if(entity!=null) {
            entity.setRole(user.getRole());
        }
    }

EDIT2:

My hibernate configuration

@Configuration
@EnableTransactionManagement
@ComponentScan({ "com.spring.configuration" })
@PropertySource(value = { "classpath:application.properties" })
public class HibernateConfiguration {

    @Autowired
    private Environment environment;

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setPackagesToScan(new String[] { "com.spring.model" });
        sessionFactory.setHibernateProperties(hibernateProperties());
        return sessionFactory;
     }

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
        dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
        dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
        dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
        return dataSource;
    }

    private Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
        properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
        properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
        return properties;        
    }

    @Bean
    @Autowired
    public HibernateTransactionManager transactionManager(SessionFactory s) {
       HibernateTransactionManager txManager = new HibernateTransactionManager();
       txManager.setSessionFactory(s);
       return txManager;
    }
}

You should use the cascade attribute of the OneToMany annotation, it does not have any relationship with the database cascade operations (but can be affected by that).

@OneToMany(cascade = CascadeType.ALL, mappedBy="role", orphanRemoval = true)
private Set<User> users;

This way the operation will be propagated to the collection elements. You can check this answer for more info.

You can also modify the cascade property of the ManyToOne annotation.

@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "role_id")
private Role role;

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