我(该死的)移植SpringMVC应用程序,将Tomcat中的战争部署到SpringBootApplication,我面临很多问题,基本上来自Hibernate。
应用程序是使用DAO / Service模式制作的。 我知道Spring引导想使用Spring数据JPA,但我不想重构所有的应用程序。
问题尤其在某个地方我得到了No Session的hibernate异常,而且更多的是旧的SpringMVC应用程序工作的org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role
。
例如,我有这个实体
@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
注释的服务类,我仍然得到例外
这就是我配置Hibernate的方式
@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启动我们需要配置其他东西来使用Hibernate。 我使用的是Spring Boot 1.5.8以及Hibernate 5.0.12.Final
答案 0 :(得分:0)
我认为你试图在Hibernate事务之外获取一个延迟加载的集合(例如,在视图,控制器或非事务服务中)。您可以尝试使用getPiani()
@Transactional
调用对该课程进行注释。
还要记住,一个好的做法是只有服务层事务。
答案 1 :(得分:0)
如果你在类路径中拥有所有必需的依赖项,则不必再显式配置hibernate。
因此,请确保已将spring-boot-starter-data-jpa
或spring-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
您可以在此处阅读有关使用Spring Boot的数据库配置的更多信息: 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);
}
}