介绍
今天,我将讨论更具体的问题。 这次没有设计模式或算法:-)。 我们并不总是从头开始设计软件组件。 通常,我们必须尝试使现有软件组件协同工作。
Spring Boot是Java世界上最好的免费软件之一。 它解决了Spring的许多配置问题。 它非常灵活,功能强大。
Spring Data是Spring项目集合的一部分。 它提供了用于处理数据库的高级工具。 其中最有用的是自动存储库。 一个类可以实现JpaRepository,并且大多数用于处理数据的方法将自动创建。
Thymeleaf是一个HTML模板引擎。 它可以使用Spring Boot的某些功能,例如模板中Spring bean的调用方法以及许多其他内容。 官方文档有很棒的教程。
我使用了spring-boot-starter-parent版本2.0.1.RELEASE – 2.0.4.RELEASE。 其他依赖项由Spring Boot提供。
问题描述
任何与Spring Boot,Spring Data和Thymeleaf一起使用的应用程序的主要思想是编辑数据库中的数据。 Spring-boot-starter-data-jpa包含Hibernate,可用于处理数据库中的数据。 Thymeleaf可用于向用户显示数据。 Spring Boot将它们连接在一起。
一个非常简单的场景包括一个与另一实体具有一对多关系的实体。 用户希望能够创建一个新实体并在HTML中选择另一个实体
选择框。
这是第一个问题出现的地方。 如果使用标准的Thymeleaf结构,则不能组装后备bean。在选择框中使用以下结构选择的对象:
<form action="#" th:action="@{/<some Action>}" th:object="${beanObj}" method="post">
.... <other fields>
<select th:field="*{room}" class="textinput">
<option th:each="currRoom : ${allRooms}"
th:value="${currRoom}" th:text="${currRoom.name}">no
name</option>
</select>
</form>
不是由Thymeleaf创建的。 我没有在官方文档中提及此内容。
解
经过一些调试后,我找到了根本原因。 原来Thymeleaf将所有字段作为参数传递给POST请求。 它使用toString方法将对象转换为String并作为参数添加到POST请求中。 它发送这样的参数:
room: Room+[id=273,+name=room111]
在控制器方法中,必须将该值转换回对象形式。 Spring Boot使用转换器来做到这一点。
解决方案是–向conversionService注册适当的转换器。 并在实体的toString方法中使用这些转换器,以确保使用相同的方法来转换为String形式并返回。
下一个问题
听起来很有趣不是吗? 已经找到解决方案,但是还有更多问题吗? 实际上,所描述的解决方案在没有Spring Data的情况下效果很好。 使用Spring Data,转换再次失败。 而且即使没有Spring Data也不需要该bean,Spring Boot仍希望您创建entityManagerFactory bean。
下一个解决方案
可以通过在Internet上进行一些深入的搜索来解决entityManagerFactory bean的问题。 这是我最终得到的解决方案:
@Primary
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource ds) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(ds);
em.setPackagesToScan("<some packages>");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
@Bean
public SessionFactory sessionFactory(@Qualifier("entityManagerFactory") EntityManagerFactory emf) {
return emf.unwrap(SessionFactory.class);
}
private Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
properties.setProperty("hibernate.default_schema", "public");
properties.setProperty("hibernate.show_sql", "true");
// Validation will fail because the tables use bigint as the ID but it is mapped to the Integer type by Hibernate
// Validation expects a 8-bit number as the mapping to bigint.
properties.setProperty("hibernate.hbm2ddl.auto", "none");
return properties;
}
第二个问题原来更加复杂,需要大量调试。 最终,我发现spring-data某种程度上改变了Spring Boot使用的转换服务。 使用Spring Data mvcConversionService代替默认的conversionService。 格式程序/转换器必须添加到WebMvcConfigurer类(实现WebMvcConfigurer的类)中。 方法是addFormatters:
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new <SomeConverter>);
...
现在,所有问题已解决,Spring Data可以与Thymeleaf一起使用。
快乐的编码和勤奋的调试!
翻译自: https://www.javacodegeeks.com/2018/11/spring-data-thymeleaf.html