I use hibernate in an application with spring boot 1.4.0.RELEASE.
The Entity for the index looks something along the lines of:
#Entity(name = "SearchableTariffItem")
#Indexed
public class SearchableTariffItem {
public static final String ZIFFER_ANALYZER_NAME = "ZIFFER_ANALYZER";
#GeneratedValue(strategy = GenerationType.TABLE)
#Id
private Long id;
...
}
I now get the following warning when I save the entity for the first time:
2016-08-26 15:08:32.501 WARN 8476 — [apr-8080-exec-6] org.hibernate.orm.deprecation : HHH90000015: Found use of deprecated [org.hibernate.id.MultipleHiLoPerTableGenerator] table-based id generator; use org.hibernate.id.enhanced.TableGenerator instead. See Hibernate Domain Model Mapping Guide for details.
Unfortunately I don't know where I can configure my application (preferably in a the application.yml) to use the TableGenerator class.
I use the following dependency:
Hibernate core 5.0.9.Final
Hibernate search ORM 5.5.1.Final
Lucene 5.3.1
The property that controls this behaviour in Hibernate is hibernate.id.new_generator_mappings, which defaults to true for Hibernate 5 -> which means the new TableGenerator will be used instead of the deprecated MultipleHiLoPerTableGenerator .
Spring Boot however defaults this property to false, which means the old generator will be used, unless you explicitly tell it you want the new one.
You need to set the property spring.jpa.hibernate.use-new-id-generator-mappings to true to get the TableGenerator.
See https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-1.4-Release-Notes#generator-mappings
Related
I'm using spring-boot-data-elasticsearch to persist the documents into elasticsearch.
Below is my Document Object for it.
#Builder
#Document(indexName = "testidx", createIndex = false)
public class Book {
#Id
private final String _id;
#NotNull
#CreatedDate
#Field(type = FieldType.Date, format = DateFormat.basic_date_time)
private final Instant regTime;
#NotNull
#Field(type = FieldType.Text)
private final String bookName;
}
However, when I saved the object into the ElasticSearchRepository, the regTime(which has to be created and saved automatically by #CreatedDate), has not been saved.
elasticRepository.save(
Book.builder()
.bookName("test")
.build()
);
GET /testidx/_search
{
"_index" : "testidx",
"_type" : "_doc",
"_id" : "M3IS_XgBGpcXDVxetXXn",
"_score" : 1.0,
"_source" : {
"_class" : "{test class Name}",
"bookName" : "test",
}
}
Could you please let me know what I have been missed?
I'm working on the spring-boot 2.4.5 (and spring-boot-starter-data-elasticsearch 2.4.5 also) and ElasticSearch 7.12.0.
Please check the documentation about auditing (https://docs.spring.io/spring-data/elasticsearch/docs/4.2.0/reference/html/#elasticsearch.auditing).
Your entity needs to implement the Persistable interface and needs to reimplement the isNew() method (see section 9.2.1).
Note: I just saw that in the documented entity sample the #CreatedDate and #CreatedBy annotations are missing. I will fix the docs, the annotation is needed of course.
Then do you have #EnableElasticsearchAuditing on your Spring Boot application or any other configuration class? This is needed as well.
Unfortunately spring-data-elasticsearch does not support all persistence related annotations, neither all of the mapping-annotations of JPA, nor the auditing-annotations of Spring-Data, where #CreatedDate belongs to.
Solution
So I would drop it and just use the basic #Field annotation.
Then your property regTime should show up in JSON request as sibling above bookName and be persisted as expected.
However, without the special feature of Spring-Data's #CreatedDate annotation (convenience for auditing), you have to care for initialization yourself, set the value before persisting, e.g. using regTime = Instant.now() (either in field definition, in constructor, or else).
Background
See the docs for Meta Model Object Mapping, 6.1.1. Mapping Annotation Overview which currently (version 4.2) only includes these field annotations:
#Id
#Field
#GeoPoint
See also the official guide 8. Elasticsearch Repositories.
Formerly there was an enum SUPPORTED_ID_PROPERTY_NAMES in SimpleElasticsearchPersistentProperty which listed these field-annotations.
See similar question: Does Spring Data Elasticsearch supports #Id annotation from JPA?
This tutorial helped me as introduction to elasticsearch-data:
Spring Boot Elastic Search Example - Java Developer Zone
my application is logging
org.hibernate.orm.deprecation : HHH90000014: Found use of
deprecated [org.hibernate.id.SequenceHiLoGenerator] sequence-based id
generator; use org.hibernate.id.enhanced.SequenceStyleGenerator
instead. See Hibernate Domain Model Mapping Guide for details.
There is a similar question about this here that fix the problem, but my question is if it's possible replace the Sequence generator org.hibernate.id.SequenceHiLoGenerator
to org.hibernate.id.enhanced.SequenceStyleGenerator without go throught every single domain class annotations writing a custom #GenericGenerator? Something like a property maybe...
My code has something like this:
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator="seq_name")
#SequenceGenerator(name="seq_name", sequenceName="hibernate_sequence")
private Long id;
Thank you.
You should be able to set hibernate.id.new_generator_mappings to true, which is the default in Hibernate 5, and that should disable the legacy behavior and automatically selecting the enhanced generator.
Similar to this problem:
ORA-00904: : invalid identifier Issue with Hibernate Dependent objects program
I'm trying to do batch inserts using hibernate. Whenever I try to do a session.save or session.saveOrUpdate, hibernate complains that I have an invalid identifier
Stack output
2015-11-20 14:17:37 ERROR : ORA-00904: "USERATTRID": invalid identifier
Entity
public class Attribute {
#Id
#GenericGenerator(name = "increment", strategy = "increment")
#GeneratedValue(generator = "increment", strategy = GenerationType.SEQUENCE)
private int USERAttrID;
private long userNumber;
private String attribute;
private String value;
private String description;
private LocalDateTime updatedDate;
private LocalDateTime createdDate;
The database looks like this after hibernate applies its improved naming convention
USER_ATTRID
ATTRIBUTE
USER_NUMBER
DESCRIPTION
VALUE
CREATED_DATE
UPDATED_DATE
If I use repository.save then the code works fine. The crud repository seems to know how to map my entity to the database, but hibernate's session does not.
I see a few solutions here:
1. Use hibernate's default default naming strategy. Tables get named things like USERATTRID. I'm not sure what implications this has other than making columns harder to read.
2. Combine hibernate with crudrepository using the tutorial here
http://frightanic.com/software-development/jpa-batch-inserts/
3. Figure out how to get hibernate's session.save to use the improvedNamingConvention mapper. Can anyone help me with this or provide me another suggestion?
4. I guess I can also manually map the columns :/. Ugh this is messy, you now have to manually do all the conversions on dates :/
It would be good to know how you are actually getting the session?The most likely cause that comes to mind is that when you using the hibernate session it is actually not built using the same configuration that was used to build the entity manager that CrudRepository uses underneath.
Ends up being more trouble than it's worth as you stop using hibernate jpa's defaults and all the things spring-data provides you out of the box
Stupid. The tutorial doesn't even use crudRepository
Same as 1
Same as 1
Instead I'm banging my head against a wall trying to get a simple batch process to insert
I'm currently migrating some existing code from Hibernate 3.2 to Hibernate 3.6.10.Final
(and also from Spring 2.0 to Spring 3.1.2 by the way).
I have an issue with some integration tests running against H2 database, verifying that some fields are not nullable.
- I test that an attempt to insert a null String into a field marked as nullable=false ends with an Exception
- I checked that the schema is correctly created : the column is not nullable.
Using H2 (with MySQL mode), nullable constraint is ignored : an empty String is inserted in database.
I don't reproduce the case if I run my test against a MySQL database.
It worked before with Hibernate 3.2
For example, if I have a class Person :
#Entity
class Person {
#Id
#GeneratedValue
private Long id;
#Column(nullable=false)
private String name;
//getters and setters
}
And then I have a test (still using JUnit3, I'll migrate this later) :
#ExpectedException(value=DataIntegrityViolationException.class)
public void testPerson_NameCantBeNull() throws Exception {
// Given
Person person = new Person();
person.setName(null);
// When
getHibernateTemplate().persist(person);
//Flush and clear session
}
I could fix this by replacing nullable=false by #NotNull annotation but I don't want to replace it in my huge code base as I wouldn't expect the same Exception.
I had a quick look into H2Dialect class and JIRA issues in Hibernate but I didn't find anything.
Does anybody know where it comes from ?
EDIT :
Some additional informations, I added the TRACE level in Hibernate logs.
When I insert null and the field is marked with #Column(nullable=false), I have the following log :
2013-01-16 15:57:52 TRACE [BasicExtractor] found [] as column [NAME1_3_]
When I insert null and the field is not marked with #Column(nullable=false), I have the following log :
2013-01-16 15:57:52 TRACE [BasicExtractor] found [null] as column [NAME1_3_]
EDIT (22/01/13) :
I still didn't found where the problem exactly come from, but I found out that it is tied to MySQL mode with H2 : if I disable MySQL mode, Hibernate doesn't try anymore to replace my null Strings by empty Strings.
But I can't do this since some other pieces of code are tied to MySQL syntax.
Any idea ?
I didn't have enough time to digg in Hibernate and MySQL dialect, so I moved to Java Validation Framework, using #NotNull annotation.
It does the job and meets one of our other requirement : a part of our model is used in a Grails application and we want to use constraints to validate part of CRUD operations (not possible with pure javax.persistence annotations).
According to my JPA 2.0 book (and online documentation), I should be able to mix field and property access within a single entity or entity hierarchy. The annotation of #Access on the class specifies the default access. When placed on a field or property getter #Access can specify that the default should be overridden for this field.
#Entity
#Access(AccessType.FIELD)
Class Foo {
#Id
int id;
#Column(name = "myfield")
String myField;
#Column(name = "myProp")
#Access(AccessType.PROPERTY)
public int getMyProp () {
return 3;
}
public void setMyProp (int p) {
// do nothing
}
}
This class should result in a table with three columns. However it doesn't with Hibernate...the "myProp" column is missing from the table because apparently Hibernate takes its field vs property cue from the entity ID and runs with it...totally ignoring the JPA spec with regards to #Access.
Can anyone confirm this or did I make a stupid mistake somewhere?
I've seen similar (not the same but similar) issues like HHH-5004 so I wouldn't exclude that this might be a new one (the TCK doesn't seem exhaustive). But what version of Hibernate are you using? Did you try with the latest?
Based on the docs your code seems to be right. The #Access(AccessType.FIELD) annotation on top is unnecessary, because you annotated the field int id;
This tells hibernate to use field access. I tried a very similar example with annotations and xml config mixed. This leads to the same behaviour, so it's probably a bug in hibernate.
I tried with hibernate 3.5.3