Hi,
since the version 3.6.4 a bug in hibernate was fixed (which is a good thing) but the fix now breaks my application (which is bad) and i have no
clue how i am supposed to do what i would like to do :(
The fix which breaks my application is:
http://opensource.atlassian.com/project ... e/HHH-2049My situation:
I have a 1:n relation... lets call it Bean with many ChildBeans. I would like to get a list with Beans and preload the associated ChildBeans with
ONE select clause. I attached a working (actually not working as i would like it) example code to my post.
My problem:
It seams not to be possible to do this using one select clause as the Beans are multiplied by the count of their ChildBeans. In my example code
i get bean1 and bean2 two times as both of them have two childbeans. Of course this is not what i want. In the past i applied a filter to the
ChildBeans which assured that each Bean has just one ChildBean (that was ok for the logic of the application). But this workaround doesn't
work anymore with the fix applied to 3.6.4 as it leaves the collection uninitialized and causes many additional select statements on access.
I already tried the DistinctRootEntityResultTransformer which actually does what i would like (one Bean with multiple ChildBeans) but the
implementation of the Transformer makes paging using setMaxResults impossible.
Preferred solution:
My preferred solution would actually be to add a filter to the ChildBeans again but initialize the collection with the result. Yes i know that
the state of the object does not reflect the state from the database correctly but this is the only way to keep things working. I think not
filtering the collection would break other things (as sorting or paging) too.
How i am supposed to solve my problem using Hibernate 3.6.4?
Please help me.
Yours
Thomas
My code:
Code:
CREATE TABLE IF NOT EXISTS `beans` (
`id` int(11) NOT NULL,
`value` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `beans` (`id`, `value`) VALUES
(1, 'bean1'),
(2, 'bean2');
CREATE TABLE IF NOT EXISTS `childbeans` (
`id` int(11) NOT NULL,
`fkbeans` int(11) NOT NULL,
`value` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `childbeans` (`id`, `fkbeans`, `value`) VALUES
(1, 1, 'childbean1'),
(2, 1, 'childbean2'),
(3, 2, 'childbean3'),
(4, 2, 'childbean4');
Code:
package de.test;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
@Entity
@Table(name = "beans")
public class Bean {
@Id
@Column(name = "id", nullable = false)
private Integer id;
@Column(name = "value", nullable = false, length = 20)
private String value;
@OneToMany(mappedBy = "bean")
@Cascade(value = { CascadeType.ALL })
private Set<ChildBean> childbeans;
public Bean() {
this.childbeans = new HashSet<ChildBean>();
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getValue() {
return value;
}
public Set<ChildBean> getChildbeans() {
return childbeans;
}
public void setChildbeans(Set<ChildBean> childbeans) {
this.childbeans = childbeans;
}
}
Code:
package de.test;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name = "childbeans")
public class ChildBean {
@Id
@Column(name = "id", nullable = false)
private Integer id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "fkbeans", updatable = false, nullable = false)
private Bean bean;
@Column(name = "value", nullable = false, length = 20)
private String value;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Bean getBean() {
return bean;
}
public void setBean(Bean bean) {
this.bean = bean;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
Code:
package de.test;
import java.util.List;
import org.hibernate.FetchMode;
import org.hibernate.Session;
public class Main {
public static void main(String[] args) throws Exception {
Session session = Hibernate.getSessionFactory().getCurrentSession();
session.beginTransaction();
List<Bean> beans = (List<Bean>) session.createCriteria(Bean.class)
.setFetchMode("childbeans", FetchMode.JOIN)
.list();
for (Bean bean : beans) {
System.out.println(bean.getValue() + ": " + bean.getChildbeans().size());
}
session.getTransaction().commit();
}
}
Output:
Code:
bean1: 2
bean1: 2
bean2: 2
bean2: 2