Имею две энтити: Train и Seat. У них есть реляция one-to-many:
UML
Train.java:
@Entity
@Table(name = "train")
public class Train {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "name")
private String name;
// Проблема с реляцией!!!
@OneToMany(mappedBy = "train", cascade = CascadeType.ALL)
private Set<Seat> seats;
@OneToOne
private State state;
@Column(name = "carriages")
private Integer carriages;
// Getters & Setters...
}
Seat.java:
@Entity
@Table(name = "seat")
public class Seat {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "carriage")
private Integer carriage;
@Column(name = "seat")
private Integer seat;
// Реляция с поездом
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "train_id", nullable = false)
private Train train;
// Getters & Setters...
}
Как можно заметить, связка тут bi-directional:
@OneToMany(mappedBy = "train", cascade = CascadeType.ALL)
private Set<Seat> seats;
И
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "train_id", nullable = false)
private Train train;
Собственно говоря, у меня произошла ошибка в бизнес-логике на уровне сервиса, когда я вытаскиваю из расписания JPA Train. Причём, проблемы начинаются лишь тогда, когда я вытаскиваю из поезда список сидений (Seat). В моём Spring MVC приложении вылетает такая ошибка:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.slandshow.models.Train.seats, could not initialize proxy - no Session
Затем, когда я понял первоисточник проблемы, решил дебажить в мейне эти два энтити.
С помощью SessionFactory я решил вытащить из БД поезд под конкретным айдишником записи и посмотреть:
session.beginTransaction();
Train train = session.get(Train.class, 5l); // Вытаскиваю поезд из базы
System.out.println(train); // Причина ошибки вылезает в переопределённом методе toString
session.getTransaction().commit();
Так как у меня toString переопределён, то я хватаю вот такой стек-трейс:
ERROR 2018-09-21 19:42:44,671 [main] org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl - Connection leak detected: there are 1 unclosed connections upon shutting down pool jdbc:mysql://localhost:3306/RattlerStation
Exception in thread "main" java.lang.StackOverflowError
at java.lang.Long.toString(Long.java:396)
at java.lang.Long.toString(Long.java:1032)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at java.util.AbstractCollection.toString(AbstractCollection.java:462)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:303)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Train.toString(Train.java:74)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.slandshow.models.Seat.toString(Seat.java:72)
at java.lang.String.valueOf(String.java:2994)
Когда я просто вывожу другие поля Train'а - то всё ок, проблему Connection leak detected: there are 1 unclosed connections upon shutting down pool jdbc:mysql://localhost:3306/RattlerStation
вызывает именно train.getSeats();
Вот мой Hibernate конфи, просто вдруг дело в нём
@Configuration
@EnableTransactionManagement
@ComponentScan({"com.slandshow"})
@PropertySource(value = {"classpath:application.properties"})
public class HibernateConfig {
private static final String MODEL_PACKAGE = "com.slandshow.models";
private static final String JDBC_DRIVER_CLASS_NAME_PROPERTY = "jdbc.driverClassName";
private static final String JDBC_URL_PROPERTY = "jdbc.url";
private static final String HIBERNATE_DIALECT_PROPERTY = "hibernate.dialect";
private static final String HIBERNATE_SHOW_SQL_PROPERTY = "hibernate.show_sql";
private static final String HIBERNATE_FORMAT_SQL_PROPERTY = "hibernate.format_sql";
@Autowired
private Environment environment;
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(MODEL_PACKAGE);
sessionFactory.setHibernateProperties(hibernateProperties());
Properties property = new Properties();
property.put("hibernate.id.new_generator_mappings", "false");
sessionFactory.setHibernateProperties(property);
return sessionFactory;
}
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty(JDBC_DRIVER_CLASS_NAME_PROPERTY));
dataSource.setUrl(environment.getRequiredProperty(JDBC_URL_PROPERTY));
dataSource.setUsername("root");
dataSource.setPassword("12345");
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put(HIBERNATE_DIALECT_PROPERTY, environment.getRequiredProperty(HIBERNATE_DIALECT_PROPERTY));
properties.put(HIBERNATE_SHOW_SQL_PROPERTY, environment.getRequiredProperty(HIBERNATE_SHOW_SQL_PROPERTY));
properties.put(HIBERNATE_FORMAT_SQL_PROPERTY, environment.getRequiredProperty(HIBERNATE_FORMAT_SQL_PROPERTY));
return properties;
}
@Bean
@Autowired
public HibernateTransactionManager transactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
Что же я сделал не так?
toString() плохо переопределен и зацикливается переходя по ссылкам.
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
поможет, если нужно вызывать getSeats() когда сессия уже не доступна
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Задумал реализовать клиент-серверное приложение на Android с применением архитектуры MVPТакже добавить транспортный слой в приложения, который...
Имеется вот такой шаблончик https://codepenio/psyapathy/pen/wENPgX
Не работает следующий код в IE11, а так же если повесить событие через onclickПри этом в chrome работает