0

I want to implement a method for deleting a given user, I have tried so many different ways but it still generates some errors, here are my classes:

    @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;
    }

}

My method I have written so far:

@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;
        }
    }

And here is the exception I got:

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
Tano
  • 1,285
  • 1
  • 18
  • 38
  • Why obtain the user twice? Once with username and once with the id of the already retrieved user? Set the `orphanRemoval` attribute of the `@OneToMany` to `true`. – M. Deinum Jul 05 '16 at 11:22
  • @M.Deinum i tried but still the same error :// – Tano Jul 05 '16 at 11:26
  • Fetch the roles before deleting them – M. Deinum Jul 05 '16 at 11:29
  • @M.Deinum how I can do it, I am just learning now hibernate – Tano Jul 05 '16 at 11:40
  • You have to first remove the user (the one you're going to delete) from the join table that relates _Role_ and _User_. Take a look at this [answer](http://stackoverflow.com/questions/9410252/how-to-delete-the-record-from-the-join-table-in-hibernate). – kazbeel Jul 05 '16 at 11:47
  • I'm saying this by heart but I believe you may use the flag `orphanRemoval=true` in `@OneToMany`. – kazbeel Jul 05 '16 at 11:52

3 Answers3

1

You are getting this error probably because when you are deleteting a user1 that has a role role1 there is anothe user that has a role1.

This happens because of cascade=CascadeType.ALL on getRoles. Try removing that cascade and see if that works.

hashiCode
  • 489
  • 8
  • 17
1

The table user_role is between user and role and has no Entity.

You are using CascadeType.ALL but hibernate ignores the annotation when used with @JoinTable. CascadeType only works together with other Entities, but not by referencing directly to database tables.

See here for more information: JPA CascadeType.REMOVE not working

Generate the entity and map it to the User instead of the JoinTable or delete the user-role mapping from user_role table before removing the user.

Another good option would be to define a casade delete in your database for the user_role join table.

Community
  • 1
  • 1
tak3shi
  • 2,305
  • 1
  • 20
  • 33
0

I really don't want to setup hibernate just to demonstrate this but i see that you are writing a lot of code just to do a simple delete. If your findUserByName() method works fine and returns a valid user, then this should be enough to delete that user from the database, i do it all time.

sessionFactory.getCurrentSession().delete(user);

"user" is an object obtained by calling your findUserByName(name) method and this assumes you already have an instance of SessionFactory.

Update I did not take a look at your stacktrace. Looks like user is been referenced as a foreign key inside some other table and if thats the case you cannot delete that user unless you delete all the fields referencing it.

Stylishcoder
  • 1,142
  • 1
  • 11
  • 21
  • i dont see how thats an answer to the problem – Zulfi Jul 05 '16 at 11:37
  • @Zulfi this should have been in a comment. But if you look at my rep you'll see that i don't enough to comment on anothers post. Just trying to help out. – Stylishcoder Jul 05 '16 at 11:46
  • @imoteb have you tried deleting all roles associated to a user before deleting that user? But theoretically this does not sound like a nice thing but it maybe a solution to your problem. – Stylishcoder Jul 05 '16 at 11:55