-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: JPA 2 weird behaviour when Mapping basic Collections
PostPosted: Wed Jul 13, 2011 8:44 am 
Newbie

Joined: Wed Jul 13, 2011 8:15 am
Posts: 2
My situation is the following:

I am mapping a simple one-to-many relationship I have done many times before successfully without too much thought. However yesterday after starting anew project and downloading the latest hibernate jars I experienced some strange behaviour when using JPA Annotations to map a one-to-many.

In a nutshell, the code works fine if the Annotation is placed at field level as opposed to the placing it above the getter, but fails if its placed on the getter...unless I explicitly declare the collection field implementation type rather than use the interface, e.g. HashSet instead of Set. My question is why cant I place the annotation above the getter and use an interface eg Set reference instead of a concrete implementation like HashSet as I have always done??

I can resolve the problem by either:

1) Placing all annotations at field level
2) Use the class implementation for collection/set type field references rather than the interface i.e. HashSet instead of Set, ArrayList instead of List and carry on placing the annotation above the getter.

But why is it a problem in the first place???

Here is the parent side:

@Entity
@Table(name="TEST")
public class Test extends BaseEntityImpl {

private String name;

private Set<TestMany> testManys = new HashSet<TestMany>(0);

public String getName() {
return name;
}


@OneToMany(targetEntity=TestMany.class,
cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@JoinColumn(name="TESTID")

public Set<TestMany> getTestManys() {
return testManys;
}

public void setTestManys(Set<TestMany> testManys) {
this.testManys = testManys;
}
}

Here is the many side.

@SuppressWarnings("serial")
@Entity
@Table(name="TESTMANY")
public class TestMany extends BaseEntityImpl{

private Test test;

private String manyPeople;


@ManyToOne
@JoinColumn(name="TESTID", insertable=false, updatable=false)
public Test getTest() {
return test;
}

@Column(name="MANYPEOPLE")
public String getManyPeople() {
return manyPeople;
}

public void setManyPeople(String manyPeople) {
this.manyPeople = manyPeople;
}

public void setTest(Test test) {
this.test = test;
}
}

Both classes extend the generic base class which doesnt do much but provide an ID.

@MappedSuperclass
public abstract class BaseEntityImpl implements BaseEntity, Serializable {

private static final long serialVersionUID = 7887314289537012320L;

@Id @GeneratedValue(strategy = AUTO)
@Column(name = "ID")
private Long id;

public Long getId() {
return id;
}

@SuppressWarnings("unused")
private void setId(Long id) {
this.id = id;
}
}

Now from the above code the following doesnt work from the Test class:

private Set<TestMany> testManys = new HashSet<TestMany>(0);

@OneToMany(targetEntity=TestMany.class,
cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@JoinColumn(name="TESTID")

public Set<TestMany> getTestManys() {
return testManys;
}

But this does work when placing the annotation above the field:


@OneToMany(targetEntity=TestMany.class,
cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@JoinColumn(name="TESTID")
private Set<TestMany> testManys = new HashSet<TestMany>(0);


And so does this - changing the Set to HashSet and leaving the annotation on the getter:

// here now a HashSet and it works ok, I can place the annotation on the getter.
private HashSet<TestMany> testManys = new HashSet<TestMany>(0);

@OneToMany(targetEntity=TestMany.class,
cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@JoinColumn(name="TESTID")

public Set<TestMany> getTestManys() {
return testManys;
}

The error I get without doing one of the two methods above is:

Stack Trace:
Caused by: org.hibernate.MappingException: Could not determine type for: java.util.Set, at table: TEST, for columns: [org.hibernate.mapping.Column(testManys)]
at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:306)
at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:290)
at org.hibernate.mapping.Property.isValid(Property.java:217)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:464)
at org.hibernate.mapping.RootClass.validate(RootClass.java:235)
at org.hibernate.cfg.Configuration.validate(Configuration.java:1335)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1838)
at org.springframework.orm.hibernate3.LocalSessionFactoryBean.newSessionFactory(LocalSessionFactoryBean.java:860)
at org.springframework.orm.hibernate3.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:779)
at org.springframework.orm.hibernate3.AbstractSessionFactoryBean.afterPropertiesSet(AbstractSessionFactoryBean.java:211)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417)
... 47 more

My pom:

<properties>
<hibernate.version>3.5.3-Final</hibernate.version>
</properties>

<!-- hibernate dependencies -->
<dependencies>

<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.6.3.Final</version>
</dependency>

<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
</dependency>

<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.6.3.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-commons-annotations</artifactId>
<version>3.2.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>1.1.1.Final</version>
</dependency>
</dependencies>

Please can someone explain I think its something very basic I'm missing???


Top
 Profile  
 
 Post subject: Re: JPA 2 weird behaviour when Mapping basic Collections
PostPosted: Wed Jul 13, 2011 7:40 pm 
Newbie

Joined: Wed Jul 13, 2011 8:15 am
Posts: 2
The Hibernate docs state:

Quote:
Depending on whether you annotate fields or methods, the access type used by Hibernate will be field or property. The EJB3 spec requires that you declare annotations on the element type that will be accessed, i.e. the getter method if you use property access, the field if you use field access. Mixing annotations in both fields and methods should be avoided. Hibernate will guess the access type from the position of @Id or @EmbeddedId.


So thats where I screwed up. I had the @Id annotation for the field in BaseEntity not on the getter. Cant believe 3 hours of my life..............


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.