Почему в Spring Boot и Hibernate не работает по умолчанию Naming strategy?
Открываю официальную документацию по Spring Boot и вижу, что Spring Boot по умолчанию использует стратегию именования SpringPhysicalNamingStrategy, которая принадлежит Hibernate и подразумевает правила:
- все точки заменяются символами подчеркивания
- регистр camelCase заменяется также подчеркиванием
- по умолчанию все имена таблиц создаются в нижнем регистре. Например, объект
TelephoneNumberотображается в таблицуphone_number.
Есть у меня сущность GiftCertificate. Почему при выполнении запроса через EntityManager мой Entity-класс c именем GiftCertificate переименовывается в giftcertificate, а не в gift_certificate, как ожидается?
На всякий случай привожу пример:
- запрос в БД:
@Override
public Set<GiftCertificate> findAll() {
return entityManager.createQuery(FIND_ALL_GIFT_CERTIFICATES_SQL, GiftCertificate.class)
.getResultStream()
.collect(Collectors.toSet());
}
Результат - java.sql.SQLSyntaxErrorException: Table 'gift_certificates_system_db.giftcertificate' doesn't exist
- сущность
GiftCertificate:
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Entity
@EntityListeners(GiftCertificateListener.class)
public class GiftCertificate implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String description;
@Column(nullable = false)
private BigDecimal price;
@Column(nullable = false)
private Integer duration;
@Column(nullable = false)
private LocalDateTime createDate;
@Column(nullable = false)
private LocalDateTime lastUpdateDate;
}
- Конфигурация:
@Configuration
@EnableTransactionManagement
public class EsmConfiguration implements WebMvcConfigurer {
private final DataSource dataSource;
@Autowired
public EsmConfiguration(DataSource dataSource) {
this.dataSource = dataSource;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource);
entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
entityManagerFactoryBean.setPackagesToScan(ENTITY_PACKAGES_TO_SCAN);
return entityManagerFactoryBean;
}
@Bean
public JpaTransactionManager jpaTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messages = new ResourceBundleMessageSource();
messages.setBasename("locale");
messages.setDefaultLocale(Locale.ENGLISH);
messages.setDefaultEncoding("UTF-8");
return messages;
}
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
}
Что я пробовал:
- в
application.propertiesуказывал явноspring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl, но не помогает. - явно указывать
@Table(name = "gift_certificate")- помогает, но меня интересует реализация по умолчанию без явного указания имен таблиц в куче сущностей, что загромождает код.
Ответы (1 шт):
ImplicitNamingStrategy используется, когда явно не указывается имя базы данных, имя таблицы, имя столбца в определении сущности. Т.е. когда не используется аннотация @Table или если есть аннотация @Column, но свойство name не задано.
PhysicalNamingStrategy стратегия вступает в работу, когда явно задано имя БД, имя таблицы, имя столбца, например @Column(name = "camelCase"). Вот тогда Hibernate уже будет работать со значением параметра name.
Задаются свойства в application.properties:
spring.jpa.hibernate.naming.implicit-strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
Мне нужно была стратегия ImplicitNamingStrategy, а не PhysicalNamingStrategy.