繁体   English   中英

从 SpringMVC 到 SpringBoot 的 Hibernate 配置

[英]Hibernate Configuration from SpringMVC to SpringBoot

我(该死的)正在移植一个 SpringMVC 应用程序,作为 Tomcat 中的战争部署到 SpringBootApplication 中,我面临着很多问题,基本上来自 Hibernate。

该应用程序是用 DAO/Service 模式制作的。 我知道 Spring boot 想使用 Spring 数据 JPA,但我不想重构所有应用程序。

问题尤其是在某个地方我得到了 No Session 的休眠异常,更常见的是org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role where old SpringMVC application works。

例如,我有这个实体

@Entity
@Table(name = "PARK")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "idPark")
public class Park implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = -7630704706109692038L;
    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id_park", unique = true, nullable = false)
    private int idPark;

    @NotEmpty
    @Column(name = "nome_park")
    private String nomePark;

    @Column(name = "latitude")
    private double latitude;

    @Column(name = "longitude")
    private double longitude;

    @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.DETACH, CascadeType.REFRESH}, mappedBy = "park")
    @JsonIgnore
    private List<Piano> piani;
//getters and setters
}

在控制器中,如果我打电话

List<Piano> piani = pianoService.findPianoByPark(park);

从带有@Transactional注释的服务类中,我仍然收到异常

这就是我配置休眠的方式

@Configuration
@EnableTransactionManagement
@ComponentScan({ "it.besmart.epark.persistence" })
@PropertySource(value = { "classpath:application.properties" })
public class HibernateConfiguration {
    
@Autowired
private Environment environment;

@Bean
public LocalSessionFactoryBean sessionfactory(){
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
    sessionFactory.setDataSource(dataSource());
    sessionFactory.setPackagesToScan(new String[] {"it.besmart.epark.persistence.model"});
    sessionFactory.setHibernateProperties(hibernateProperties());
    return sessionFactory;
}

@Bean
public DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
    dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
    dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
    dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
    return dataSource;
}
 
private Properties hibernateProperties() {
    Properties properties = new Properties();
    properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
    properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
    properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
    return properties;        
}
 
@Bean
@Autowired
public HibernateTransactionManager transactionManager(SessionFactory s) {
   HibernateTransactionManager txManager = new HibernateTransactionManager();
   txManager.setSessionFactory(s);
   return txManager;
}

我认为这是一个配置问题,因为旧的应用程序使用这个模式,所以也许在 Spring boot 中我们需要配置其他东西来与 Hibernate 一起工作。 我正在使用 Spring Boot 1.5.8 等 Hibernate 5.0.12.Final

我认为您正试图在 Hibernate 事务之外(例如,在视图、控制器或非事务性服务中)获取一个延迟加载的集合。 您可以尝试使用@Transactional调用getPiani()来注释类。

还要记住,一个好的做法是只有服务层事务性。

如果类路径中有所有必需的依赖项,则不必再显式配置休眠。 因此,请确保您已添加spring-boot-starter-data-jpaspring-boot-starter-data-jdbc作为依赖项。

尝试删除HibernateConfiguration并在application.properties添加您的配置,以便 Spring Boot 可以处理设置:

spring.jpa.database-platform = org.hibernate.dialect.PostgreSQL94Dialect
spring.jpa.show-sql = false
spring.datasource.url = jdbc:...
spring.datasource.username = ...
spring.datasource.password = ...
spring.datasource.driver-class-name=...jdbc.Driver

你可以阅读更多关于春季启动数据库配置的位置: https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html参考可用的应用特性: HTTPS:/ /docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html

只要您不停用它,Spring Boot 就应该自动选取您的实体。 如果您确实需要指定一个包,您可以使用@EntityScan 例如,一旦我们的实体位于与我们的 Application 类不同的项目中,我们就必须这样做。

@SpringBootApplication
@EntityScan(basePackages = { "it.besmart.epark.persistence" })
public class Application {

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM