I use Spring JPA + Hibernate Search to implement persistant and search in my application.
I have models like this
public class FeatureMeta {
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#Column(unique=true)
private String uri;
#Column
#Field
private String name;
#Field
#Column
private String businessDesc;
#Field
#Column
private String logicalDesc;
.
.
#Field
#Column(insertable=false,updatable=false)
private Long totalDownloads;
.
.
}
To give the idea about this class, "FeatureMeta" maintains meta-data information which updates very rarely.
However the field "totalDownloads" is constantly changing whenever user download information about this "feature".
Basically "totalDownloads" is not part of the meta-data but I had to put this field in the model because I need to show the "totalDownloads" in the search result of "feature search".
I use same JPA Repository which updates both MySQL and Lucene index.
My question is ; Is it possible to only update the "totalDownloads" in the Lucene Index but not the entity in MySQL whenever change is done to the "totalDownloads" field ?
You'll have to use the #Transient annotation to mark that you don't want this attribute part of your database model.
#Field
#Transient
private Long totalDownloads;
Making the field transient also means it won't be loaded from the database (completely ignored by Hibernate ORM, but not by Hibernate Search); if that's not what you intended you could add an additional field: map one to Hibernate ORM and the other indexed with Hibernate Search and annotated with #Transient. In this case you'll have to make the setter update both fields.
You will likely need to change this configuration property too:
hibernate.search.enable_dirty_check = false
as Hibernate Search will otherwise not generate any change in the Lucene index, in case the entity has no other changes.
Related
I have a pojo with two fields that need to be unique, the id and the email. So I added the #Indexed(unique = true) annotation to the necessary fields like so
public class User {
#Id
#Indexed(unique = true)
private String id;
#Indexed(unique = true)
private String email;
private int money;
I then tested it out and it was not enforced. So I googled about and I found a previous answer here - Spring Data: Unique field in MongoDB document and subsequently deleted the collection, added spring.data.mongodb.auto-index-creation=true to my application.properties file and tried again.
However, the unique field still isn't enforced! I see there is another answer using ensureIndex() but it also has a great comment that was never answered- Why do we need to use the annotation if all the work is done on mongoTemplate?
So since the question is old enough that apparently the only working answer is depreciated (the new way is using createIndex()), I thought it was time for a new version. Is it possible to require a column in a mongo collection to be unique from Spring Boot?
In Hibernate Search 5.x I can map entity method as the fulltext field like this:
#Entity
public class Person {
#Id
#GeneratedValue
private Long id;
private String name;
private String surname;
public String getWholeName() {
return name + " " + surname;
}
// getters, setters
}
// Mapping configuration, programmatic approach
SearchMapping sm = new SearchMapping();
sm
.entity(Person.class)
.indexed()
.property("wholeName", ElementType.METHOD)
.field();
Then I have a field with name "wholeName" in my fulltext index and it contains return value of getWholeName() method.
How to do it in Hibernate Search 6? I found only a way how to map an entity field but not a method. Thank you!
Short answer
If there is no field named wholeName, Hibernate Search 6 will automatically fall back to the getter. The ElementType from Hibernate Search 5 is no longer necessary, and that's why it was removed.
Note that Hibernate Search is also smarter when it comes to detecting changes in entities. That's usually great, but the downside is that you'll need to tell Hibernate Search what other attributes wholeName relies on. See this section of the documentation (you can also find an example using the programmatic mapping API here).
Long answer
When an attribute has a field but no getter, or a getter but no field, there is no ambiguity. Hibernate Search uses the only available access type.
When an attribute has both a field and a getter, there is a choice to be made. Hibernate Search 6 chooses to comply with Hibernate ORM's access type.
Hibernate ORM accesses attributes either by direct access to the field ("field" access type) or through getters/setters ("property" access type).
By default, the access type in Hibernate ORM is determined by where your #Id annotation is. In this case, the #Id annotation is located on a field, not a method, so Hibernate ORM will use the "field" access type. And so will Hibernate Search.
You can also set the Hibernate ORM access type explicitly using the #Access annotation, either for the whole entity (put the annotation on the class) or for a particular property (put the annotation on the field). Hibernate Search will comply with this too.
I am trying to implement search functionality using hibernate search for my project which is in spring boot .
I used hibernate search annotations like #Indexed, #Field.
When i use datatype of id Field as Long then search is performed and list of results is returned but in my project UUID is used as datatype for id field which is also primary key .in the case of UUID the result is an empty list.
#Id
#GeneratedValue
private UUID id;
How can i perform search operation using UUID as datatype for id field?
Please use the following code
#Id
#Type(type = "uuid-char") // add column type
#GeneratedValue
#Column(name = "id")
You need to add #Type for the ID column if your using uuid as your data type
I hope it helps you
Thanks
Yes, you can use UUID as a document ID, and it should work out of the box.
If you're not getting any result:
Check you're using a recent version of Hibernate Search (5.11+) and Hibernate ORM (5.4+).
Check that you reindexed your data after changing the type of your ID.
When reindexing, check your logs for indexing failures and report them here.
Test with a very simple query, for example qb.all().createQuery(). If you get results with that query, the problem is with your initial query, not with your identifier.
You can apply #sridhar-karuppusamy's suggestion, but that should only be necessary if you want the database type to be VARCHAR instead of VARBINARY. And that is irrelevant to Hibernate Search.
I would like Hibernate to disable certain classes from being validated on startup.
My particular use-case:
spring.jpa.hibernate.ddl-auto=validate
#Table (name = "SAME_TABLE")
public class Entity1 {
#Column
private Long value;
// rest of values
}
#Table (name = "SAME_TABLE")
public class SearchEntity2 {
#Column
private String value;
// rest of values
}
As you can see I have two classes mapped to the same table called SAME_TABLE. This is because I want to do wildcard searches on numeric field value
JPA Validation fails on Oracle (h2 succeeds suprisingly) because it detects that the String is not NUMERIC(10).
This question here by #b0gusb provides an excellent way of filtering out via table name:
How to disable schema validation in Hibernate for certain entities?
Unfortunately my table name is identical. Is there any way of getting to the Java class name from SchemaFilteror perhaps another way of doing this?
Thanks
X
I am trying to save my entity in elasticsearch using spring data elasticsearch, all the attributes are saved (including objects) except for enum its always stored as null, this is my entity
#Entity
#Document(indexName="invoices", type="invoices", shards = 1)
public class Invoice {
#Transient
#JsonIgnore
#org.springframework.data.annotation.Id
private String searchIndex;
#Field(type = FieldType.String)
private InvoiceStateEnum state;
with and without #Field attribute state is being saved as null even though the object is being saved has value for this enum.
Any help is appreciated
As spring-data-elasticsearch uses Jackson, you can put the #JsonFormat.Shape.STRING annotation to your enum:
#JsonFormat.Shape.STRING
public enum InvoiceStateEnum {
// your enum code
}
I was able to solve the issue by removing folder data under my project and rerun the application, seems like for some reason elastic search was not updating the records so I was getting null since the attribute was added recently.