2016-02-15 6 views
2

Недавно я обновил приложение Spring Boot от Hibernate 4 до Hibernate 5. С тех пор я наблюдаю проблему загрузки класса. Очевидно, что классы hibernate и мой класс домена загружаются двумя разными загрузчиками классов. Это происходит только в том случае, если я запускаю приложение с Spring DevTools и Hibernate 5. Комбинации DevTools/Hibernate 4, mvn spring-boot: run/Hibernate 5 работают.Ошибка загрузки класса с помощью Spring Boot и Hibernate 5

Проблема может быть воспроизведена с помощью следующего простого приложения весной загрузок (полный проект затмения доступен here)

@Entity 
public class Employee implements Serializable { 
    private static final long serialVersionUID = 1L; 

    private Long  id; 
    private String firstName; 
    private String lastName; 

    public Employee() { 
    } 

    public Employee(String firstName, String lastName) { 
     this.firstName = firstName; 
     this.lastName = lastName; 
    } 

    @Id @GeneratedValue 
    public Long getId() { 
     return id; 
    } 

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

    public String getFirstName() { 
     return firstName; 
    } 

    public void setFirstName(String firstName) { 
     this.firstName = firstName; 
    } 

    public String getLastName() { 
     return lastName; 
    } 

    public void setLastName(String lastName) { 
     this.lastName = lastName; 
    } 

    public String toString() { 
     return id + ": " + lastName + ", " + firstName; 
    } 
} 

public class AppConfig { 

    @Autowired 
    private DataSource dataSource; 

    @SuppressWarnings("serial") 
    @Bean 
    public LocalSessionFactoryBean sessionFactory() { 

     LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); 
     sessionFactory.setDataSource(dataSource); 
     sessionFactory.setPackagesToScan("problem.domain"); 
     sessionFactory.setHibernateProperties(new Properties() { 
      { 
       setProperty("hibernate.dialect", "org.hibernate.dialect.DerbyTenSevenDialect"); 
       setProperty("hibernate.hbm2ddl.auto", "create-drop"); 
       setProperty("hibernate.current_session_context_class", "thread"); 
      } 
     }); 

     return sessionFactory; 
    } 
} 

@Component 
public class DatabaseInitializer implements ApplicationRunner { 

    @Autowired 
    private SessionFactory sessionFactory; 

    @Override 
    public void run(ApplicationArguments args) throws Exception { 

     Session session = sessionFactory.getCurrentSession(); 
     Transaction tx = session.beginTransaction(); 
     Employee empl = new Employee("John", "Doe"); 
     session.persist(empl); 
     tx.commit(); 
    } 
} 

@SpringBootApplication 
public class SpringBootMain { 

    public static void main(String[] args) throws Exception { 
     SpringApplication.run(SpringBootMain.class, args); 
    } 
} 

pom.xml: 
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 

    <groupId>swt6.spring</groupId> 
    <artifactId>hibernate5-problem</artifactId> 
    <packaging>jar</packaging> 
    <version>1.0.0-SNAPSHOT</version> 

    <parent> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-parent</artifactId> 
     <version>1.3.2.RELEASE</version> 
     <relativePath /> <!-- lookup parent from repository --> 
    </parent> 

    <properties> 
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
     <java.version>1.8</java.version> 
     <hibernate.version>5.1.0.Final</hibernate.version> 
     <derby.version>10.12.1.1</derby.version> 
    </properties> 

    <dependencies> 
     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-data-jpa</artifactId> 
     </dependency> 

     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-devtools</artifactId> 
     </dependency> 

     <dependency> 
      <groupId>org.apache.derby</groupId> 
      <artifactId>derby</artifactId> 
     </dependency> 

    </dependencies> 

    <build> 
     <plugins> 
      <plugin> 
       <groupId>org.springframework.boot</groupId> 
       <artifactId>spring-boot-maven-plugin</artifactId> 
      </plugin> 
     </plugins> 
    </build> 

</project> 

Запуска этой программы с результатами Spring Devtools в следующей ошибке:

2016-02-15 18:30:48.315 INFO 13828 --- [ restartedMain] o.h.t.schema.internal.SchemaCreatorImpl : HHH000476: Executing import script 'org.hiber[email protected]55ad1b60' 
2016-02-15 18:30:48.509 INFO 13828 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer  : LiveReload server is running on port 35729 
2016-02-15 18:30:48.536 INFO 13828 --- [ restartedMain] o.s.j.e.a.AnnotationMBeanExporter  : Registering beans for JMX exposure on startup 
2016-02-15 18:30:48.582 ERROR 13828 --- [ restartedMain] o.h.p.access.spi.GetterMethodImpl  : HHH000122: IllegalArgumentException in class: problem.domain.Employee, getter method of property: id 
2016-02-15 18:30:48.583 ERROR 13828 --- [ restartedMain] o.s.boot.SpringApplication    : Application startup failed 

