【问题标题】:Hibernate deleting user休眠删除用户
【发布时间】:2016-07-05 11:20:03
【问题描述】:

我想实现一个删除给定用户的方法,我尝试了很多不同的方法,但仍然会产生一些错误,这是我的类:

    @Entity
    @Table(name = "roles", catalog = "demo", uniqueConstraints = @UniqueConstraint(columnNames = { "name" }) )
    public class Role {

        private String name;

        public Role() {
        }

        public Role(final String name) {
            this.name = name;
        }

        @Id
        @Column(name = "name", nullable = false, length = 50)
        public String getRole() {
            return this.name;
        }

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

    }

@Entity
@Table(name="users", catalog="demo")
public class User {

    private String username;
    private String password;
    private boolean enabled;
    private Set<Role> roles;

    @Id
    @Column(unique=true, nullable=false)
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Column(nullable=false)
    public String getPassword() {
        return password;
    }

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

    @Column(nullable=false)
    public boolean isEnabled(){
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    @OneToMany(cascade=CascadeType.ALL)
    @JoinTable(name="user_role", catalog="demo",
                joinColumns = @JoinColumn(name = "user_id"),
                inverseJoinColumns = @JoinColumn(name = "role_id"))
    public Set<Role> getRoles() {
        return roles;
    }

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

}

我目前写的方法:

@Override
    public boolean deleteUser(final String username, String password){
        User user = findByUserName(username);
        if(user != null){
            Serializable id = new String(username);
            Object persistentInstance = sessionFactory.getCurrentSession().get(User.class, id); 
            if (persistentInstance != null) {
                sessionFactory.getCurrentSession().delete(persistentInstance);
            }
            return true;
        }else{
        return false;
        }
    }

这是我得到的例外:

org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [FK_AUTHORITY_ROLE]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
    at org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:163)
    at org.springframework.orm.hibernate4.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:730)
    at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:592)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
    at org.springframework.test.context.transaction.TransactionContext.endTransaction(TransactionContext.java:128)
    at org.springframework.test.context.transaction.TransactionalTestExecutionListener.afterTestMethod(TransactionalTestExecutionListener.java:224)
    at org.springframework.test.context.TestContextManager.afterTestMethod(TestContextManager.java:313)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:94)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:254)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
    at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:72)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:211)
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:62)
    at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3400)
    at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3630)
    at org.hibernate.action.internal.EntityDeleteAction.execute(EntityDeleteAction.java:114)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:465)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:351)
    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:1258)
    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.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:584)
    ... 25 more
Caused by: java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: foreign key no action; FK_AUTHORITY_ROLE table: USER_ROLE
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
    at org.hsqldb.jdbc.JDBCPreparedStatement.fetchResult(Unknown Source)
    at org.hsqldb.jdbc.JDBCPreparedStatement.executeUpdate(Unknown Source)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:208)
    ... 38 more
Caused by: org.hsqldb.HsqlException: integrity constraint violation: foreign key no action; FK_AUTHORITY_ROLE table: USER_ROLE
    at org.hsqldb.error.Error.error(Unknown Source)
    at org.hsqldb.StatementDML.performReferentialActions(Unknown Source)
    at org.hsqldb.StatementDML.delete(Unknown Source)
    at org.hsqldb.StatementDML.executeDeleteStatement(Unknown Source)
    at org.hsqldb.StatementDML.getResult(Unknown Source)
    at org.hsqldb.StatementDMQL.execute(Unknown Source)
    at org.hsqldb.Session.executeCompiledStatement(Unknown Source)
    at org.hsqldb.Session.execute(Unknown Source)
    ... 41 more

【问题讨论】:

  • 为什么要两次获取用户?一次使用用户名,一次使用已检索用户的 id?将@OneToManyorphanRemoval属性设置为true
  • @M.Deinum 我试过但仍然是同样的错误://
  • 在删除角色之前获取角色
  • @M.Deinum 我该怎么做,我现在正在学习休眠
  • 您必须首先从关联 RoleUser 的联接表中删除用户(您要删除的用户)。看看这个answer

标签: java spring hibernate


【解决方案1】:

user_role 表在用户和角色之间,没有实体。

您正在使用 CascadeType.ALL,但当与 @JoinTable 一起使用时,hibernate 会忽略注释。 CascadeType 只能与其他实体一起使用,而不是直接引用数据库表。

更多信息请看这里:JPA CascadeType.REMOVE not working

生成实体并将其映射到用户而不是 JoinTable,或者在删除用户之前从 user_role 表中删除用户角色映射。

另一个不错的选择是在数据库中为 user_role 连接表定义级联删除。

【讨论】:

    【解决方案2】:

    我真的不想设置休眠只是为了演示这一点,但我看到您编写了大量代码只是为了进行简单的删除。如果您的 findUserByName() 方法工作正常并返回一个有效用户,那么这应该足以从数据库中删除该用户,我一直这样做。

    sessionFactory.getCurrentSession().delete(user);
    

    "user" 是一个通过调用你的 findUserByName(name) 方法获得的对象,它假设你已经有一个 SessionFactory 的实例。

    更新 我没有看你的堆栈跟踪。看起来用户在其他表中被引用为外键,如果是这种情况,除非您删除所有引用它的字段,否则您无法删除该用户。

    【讨论】:

    • 我不明白这是如何解决问题的
    • @Zulfi 这应该在评论中。但是,如果您查看我的代表,您会发现我不足以评论其他帖子。只是想帮忙。
    • @imoteb 您是否尝试在删除该用户之前删除与该用户关联的所有角色?但从理论上讲,这听起来不是一件好事,但它可能会解决您的问题。
    【解决方案3】:

    您收到此错误可能是因为当您删除具有角色 role1user1 时,另一个用户具有 role1 .

    这是因为cascade=CascadeType.ALL 上的getRoles。尝试移除该级联,看看是否有效。

    【讨论】:

    • 栈是一样的吗?
    • 在你的模型中,一个用户可以有多个角色?这个角色可以关联多个用户吗?
    • @hashiCode 用户不映射到角色,而是使用带有 user_id 和 role_id 的 JoinColumn 映射到用户角色表。所以你的解决方案将不起作用。
    • @tak3shi 这很奇怪。我的项目中有一些非常相似的东西(单向多对多),这对我有用。
    • @imoteb 你用的是什么版本的hsqldb?
    猜你喜欢
    • 2013-05-25
    • 2011-02-16
    • 2012-02-07
    • 2010-11-03
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多