I'm having some troubles to make a @ManyToOne association to be loaded lazilly. I'm using the fetch=LAZY but it doesn't work when join isn't made by the primary key column.
I know this question was already asked but I think it wasn't properly answered, so I provide detailed information to clarify the issue.
This is my model:
DummyB -> DummyA
These are the tables:
create table dummyA (
id number(18,0), --pk
name varchar2(20) -- unique field
);
create table dummyB (
id number(18,0),
dummya_id number(18,0),
dummya_name varchar2(20)
);
And these are the entities:
@Entity
public class DummyA implements Serializable {
private Long id;
private String name;
@Id
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Entity
public class DummyB implements Serializable {
private Long id;
private DummyA dummyA;
@Id
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/* Case 1: mapping DummyB -> DummyA by DummyA NON primary key (field name) */
// @ManyToOne(fetch = FetchType.LAZY)
// @JoinColumn(name = "dummya_id")
// public DummyA getDummyA() {
// return dummyA;
// }
/* Case 2: mapping DummyB -> DummyA by DummyA primary key */
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "dummya_name", referencedColumnName = "name")
@LazyToOne(LazyToOneOption.PROXY)
public DummyA getDummyA() {
return dummyA;
}
public void setDummyA(DummyA dummyA) {
this.dummyA = dummyA;
}
}
Note getDummyA method in entity DummyB is duplicate to try out two cases to join the entities.
Case 1: mapping DummyB -> DummyA by DummyA primary key
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "dummya_id")
This works fine, just one query is executed to retrieve DummyB objects.
Case 2: mapping DummyB -> DummyA by DummyA NON primary key (field name)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "dummya_name", referencedColumnName="name")
Same dummyB select is execute, but right after, a dummyA select is executed filtering by name=? to fetch the related A object.
I'm using a really simple jUnit to execute filtering:
public class DummyTest {
@Autowired
HibernateTransactionManager transactionManager;
@Test
@Transactional
public void testFindDummyB() throws DAOException {
Long idDummyB = 2L;
Session session = getCurrentHibernateSession();
List lst = session.createCriteria(DummyB.class)
.add(Restrictions.eq("id", idDummyB)).list();
assertTrue(lst.size() > 0);
}
private Session getCurrentHibernateSession() {
return this.transactionManager.getSessionFactory().getCurrentSession();
}
}
My libraries:
- org.hibernate:hibernate-core:jar:4.2.17.Final:compile
- org.hibernate.common:hibernate-commons-annotations:jar:4.0.2.Final:compile
- org.hibernate.javax.persistence:hibernate-jpa-2.0-api:jar:1.0.1.Final:compile
- org.hibernate:hibernate-validator:jar:4.3.2.Final:provided
Other things I've already tried:
Adding hiberante's @LazyToOne to getDummyA() method doesn't have any effect.
@LazyToOne(LazyToOneOption.PROXY)
@ManyToOne(fetch = FetchType.LAZY, optional = true)
@JoinColumn(name = "dummya_name", referencedColumnName = "name")
@LazyToOne(LazyToOneOption.PROXY)
Creating a foreign key from DummyB table to dummyA (and an unique constraint in dummya.name field) has no effect.
- Adding @Column(unique = true) on DummyA getName() method didn't make it.
- Set optional=true or false as suggested here has no effect either.
Trying to force the lazy loading using the setFetchMode in the criteria didn't work, DummyA select keeps executing.
List lst = session.createCriteria(DummyB.class) .add(Restrictions.eq("id", idDummyB)).setFetchMode("dummyA", FetchMode.SELECT) .list();
I can't find in Hibernate's docs a point where it refers to this behaviour, so I wonder if there's anything is wrong in my annotations or I came upon a Hibernate bug.
Can anyone tell?
UPDATED by md-dev request:
To set it more clear:
Is this the expected behaviour or is a bug? if this the expected behaviour, where is it documented?
Thank you.
See Question&Answers more detail:
os