java.lang.IllegalStateException: Failed to execute ApplicationRunner 
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:800) [spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE] 
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:787) [spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE] 
    at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:777) [spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE] 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) [spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE] 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1191) [spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE] 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1180) [spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE] 
    at problem.main.SpringBootMain.main(SpringBootMain.java:10) [classes/:na] 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_66] 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_66] 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_66] 
    at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_66] 
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-1.3.2.RELEASE.jar:1.3.2.RELEASE] 
Caused by: org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of problem.domain.Employee.id 
    at org.hibernate.property.access.spi.GetterMethodImpl.get(GetterMethodImpl.java:64) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final] 
    at org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:223) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final] 
    at org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:4633) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final] 
    at org.hibernate.persister.entity.AbstractEntityPersister.isTransient(AbstractEntityPersister.java:4344) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final] 
    at org.hibernate.engine.internal.ForeignKeys.isTransient(ForeignKeys.java:226) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final] 
    at org.hibernate.event.internal.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:499) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final] 
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:99) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final] 
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final] 
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:778) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final] 
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:751) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final] 
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:756) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final] 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_66] 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_66] 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_66] 
    at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_66] 
    at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:338) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final] 
    at com.sun.proxy.$Proxy56.persist(Unknown Source) ~[na:na] 
    at problem.main.DatabaseInitializer.run(DatabaseInitializer.java:24) ~[classes/:na] 
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:797) [spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE] 
    ... 11 common frames omitted 
Caused by: java.lang.IllegalArgumentException: object is not an instance of declaring class 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_66] 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_66] 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_66] 
    at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_66] 
    at org.hibernate.property.access.spi.GetterMethodImpl.get(GetterMethodImpl.java:41) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final] 
    ... 29 common frames omitted 

2016-02-15 18:30:48.585 INFO 13828 --- [ restartedMain] .b.l.ClasspathLoggingApplicationListener : Application failed to start with classpath: [file:/D:/P20058/Documents/FH/Lehre/SWT6U/Uebungen/SpringWeb/hibernate5-problem/target/classes/] 
2016-02-15 18:30:48.585 INFO 13828 --- [ restartedMain] utoConfigurationReportLoggingInitializer : 

Error starting ApplicationContext. To display the auto-configuration report enable debug logging (start with --debug) 


2016-02-15 18:30:48.585 INFO 13828 --- [ restartedMain] s.c.a.AnnotationConfigApplicationContext : Closing org.spring[email protected]63e38bca: startup date [Mon Feb 15 18:30:46 CET 2016]; root of context hierarchy 
2016-02-15 18:30:48.587 INFO 13828 --- [ restartedMain] o.s.j.e.a.AnnotationMBeanExporter  : Unregistering JMX-exposed beans on shutdown 
2016-02-15 18:30:48.587 INFO 13828 --- [ restartedMain] .SchemaDropperImpl$DelayedDropActionImpl : HHH000477: Starting delayed drop of schema as part of SessionFactory shut-down' 
2016-02-15 18:30:48.604 INFO 13828 --- [ restartedMain] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default' 
2016-02-15 18:30:48.604 INFO 13828 --- [ restartedMain] .SchemaDropperImpl$DelayedDropActionImpl : HHH000477: Starting delayed drop of schema as part of SessionFactory shut-down' 

ответ

2

Существует открытая проблема для поддержки Hibernate 5 с Spring Boot here.

В вашем примере, есть два загрузчиков классов:

  1. Система Загрузчик классы
  2. Spring Загрузочного DevTools загрузчик, поддерживающая функция перезапуска

по умолчанию реализации классов Hibernate ClassLoaderService решать по первому глядя в его собственный загрузчик классов, а затем весенний загрузчик классов.

Ваш класс загружен пружиной (с загрузчиком класса перезагрузки), заданный для спящего режима через постоянный блок, но спящий режим перезагружает этот класс с помощью ClassLoaderService и находит его в своем собственном загрузчике классов (система cl). Загружаются два класса, и следствие - это ошибка, которую вы видели.

Весна может быть настроена для загрузки спящего режима в перезагрузку класса загрузчика, но я не смог изолировать набор библиотек: добавление только hibernate- * fail с ошибками из Spring-orm или EntityManager, не видимое из proxybuilder.

Рабочий обходной путь (но на самом деле некрасиво!): Добавить в META-INF/spring-devtools.properties

restart.include.all=.* 

Я предполагаю, что есть лучшее решение, чем это один

 Смежные вопросы

  • Нет связанных вопросов^_^