Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Hibernate:ошибка cannot simultaneously fetch multiple bags / 8 сообщений из 8, страница 1 из 1
14.07.2012, 15:20
    #37879268
faceless
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate:ошибка cannot simultaneously fetch multiple bags
Здравствуйте! Я пишу программу, где используется Hibernate. У меня есть пять персистентных классов, реализующих таблицы:

1) Это класс Post (Список Должностей)
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;

@Entity
public class Post {
	@Id
	@GeneratedValue
	@Column(name="post_id")
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	
	@Column(name="post_name")
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	@OneToMany(targetEntity=EmployeeHistory.class,mappedBy="post",
			cascade=CascadeType.ALL,fetch=FetchType.EAGER)
	public List<EmployeeHistory> getEmployeeHistories() {
		return employeeHistories;
	}
	public void setEmployeeHistories(List<EmployeeHistory> employeeHistories) {
		this.employeeHistories = employeeHistories;
	}
	
	private int id;
	private String name;
	List<EmployeeHistory> employeeHistories;
}



2) Класс Person (Список людей)
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;

@Entity
public class Person {
	
	@Id
	@GeneratedValue
	@Column(name="person_id")
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	@Column(name="person_name")
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	@Column(name="person_lost_name")
	public String getLostName() {
		return lostName;
	}
	public void setLostName(String lostName) {
		this.lostName = lostName;
	}
	public String getPatronym() {
		return patronym;
	}
	public void setPatronym(String patronym) {
		this.patronym = patronym;
	}
	
	@OneToMany(targetEntity=EmployeeHistory.class,mappedBy="person",
			cascade=CascadeType.ALL,fetch=FetchType.EAGER)
	public List<EmployeeHistory> getEmployeeHistories() {
		return employeeHistories;
	}

	public void setEmployeeHistories(List<EmployeeHistory> employeeHistories) {
		this.employeeHistories = employeeHistories;
	}


	private int id;       //первичный ключ
	private String name,  //имя 
	 	   lostName,  //фамилия
	 	   patronym; //отчество
	
	List<EmployeeHistory> employeeHistories;
}



3) Класс Division (список подразделений компании)
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;

@Entity
public class Division {
	
	@Id
	@GeneratedValue
	@Column(name="div_id")
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	
	@Column(name="div_name")
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	@OneToMany(targetEntity=DivHistory.class,mappedBy="division",
			cascade=CascadeType.ALL,fetch=FetchType.EAGER)
	public List<EmployeeHistory> getEmployeeHistories() {
		return employeeHistories;
	}
	public void setEmployeeHistories(List<EmployeeHistory> employeeHistories) {
		this.employeeHistories = employeeHistories;
	}
	
	@OneToMany(targetEntity=DivHistory.class,mappedBy="division",
			cascade=CascadeType.ALL,fetch=FetchType.EAGER)
	public List<DivHistory> getDivHistories() {
		return divHistories;
	}
	public void setDivHistories(List<DivHistory> divHistories) {
		this.divHistories = divHistories;
	}

	private int id;      //певичный ключ
	private String name; //имя
	
	List<EmployeeHistory> employeeHistories; //записи о работниках
	List<DivHistory> divHistories;  //записи о подразделениях
}



4) В классе EmployeeHistory хранится информация о том, когда (какого числа) какой сотрудник получил такую-то должность или когда перешёл в такое-то подразделение. Иными словами, записывает все изменения связанные с сотрудниками.
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name="employee_history")
public class EmployeeHistory {
	
	@Id
	@GeneratedValue
	@Column(name="emp_history_id")
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	
	@Column(name="emp_date")
	public Date getDate() {
		return date;
	}
	public void setDate(Date date) {
		this.date = date;
	}
	
	@ManyToOne
	@JoinColumn(name="person_id")
	public Person getPerson() {
		return person;
	}
	public void setPerson(Person person) {
		this.person = person;
	}
	
	@ManyToOne
	@JoinColumn(name="post_id")
	public Post getPost() {
		return post;
	}
	public void setPost(Post post) {
		this.post = post;
	}
	
	@ManyToOne
	@JoinColumn(name="div_id")
	public Division getDivision() {
		return division;
	}
	public void setDivision(Division division) {
		this.division = division;
	}
	
	private int id;//emp_change_id
	Date date;//div_date
	
	private Person person;
	private Post post;
	private Division division;	
}



5) В классе DivHistory хранится когда подразделение id стало входить в подразделение fathId (father id)
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name="div_hisory")
public class DivHistory {

	@Id
	@GeneratedValue
	@Column(name="div_change_id")
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	@Column(name="father_div_id")
	public int getFathId() {
		return fathId;
	}

