I am probably missing something here but here we go.
I have 2 classes, User and Authority, mapped using annotations. A User has a List of authorities(OneToMany relationship).
The thing is, when I remove a item from the list(say, using ListIterator) and issue session.update(user), the delete is not cascaded. It tries to null out the username field on the authorities table instead of deleting the record.
Here are the classes:
User.java
Code:
@Entity
@Table(name="users")
public class User {
private String username;
private String password;
private String fullname;
private Boolean enabled;
private List<Authority> authorities = new ArrayList<Authority>();
@Id
@Column(length=50, name="username", nullable=false)
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Column(length=64, name="password", nullable=false)
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Column(length=100, name="fullname", nullable=false)
public String getFullname() {
return fullname;
}
public void setFullname(String fullname) {
this.fullname = fullname;
}
public Boolean getEnabled() {
return enabled;
}
@Column(name="enabled", nullable=false)
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
@JoinColumn(name="username")
@Cascade({org.hibernate.annotations.CascadeType.ALL})
public List<Authority> getAuthorities() {
return authorities;
}
public void setAuthorities(List<Authority> authorities) {
this.authorities = authorities;
}
}
Authority.javaCode:
@Entity
@IdClass(AuthorityPK.class)
@Table(name="authorities")
public class Authority {
private String username;
private String authority;
@Id
@Column(length=50, name="username", nullable=false)
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Id
@Column(length=50, name="authority", nullable=false)
public String getAuthority() {
return authority;
}
public void setAuthority(String authority) {
this.authority = authority;
}
@Override
public boolean equals(Object obj) {
if (obj != null &&
((Authority)obj).getUsername().equals(this.getUsername()) &&
((Authority)obj).getAuthority().equals(this.getAuthority())) {
return true;
}
return false;
}
}
Other info:
Hibernate version: 3.2
Full stack trace of any exception that occurs(the first 3 lines are the last SQL commands issued by Hiberntae):
2007-08-05 13:28:13,255 WARN [org.hibernate.util.JDBCExceptionReporter] - <SQL Error: 0, SQLState: 01004>
2007-08-05 13:28:13,255 ERROR [org.hibernate.util.JDBCExceptionReporter] - <Data truncation: Column was set to data type implicit default; NULL supplied for NOT NULL column 'username' at row 1>
2007-08-05 13:28:13,260 ERROR [org.hibernate.event.def.AbstractFlushingEventListener] - <Could not synchronize database state with session>
org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:253)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:237)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:144)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.springframework.orm.hibernate3.HibernateAccessor.flushIfNecessary(HibernateAccessor.java:390)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:373)
at org.springframework.orm.hibernate3.HibernateTemplate.update(HibernateTemplate.java:654)
at org.springframework.orm.hibernate3.HibernateTemplate.update(HibernateTemplate.java:650)
at org.bugHunt.security.dao.UserDaoImpl.update(UserDaoImpl.java:53)
at org.bugHunt.security.service.UserServiceImpl.update(UserServiceImpl.java:37)
at org.bugHunt.security.web.controllers.ManageUserController.doEdit(ManageUserController.java:74)
at org.bugHunt.web.controllers.base.BaseSimpleManagerController.onSubmit(BaseSimpleManagerController.java:89)
at org.springframework.web.servlet.mvc.SimpleFormController.processFormSubmission(SimpleFormController.java:267)
at org.springframework.web.servlet.mvc.CancellableFormController.processFormSubmission(CancellableFormController.java:140)
at org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:250)
at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:857)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:792)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:475)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:440)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:265)
at org.acegisecurity.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:107)
at org.acegisecurity.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:72)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.ui.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:110)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:81)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:229)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.ui.logout.LogoutFilter.doFilter(LogoutFilter.java:106)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:286)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:149)
at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:210)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:174)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:151)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:870)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:685)
at java.lang.Thread.run(Thread.java:595)
Caused by: java.sql.BatchUpdateException: Data truncation: Column was set to data type implicit default; NULL supplied for NOT NULL column 'username' at row 1
at com.mysql.jdbc.ServerPreparedStatement.executeBatch(ServerPreparedStatement.java:647)
at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:294)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246)
Name and version of the database you are using: MySQL 5
The generated SQL (show_sql=true):
Hibernate: select user0_.username as username3_, user0_.password as password3_, user0_.fullname as fullname3_, user0_.enabled as enabled3_ from users user0_ where user0_.username='nana'
Hibernate: select authoritie0_.username as username1_, authoritie0_.authority as authority1_, authoritie0_.authority as authority4_0_, authoritie0_.username as username4_0_ from authorities authoritie0_ where authoritie0_.username=?
Hibernate: select user0_.username as username3_, user0_.password as password3_, user0_.fullname as fullname3_, user0_.enabled as enabled3_ from users user0_ where user0_.username='nana'
Hibernate: select authoritie0_.username as username1_, authoritie0_.authority as authority1_, authoritie0_.authority as authority4_0_, authoritie0_.username as username4_0_ from authorities authoritie0_ where authoritie0_.username=?
Hibernate: select authority_.authority, authority_.username from authorities authority_ where authority_.authority=? and authority_.username=?
Hibernate: update users set password=?, fullname=?, enabled=? where username=?
Hibernate: update authorities set username=null where username=? and authority=? and username=?
Thanks