I am getting an error from one of my test cases. The test case involves a user attempting to delete an Address of a User that they don't have permission to. What is odd is that hibernate seems to be attempting to save the user object which I have not altered.
I am not sure what I have done wrong and would appreciate some insight.
Test case (note: Seam code in use):
Code:
@Test(dependsOnMethods = "ownerCreate")
public void ownerDelete() throws Exception
{
new ComponentTest()
{
protected void testComponents() throws Exception
{
loginUser(InitialUser.USER);
getEntityManager().getTransaction().begin();
User user = (User)getValue("#{user}");
for (Address addr : user.getAddresses())
{
if (!addr.isPrimary())
{
assert "54321".equals(addr.getPostalCode());
getEntityManager().remove(addr);
break;
}
}
getEntityManager().getTransaction().commit();
}
}.run();
}
Here is the error:
Code:
FAILED: ownerDelete
javax.persistence.RollbackException: Error while commiting the transaction
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:71)
at com.christws.entities.AddressTest$7.testComponents(AddressTest.java:211)
at org.jboss.seam.mock.BaseSeamTest$ComponentTest.run(BaseSeamTest.java:167)
at com.christws.entities.AddressTest.ownerDelete(AddressTest.java:213)
Caused by: org.hibernate.ObjectDeletedException: deleted entity passed to persist: [com.christws.entities.Address#<null>]
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:90)
at org.hibernate.impl.SessionImpl.firePersistOnFlush(SessionImpl.java:644)
at org.hibernate.impl.SessionImpl.persistOnFlush(SessionImpl.java:636)
at org.hibernate.engine.CascadingAction$9.cascade(CascadingAction.java:323)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:216)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:296)
at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:242)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:219)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
at org.hibernate.event.def.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:131)
at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:122)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:65)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:54)
... 25 more
... Removed 22 stack frames
Here are the fields from Address:
Code:
@Entity
@Table(name="user_address")
@SequenceGenerator(name="seq", sequenceName="user_address_seq")
@Restrict
public class Address
extends BaseEntity
{
private final static long serialVersionUID = 1l;
@ManyToOne
@NotNull(message="{valid.address.user.notnull}")
@JoinColumn(name="user_id")
private User user;
@Basic
@NotNull(message="{valid.address.location.notnull}")
@Length(max=50, message="{valid.address.location.length}")
private String location;
@Basic
@NotNull(message="{valid.address.street.notnull}")
@Length(max=2000, message="{valid.address.street.length}")
private String street;
@Basic
@NotNull(message="{valid.address.city.notnull}")
@Length(max=250,message="{valid.address.city.length}")
private String city;
@Basic
@NotNull(message="{valid.address.region.notnull}")
@Length(max=100,message="{valid.address.region.length}")
private String region;
@Basic
@Column(name="postal_code")
@NotNull(message="{valid.address.postalcode.notnull}")
@Length(max=100,message="{valid.address.postalcode.length}")
private String postalCode;
@Basic
@NotNull(message="{valid.address.country.notnull}")
@Length(max=100,message="{valid.address.country.length}")
private String country;
@Basic
@Column(name = "`primary`")
private boolean primary;
@OneToMany(mappedBy = "address")
@OnDelete(action = OnDeleteAction.CASCADE)
@Cascade( { CascadeType.ALL, CascadeType.DELETE_ORPHAN })
private Set<AddressPermission> permissions;
...
Here are some of the user fields:
Code:
@Entity
@Table(name = "site_user")
@SequenceGenerator(name = "seq", sequenceName = "site_user_seq")
@Roles({ @org.jboss.seam.annotations.Role(name = "user", scope = ScopeType.SESSION ) })
public class User
extends BaseEntity
{
private final static long serialVersionUID = 1l;
// Fields
@Basic
@NotNull(message = "{valid.user.username.notnull}")
@Length(min = 4, max = 250, message = "{valid.user.username.length}")
private String username;
@Basic
@Column(name = "password")
@Length(max = 32)
private String passwordHash;
@Basic
@Column(name = "first_name")
@Length(max = 15, message = "{valid.user.firstname.length}")
@NotNull(message = "{valid.user.firstname.notnull}")
private String firstName;
@Basic
@Column(name = "last_name")
@Length(max = 25, message = "{valid.user.lastname.length}")
@NotNull(message = "{valid.user.lastname.notnull}")
private String lastName;
@Basic
@Column(name = "time_zone")
private TimeZone timeZone;
@Basic
private Locale locale;
@ManyToMany
@JoinTable(name = "user_role_j", joinColumns = { @JoinColumn(name = "user_id", nullable = false) }, inverseJoinColumns = { @JoinColumn(name = "role_id", nullable = false) })
@Cascade( { CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.SAVE_UPDATE })
private Set<Role> roles;
@OneToMany(mappedBy = "user")
@OnDelete(action = OnDeleteAction.CASCADE)
@Cascade( { CascadeType.ALL, CascadeType.DELETE_ORPHAN })
private List<Address> addresses;
...
Here is BaseEntity:
Code:
@AccessType("field")
@MappedSuperclass
public abstract class BaseEntity
implements Serializable, Comparable<BaseEntity>, IdentifiedEntity
{
@Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq")
private Long id;
@Basic
@Column(name="created_dt", updatable = false)
private Timestamp created;
@Basic
@Version
@Column(name="modified_dt")
private Timestamp modified;
...
Why is hibernate trying to save the User object when I haven't made changes to it? What must I do to stop hibernate from updating every object in memory?
I think there must be something wrong with my mapping, but I am not sure what. Any help would be appeciated.
Hibernate versions: hibernate-3.2.4.sp1.jar
hibernate-annotations-3.3.0.ga.jar
hibernate-commons-annotations-3.0.0.ga.jar
hibernate-entitymanager-3.3.1.ga.jar
hibernate-validator-3.0.0.GA.jar
persistence-api-1.0.jar
Name and version of the database you are using:postgresql-8.2-504.jdbc4.jar
The generated SQL (show_sql=true):Code:
Hibernate: select user0_.id as id20_, user0_.created_dt as created2_20_, user0_.modified_dt as modified3_20_, user0_.first_name as first4_20_, user0_.last_name as last5_20_, user0_.locale as locale20_, user0_.password as password20_, user0_.time_zone as time8_20_, user0_.username as username20_ from christwstest.christwstest.site_user user0_ where user0_.username=? and user0_.password=?
Hibernate: select roles0_.user_id as user1_1_, roles0_.role_id as role2_1_, role1_.id as id6_0_, role1_.created_dt as created2_6_0_, role1_.modified_dt as modified3_6_0_, role1_.comments as comments6_0_, role1_.hidden as hidden6_0_, role1_.name as name6_0_ from christwstest.christwstest.user_role_j roles0_ left outer join christwstest.christwstest.role role1_ on roles0_.role_id=role1_.id where roles0_.user_id=?
Hibernate: select addresses0_.user_id as user12_1_, addresses0_.id as id1_, addresses0_.id as id14_0_, addresses0_.created_dt as created2_14_0_, addresses0_.modified_dt as modified3_14_0_, addresses0_.comments as comments14_0_, addresses0_.city as city14_0_, addresses0_.country as country14_0_, addresses0_.location as location14_0_, addresses0_.postal_code as postal8_14_0_, addresses0_."primary" as primary9_14_0_, addresses0_.region as region14_0_, addresses0_.street as street14_0_, addresses0_.user_id as user12_14_0_ from christwstest.christwstest.user_address addresses0_ where addresses0_.user_id=?
Hibernate: select permission0_.address_id as address6_2_, permission0_.id as id2_, permission0_.id as id19_1_, permission0_.created_dt as created2_19_1_, permission0_.modified_dt as modified3_19_1_, permission0_.access_type as access4_19_1_, permission0_.role_id as role5_19_1_, permission0_.address_id as address6_19_1_, role1_.id as id6_0_, role1_.created_dt as created2_6_0_, role1_.modified_dt as modified3_6_0_, role1_.comments as comments6_0_, role1_.hidden as hidden6_0_, role1_.name as name6_0_ from christwstest.christwstest.user_address_role permission0_ inner join christwstest.christwstest.role role1_ on permission0_.role_id=role1_.id where permission0_.address_id=?
Hibernate: select permission0_.address_id as address6_2_, permission0_.id as id2_, permission0_.id as id19_1_, permission0_.created_dt as created2_19_1_, permission0_.modified_dt as modified3_19_1_, permission0_.access_type as access4_19_1_, permission0_.role_id as role5_19_1_, permission0_.address_id as address6_19_1_, role1_.id as id6_0_, role1_.created_dt as created2_6_0_, role1_.modified_dt as modified3_6_0_, role1_.comments as comments6_0_, role1_.hidden as hidden6_0_, role1_.name as name6_0_ from christwstest.christwstest.user_address_role permission0_ inner join christwstest.christwstest.role role1_ on permission0_.role_id=role1_.id where permission0_.address_id=?
Thanks,
Andrew