	public void setFathId(int fathId) {
		this.fathId = fathId;
	}

	@Column(name="div_date")
	public Date getDate() {
		return date;
	}

	public void setDate(Date date) {
		this.date = date;
	}
	
	@ManyToOne
	@JoinColumn(name="div_id")
	public Division getDivision() {
		return division;
	}
	
	public void setDivision(Division division) {
		this.division = division;
	}
	

	private int id,//div_change_id
			fathId;//father_div_id
	Date date;//div_date
	Division division;

}



И есть ещё класс DBManager, управляющий всем этим.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;

public class DBManager {

	public DBManager() {
		config=new Configuration();
		config.addAnnotatedClass(DivHistory.class);
		config.addAnnotatedClass(Division.class);
		config.addAnnotatedClass(EmployeeHistory.class);
		config.addAnnotatedClass(Person.class);
		config.addAnnotatedClass(Post.class);
		
		config.configure(constConfig);
		//new SchemaExport(config).create(true, true);
		
//		SessionFactory factory=config.buildSessionFactory();
//		session=factory.getCurrentSession();
	}
	
	public Session getCurrentSession()
	{
		SessionFactory factory=config.buildSessionFactory();
		return factory.getCurrentSession();
	}
	
	public void init()
	{
		new SchemaExport(config).create(true, true);
	}
	
	public void addPerson(Person person,Post post,Division division) 
	{
		Session session=this.getCurrentSession();
		session.beginTransaction();//начало транзакции
		
		EmployeeHistory eh=new EmployeeHistory();
		
		eh.setPerson(person);
		eh.setPost(post);
		eh.setDivision(division);
		
		session.save(eh);
		session.save(person);
		session.getTransaction().commit();
	}
	
	public void addEmployee(String name,String surname, String patronym,
			String post, String division) 
	{
		
	}
	
	public void addDivision(Division division, int fathId)
	{
		Session session=this.getCurrentSession();
		session.beginTransaction();//начало транзакции
		
		DivHistory dh=new DivHistory();
		
		dh.setDivision(division);
		dh.setFathId(fathId);
		
		session.save(dh);
		session.save(division);
		
		session.getTransaction().commit();
	}
	
	public void addPost(Post post)
	{
		Session session=this.getCurrentSession();
		session.beginTransaction();//начало транзакции
		
		session.save(post);
		
		session.getTransaction().commit();
	}
	
	public static void main(String[] args) 
	{
		DBManager manager=new DBManager();
		manager.init();
		Post post=new Post();
		post.setName("Administrator");
		manager.addPost(post);
//		Division div=new Division();
//		manager.addDivision(div, 13);
//		Person person=new Person();
//		person.setName("Nikolay");
//		person.setLostName("Stavrogin");
//		person.setPatronym("Vselodovich");
//		manager.addPerson(person, post, div);
	}
	
	Configuration config;
	private final static String constConfig="hibernate.cfg.xml";
}


Все действия описаны в методе main() класса DBManager.

Все таблицы благополучно создаются, код конструктора класса и метод init() работаю без ошибок. Но при попытке добавить новую запись возникает ошибка " cannot simultaneously fetch multiple bags ".
Трассировка ошибки, выглядит следующим образом:
Exception in thread "main" org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags
at org.hibernate.loader.BasicLoader.postInstantiate(BasicLoader.java:94)
at org.hibernate.loader.entity.EntityLoader.<init>(EntityLoader.java:119)
at org.hibernate.loader.entity.EntityLoader.<init>(EntityLoader.java:71)
at org.hibernate.loader.entity.EntityLoader.<init>(EntityLoader.java:54)
at org.hibernate.loader.entity.BatchingEntityLoader.createBatchingEntityLoader(BatchingEntityLoader.java:133)
at org.hibernate.persister.entity.AbstractEntityPersister.createEntityLoader(AbstractEntityPersister.java:1914)
at org.hibernate.persister.entity.AbstractEntityPersister.createEntityLoader(AbstractEntityPersister.java:1937)
at org.hibernate.persister.entity.AbstractEntityPersister.createLoaders(AbstractEntityPersister.java:3206)
at org.hibernate.persister.entity.AbstractEntityPersister.postInstantiate(AbstractEntityPersister.java:3192)
at org.hibernate.persister.entity.SingleTableEntityPersister.postInstantiate(SingleTableEntityPersister.java:728)
at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:348)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1872)
at com.java.summwork.dbwork.DBManager.getCurrentSession(DBManager.java:27)
at com.java.summwork.dbwork.DBManager.addPost(DBManager.java:76)
at com.java.summwork.dbwork.DBManager.main(DBManager.java:90)


