#Column(name="DateOfBirth")
private Date dateOfBirth;
I specifically need the above code to create a column named "DateOfBirth," instead Hibernate gives me a column named date_of_birth. How can I change this? Is there a web.xml property? I came across DefaultNamingStrategy and ImprovedNamingStrategy, but not sure how to specify one or the other.
Try putting this in
application.properties
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
FYI: The reason for the insertion of underscores is probably because you're using an ImprovedNamingStrategy. It's set on your Configuration object. See here for an example...
If you don't want the underscores you can just not set the naming strategy, or set it to the DefaultNamingStrategy you discovered earlier.
Here is a possible workaround: if you name it dateofbirth the column in the DB would be named like that, but the attribute name should be the same.
Hibernate takes the camel case format to create/read database columns.
I've had this problem before. I worked with a legacy columns where there was no space in the column names "employeename", "employeerole", "departmentlocation". I hate it because all my beans properties had to be without camel case.
Database columns separated by "_" will be used to properly camelCase as you have just seen.
add below property in the case of spring boot.
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
Put the #Column annotation on the getter:
#Column(name="DateOfBirth")
public Date getDateOfBirth() {
...
}
The workaround proposed was to use #Column(name="dateofbirth"), which worked for my purposes.
ImprovedNamingStrategy has method addUnderscores() which is called from tableName() and columnName()
you can implement your own naming strategy class and override these as per your choice
public class MyOwnNamingStrategy extends ImprovedNamingStrategy {
#Override
public String tableName(String tableName) {
//return addUnderscores(columnName); // skip this
return columnName; // if you want column name variable name same
//return changeAsYouWant(columnName); // as name sames
}
}
You can annotate either fields or getter methods, it doesn't make a difference. Can you post your full hibernate.cfg.xml or persistence.xml file?
I'm not 100% sure, but don't you need to annotate the get method and not the private variable?
I had a similar problem and adding the following two properties to my application.properties solved my issue: spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl .
Related
In my Java code, I have a field named isNegative with a similar column existing in database. But Hibernate insists the name should be is_negative, even with forcing the name with #Column.
#Column(name="isNegative")
private boolean isNegative;
Error:
Caused by: org.hibernate.HibernateException: Missing column:
is_negative in datasource.item
Application.properties:
#JPA
spring.data.jpa.repositories.enabled=false
spring.jpa.database=mysql
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
spring.jpa.generate-ddl=true
spring.jpa.open-in-view=true
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.hibernate.use-new-id-generator-mappings=false
spring.jpa.properties.hibernate.event.merge.entity_copy_observer=allow
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext
That's due to your configuration, because you are setting spring.jpa.hibernate.naming.physical-strategy to PhysicalNamingStrategyStandardImpl which will use underscores for the names.
If you check the Configure Hibernate Naming Strategy section of Spring Docs, you can see that:
Hibernate uses two different naming strategies to map names from the object model to the corresponding database names. The fully qualified class name of the physical and the implicit strategy implementations can be configured by setting the spring.jpa.hibernate.naming.physical-strategy and spring.jpa.hibernate.naming.implicit-strategy properties, respectively. Alternatively, if ImplicitNamingStrategy or PhysicalNamingStrategy beans are available in the application context, Hibernate will be automatically configured to use them.
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.
To solve that you need to remove this property and use the default naming strategy instead:
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.DefaultNamingStrategy
You would need spring.jpa.hibernate.naming.physical-strategy and spring.jpa.hibernate.naming.implicit-strategy
Adding following
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
to application.properties could help. This solution would work from hibernate 5.
Hope it helps.
Please find below my analysis:
If you don't want your naming strategy to add an underscore to the column name or class name, then the strategy that you need to use would look like: spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl. The things that you provide in annotations #Table and #Column’s name attribute would remain as it is. E.g. firstName attribute in entity will get a column name as firstName i.e. No change.
If you don't want to provide annotations and want to manually handle the table name and column names, you should extend the class org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl and override the required methods. If you still use annotations for some of the cases here, remember the overridden methods will apply on the names written in those annotations. spring.jpa.hibernate.naming.physical-strategy=example.CustomStrategy
naive cassandra question, I just want to read the whole column as a string from cassandra using the accessor. Is it possible? Seems to me people are all using data types that are annotated with the table definition :( I could have had defined a user type with the table annotation, but the name of the keyspace is different in every environment
please help. Many thanks
Why not just call .toString () after the mapper ?
Keyspace annotation is not mandatory.
You can specify default keyspace when creating the session.
Session session = cluster.connect("myKeyspace");
How can I get property value inside an annotation. For example I have an annotation
#GetMyValue(value1="Val1",intVal=10)
Now I want "Val1" and 10 to be coming from a property file. I tried
#GetMyValue(value1="${test.value}",intVal="${test.int.value}")
Which doesn't work.
I understand I can use
#Value("${test.value}")
String value;
#Value("${test.int.value}")
int intValue;
I don't want that, it need to be inside an annotation. Any suggestions?
In the Spring #Value the replacement of the placeholder is not done inside the annotation but by the framework when inspecting the bean.
See
DefaultListableBeanFactory#doResolveDependency
DefaultListableBeanFactory#resolveEmbeddedValue
org.springframework.util.StringValueResolver
So, you have to "manually" get the annotation value1 and intVal (which should be a string in your annotation) and resolve them against your properties file.
This need involve more code works I think, but maybe you can have a workaround, for example, not hardcode the value for #GetMyValue annonation, just introduce two parameters in a config bean.
private String stringVal;
private int intVal;
then you can use this two params in you annonation by spEL.
Here is how:
GetMyValue(value1="#{'${test.value}'}",intVal="#{'${test.int.value}'}")
We have a requirement where we need to have the column names externally configurable in Hibernate. The column names in the database will change in the future and we do not want to change the hibernate entity class (annotations) every time this happens.
What is the best approach for this scenario?
You cna either use a custom NamingStrategy (see here)
Or define dynamic maping (see here)
You can use hibernate mappings files
Check this link maybe it can help you
http://www.tutorialspoint.com/hibernate/hibernate_map_mapping.htm
You can keep column names in some class as constants, this way you would only need to update that class when column names change
public class MyEntityColumns {
public static final String COLUMN1 = "column1";
...
}
#Entity
public class MyEntity {
#Column(name = MyEntityColumns.COLUMN1)
private String someField;
}
E.g. I have:
#Column(name = "username")
private String m_username;
Note that the #Column annotation only affects the database column name.
Hibernate still thinks the name of the property is 'm_username'.
How can I tell Hibernate that the property name is just 'username'?
Please tell me there is a way to do this...
Edit: I removed the #AccessType annotation in my code example, as it is not relevant for this question.
Update: After switching everything to field access, this exception happens:
org.hibernate.QueryException: could not resolve property: username of: mypackage.model.User
It happens here:
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.eq("username", username));
User result = (User) criteria.uniqueResult();
And the reason is most likely that hibernate only 'knows' of a property called 'm_username', while I think of it and program against a property named 'username'. Also note that my getters/setters are called: "getUsername()" and "setUsername(String value)" (automatically generated).
why do you use AccessType.PROPERTY?
remove it and it is accessed by 'field'.
do not mix field and property annotations. stick to one or the other.
As per my knowledge we can't* .
There is still one issue with the way hibernate looks up the methods
for a given property name.
Suppose you have a property with a name like "mProperty" (first
lowercase, second uppercase, rest doesn't matter). Not the accessor
methods in the source code will be getMProperty and setMProperty.
The way BasicPropertyAccessor.getterMethod is implemented in that way .
I found one lead here: https://forum.hibernate.org/viewtopic.php?f=1&t=943110
But the thread is 7 years old and I don't know how to apply this to annotation based configuration (I don't have an xml configuration file).