Я попытался выяснить новый механизм интеграции JPA Hibernate и Spring Data.Я последовал примеру, приведенному на https://www.baeldung.com/hibernate-5-spring, но безрезультатно.Дальнейшие исследования принесли мне проблему на Github от Юргена Хеллера, сказавшую:
[...] Это охватывает множество оснований для начала: в Hibernate 5.2 и 5.3, LocalSessionFactoryBeanи HibernateTransactionManager служат в качестве совместимой на 99% замены для LocalContainerEntityManagerFactoryBean и JpaTransactionManager во многих сценариях, позволяя взаимодействовать с SessionFactory.getCurrentSession () (а также с HibernateTemplate) рядом с @PersistenceContext EntityManager 21 (локальная транзакция # 21) (в том же месте).Кроме того, такая установка также обеспечивает более сильную интеграцию Hibernate (# 21494, # 20852) и большую гибкость конфигурации, не будучи ограниченным контрактами начальной загрузки JPA.
И соответствующий Javadoc для LocalSessionFactoryBean класс, заявив:
Совместимо с Hibernate 5.0 / 5.1, а также 5.2 / 5.3, начиная с Spring 5.1.Установленный с Hibernate 5.3, LocalSessionFactoryBean является непосредственной альтернативой LocalContainerEntityManagerFactoryBean для общих целей JPA: В частности, в Hibernate 5.3 Hibernate SessionFactory также будет нативно представлять интерфейс JPA EntityManagerFactory, а интеграция Hibernate BeanContainer будет зарегистрирована вне реестра.В сочетании с HibernateTransactionManager это, естественно, позволяет смешивать код доступа JPA с собственным кодом доступа Hibernate в одной и той же транзакции.
Я реализовал простой пример проекта с помощью Spring Boot 2.1.2.RELEASE.Он обеспечивает простую настройку (такую же, как в примере с Baeldung выше) и подключается к базе данных PostgreSQL.Кроме того, он использует модель и репозиторий для теоретической работы с данными.Классы выглядят так:
DemoApplication.java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication
{
public static void main(String[] args)
{
SpringApplication.run(DemoApplication.class, args);
}
}
BasicConfig.java
package com.example.demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.repository.config.BootstrapMode;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import org.postgresql.Driver;
import java.util.Properties;
@Configuration
@EnableJpaRepositories
public class BasicConfig
{
@Bean
public LocalSessionFactoryBean sessionFactory()
{
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan("com.example.demo");
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean
public DataSource dataSource()
{
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriverClass(Driver.class);
dataSource.setUrl("jdbc:postgresql://localhost:5432/backend");
dataSource.setUsername("backend");
dataSource.setPassword("backend");
return dataSource;
}
@Bean
public PlatformTransactionManager hibernateTransactionManager()
{
HibernateTransactionManager transactionManager
= new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
private final Properties hibernateProperties()
{
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty(
"hibernate.hbm2ddl.auto", "create-drop");
hibernateProperties.setProperty(
"hibernate.dialect", "org.hibernate.dialect.PostgreSQL95Dialect");
return hibernateProperties;
}
}
Model.java
package com.example.demo;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "model")
public class Model
{
@Id
@GeneratedValue
@Column(name = "id", unique = true, nullable = false)
private Long id;
@Column(name = "name")
private String name;
}
DemoRepository.java
package com.example.demo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface DemoRepository extends JpaRepository<Model, Long>
{
}
Как только я добавляю DemoRepository
, приложение больше не запускается, потому что:
A component required a bean named 'entityManagerFactory' that could not be found.
Action:
Consider defining a bean named 'entityManagerFactory' in your configuration.
Полное сообщение об ошибке:
Exception encountered during context initialization - cancelling refresh
attempt: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'demoRepository':
Cannot create inner bean '(inner bean)#6c5ca0b6' of type [org.springframework.orm.jpa.SharedEntityManagerCreator]
while setting bean property 'entityManager';
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name '(inner bean)#6c5ca0b6':
Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No bean named 'entityManagerFactory' available
IУ меня сложилось впечатление, что SessionFactory
теперь правильно реализует и выставляет EntityManagerFactory
, но, похоже, это не так.Я почти уверен, что в моей реализации есть недостаток и что пример из Baeldung действительно работает правильно.Я надеюсь, что кто-то может указать мне на это и помочь мне понять мою ошибку.
Спасибо всем заранее.
Зависимости:
- spring-data-jpa: 2.1.4.RELEASE
- пружинный сердечник: 5.1.4.RELEASE
- пружинный стержень: 5.1.4.RELEASE
- гибернационный сердечник: 5.3.7.Final
- spring-boot: 2.1.2.RELEASE
gradle.build
buildscript {
ext {
springBootVersion = '2.1.2.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.postgresql:postgresql'
}