У меня есть подозрения, что это связано с моими попытками маппинга @OneToMany в классе EmployeeHistory, но может это и не так.

В чём может быть эта ошибка? Есть ли способ её как-дибо разрешить?
...
Рейтинг: 0 / 0
16.07.2012, 03:03
    #37880119
ivanov-void
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate:ошибка cannot simultaneously fetch multiple bags
faceless,

Прогнал ваш пример из любопытства, запись благополучно добавилась-

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
...
	public static void main(String[] args) 
	{
		DBManager manager=new DBManager();
		manager.init();
		Post post=new Post();
		post.setName("Administrator");
		manager.addPost(post);
               getNames();
...



Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
...
public static void getNames() {
	List list;
		
	Session session = getCurrentSession();
	session.beginTransaction();
		
	try {
		list = session.createQuery(
		   "from Post").list();
		session.getTransaction().commit();
	}
	catch (HibernateException e) {
		session.getTransaction().rollback();
                session.close();
		throw e;
	}
		
	for(Iterator<List> iterator = list.iterator(); iterator.hasNext(); ) 
		System.out.println(((Post)iterator.next()).getName());	        
}
...



Попробуйте включить автоматическое управление контекстами сеанса -
Код: xml
1.
2.
3.
...
<property name="hibernate.current_session_context_class">thread</property>
...
...
Рейтинг: 0 / 0
16.07.2012, 10:29
    #37880257
svenom
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate:ошибка cannot simultaneously fetch multiple bags
Проблема вызвана тем, что у вас в классе Division несколько OneToMany c типом EAGER. Так делать нельзя, так как при этом Хибер будет пытаться вытащить одним запросом две коллекции, которые не связаны между собой, то есть по сути получится картезиан в терминах реляционной алгебры.
Сделайте одну из заивисимостей LAZY.
...
Рейтинг: 0 / 0
16.07.2012, 10:37
    #37880273
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate:ошибка cannot simultaneously fetch multiple bags
Проблема в том что у одного бина две One-To-Many ассоциации с FetchType.EAGER. Так как указные ассоциации не используют никаких колонок для упорядочивания, то Хибер использует для них тип Bag - неупорядоченая коллеция. А так как дефолтная реализация для EAGER это Join, то Хибер пытается сущность и обе ассоциации вычитать одним джоином. И вот тут возникает путаница. Если вы такой джоин разложите, и посмотрите на результат, то по нему нельзя однозначно определить какие FK значения какой ассоциации принадлежат.

Вариантов исправить - масса. Вообще использовать FetchType.EAGER прямо в маппинге чревато. Тем более для One-To-Many, это просто дополнительная нагрузка, на уровень работы с БД, которая далеко не всегда нужна. Варианты исправления
заменить JOIN Fetch на SELECT, как бы, результат тот же что и с FetchType.LAZY
помеять тип One-To-Many с Bag, на List. Для этого нужно указать ещё и колонку, которую можно использовать как индекс для списка.
...
Рейтинг: 0 / 0
05.04.2013, 22:58
    #38215200
alexander00513
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate:ошибка cannot simultaneously fetch multiple bags
помеять тип One-To-Many с Bag, на List.

А как это сделать, и что это за параметры ? Если можно в 2х словах...
...
Рейтинг: 0 / 0
05.04.2013, 23:31
    #38215210
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate:ошибка cannot simultaneously fetch multiple bags
...
Рейтинг: 0 / 0
24.03.2014, 12:31
    #38594395
aleXVoipp
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate:ошибка cannot simultaneously fetch multiple bags
Blazkowicz,

А почему одним джоином?
Пишут, что двумя.Но все равно не понятно, какие проблемы с получением значений
...
Рейтинг: 0 / 0
24.03.2014, 12:42
    #38594416
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate:ошибка cannot simultaneously fetch multiple bags
aleXVoippА почему одним джоином?

Что почему? Сконцентрируйтесь и сформулируйте полный вопрос.

aleXVoippПишут, что двумя.
Пусть пишут.

aleXVoippНо все равно не понятно, какие проблемы с получением значений
Нарисуйте несколько таблиц с двумя отношениями OneToMany в одной из них. Забейте данными. Напишите JOIN запрос на все таблицы.
Посмотрите на результат и расскажите как узнать какие колонки к какой ассоциации относятся.
Особо ленивые могут гуглить по тексту ошибки, я находил пару статей где на примерах с данными рассказывается в чем проблема разобрать результат запроса в отдельные объекты.
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Hibernate:ошибка cannot simultaneously fetch multiple bags / 8 сообщений из 8, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]