Skip to content

Provide more details about overriding SpringPhysicalNamingStrategy's case insensitive flag #24045

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ah1508 opened this issue Nov 5, 2020 · 7 comments
Assignees
Labels
type: documentation A documentation update
Milestone

Comments

@ah1508
Copy link

ah1508 commented Nov 5, 2020

Hi,

SpringPhysicalNamingStrategy (applied by defaut by spring boot) does not work in this case.

@Entity
public class Book {
	@Id
	private int id;
	@ElementCollection
	private List<Comment> comments;
}

@Entity
public class User {
	@Id
	private int id;
	@ElementCollection
	@CollectionTable(name="book_comments")
	private List<Comment> comments;
}

@Embeddable
public class Comment {
	@ManyToOne
	private User user;

	@ManyToOne
	private Book book;

	private String text;
	private Instant date;
}

error (when EntityManagerFactory is created) : org.hibernate.MappingException: Repeated column in mapping for collection: Book.comments column: book_id

@Parent cannot be used, because user is not a parent if comments are accessed from the Book, and book is not a parent if comments are accessed from the User.

Removing relations in Comment solve the problem, setting the naming strategies (both physical and implicit) to hibernate default also solve the problem :

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl

I don't know if this mapping is officially supported by Hibernate, but if Hibernate default strategy works, it could also work withSpringPhysicalNamingStrategy.

@ah1508 ah1508 changed the title SpringPhysicalNamingStrategy problem when 2 entities own the same embeddable SpringPhysicalNamingStrategy problem when 2 entities own the same embeddable Nov 5, 2020
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Nov 5, 2020
@wilkinsona
Copy link
Member

Unfortunately, I cannot reproduce the problem that you have described. A minimal application with the three entities above starts successfully. Perhaps there's something more that's required to trigger the problem? If you would like us to spend some more time investigating, please spend some time providing a complete yet minimal sample that reproduces the problem. You can share it with us by pushing it to a separate repository on GitHub or by zipping it up and attaching it to this issue.

@wilkinsona wilkinsona added the status: waiting-for-feedback We need additional information before we can continue label Nov 5, 2020
@ah1508
Copy link
Author

ah1508 commented Nov 5, 2020

Sure, here is a zip file with a simple project.
spring-boot-issue24045.zip

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Nov 5, 2020
@wilkinsona
Copy link
Member

Thanks for the sample. The two different physical naming strategies produce the following identifiers:

Hibernate Spring
DTYPE dtype
Book book
id id
comments comments
comments_KEY comments_key
title title
Member member
firstname firstname
lastname lastname
book_comments book_comments
Member_id member_id
book book
book_id book_id
date date
member member
member_id member_id
text text
Book_id book_id

The difference with Spring Boot's strategy is that the identifiers are all in lower-case. This is described in the reference documentation:

By default, Spring Boot configures the physical naming strategy with SpringPhysicalNamingStrategy. This implementation provides the same table structure as Hibernate 4: all dots are replaced by underscores and camel casing is replaced by underscores as well. By default, all table names are generated in lower case, but it is possible to override that flag if your schema requires it.

As your schema requires mixed-case identifiers, you can override the case sensitivity flag by declaring the following bean:

@Bean
PhysicalNamingStrategy physicalNamingStrategy() {
    return new SpringPhysicalNamingStrategy() {

        @Override
        protected boolean isCaseInsensitive(JdbcEnvironment jdbcEnvironment) {
            return false;
        }
        
    };
}

I think it would be useful if the documentation showed how to "override that flag if your schema requires it". We could include the example @Bean definition above, for example. We can use this issue to do that.

@wilkinsona wilkinsona changed the title SpringPhysicalNamingStrategy problem when 2 entities own the same embeddable Provide more details in the documentation about overriding SpringPhysicalNamingStrategy's case insensitive flag Nov 5, 2020
@wilkinsona wilkinsona added this to the 2.2.x milestone Nov 5, 2020
@wilkinsona wilkinsona added type: documentation A documentation update and removed status: feedback-provided Feedback has been provided status: waiting-for-triage An issue we've not yet triaged labels Nov 5, 2020
@wilkinsona wilkinsona changed the title Provide more details in the documentation about overriding SpringPhysicalNamingStrategy's case insensitive flag Provide more details about overriding SpringPhysicalNamingStrategy's case insensitive flag Nov 5, 2020
@ah1508
Copy link
Author

ah1508 commented Nov 5, 2020

Thanks for the explanation,

Any chance to configure this boolean through application.properties (something like spring.jpa.hibernate.naming.physical-strategy.case-insensitive) ?

@wilkinsona
Copy link
Member

Thanks for the suggestion. Unfortunately, I think that would be rather confusing as it would only work when using the default strategy. In other words, the following configuration would ignore the proposed property:

spring.jpa.hibernate.naming.physical-strategy.case-insensitive=false
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

@ah1508
Copy link
Author

ah1508 commented Nov 5, 2020

I don't think it is a problem if this case-insensitive flag only applies do the default strategy. If a developer wants to use hibernate defaults

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl

It is then obvious that SpringPhysicalNamingStrategy does not need to be configured.

My concern is about the developer who wants to use spring boot defaults (SpringPhysicalNamingStrategy) but with case-insensitive set to false. The definition of a PhysicalNamingStrategy @Bean is is a bit like killing a fly with a hammer. spring.jpa.hibernate.naming.physical-strategy.case-insensitive might not be a good name since this flag is specific to SpringPhysicalNamingStrategy, but how about spring.jpa.hibernate.naming.spring-physical-strategy.case-insensitive ?

@wilkinsona wilkinsona modified the milestones: 2.2.x, 2.2.12 Nov 5, 2020
@wilkinsona
Copy link
Member

Thanks again for the suggestion but we don't want to add a property for this. It's not a particularly common need and, no matter what the properties are called, I don't think it'll be possible to avoid the confusion caused by one property disabling another.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: documentation A documentation update
Projects
None yet
Development

No branches or pull requests

3 participants