Say I have some collection called candidates. I want to create a text index on all fields inside this collection. In mongo, I know that I can do it this way
db.candidates.createIndex({"$**":"text"},{name:"TextIndex"})
Here is my java pojo or entity.
#Document(collection = "candidates")
public class Candidate {
#Id
private String id;
private String firstName;
private String lastName;
// Other stuff: removed for brevity
}
Now how do I do db.candidates.createIndex({"$**":"text"},{name:"TextIndex"}) in java? That is how do I index an entire pojo or how do I do index all fields in my collection?
This question tried to do the same thing, but it does not have full details.
Also I looked at #Indexed annotation, however how can I use to index an entire collection since it can only be applied to a field?
With #TextIndexed you can at least index all the field you want to include in your index. https://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/index/TextIndexed.html
Alternatively you can use the mongotemplate for this. How to set #TextIndex name in an entity with Spring-Data-MongoDB
Related
I have a custom POJO on which I am mapping the database records using JOOQ .fetchInto(TestClassDto.class). Most of the fields in my POJO are exactly similar to a database table's columns. However, there are a few that are different, therefore, I added java persistence and used #Column to explicitly map such columns on my POJO as described here.
Unfortunately, this is not working if I use #Column on a few specific fields. Only the fields that are annotated with #Column are mapped and the rest are ignored and set Null even though they are similar to the table column name and should be mapped implicitly.
Could you give me a hint if I am missing anything?
Sample POJO:
#Getter
#Setter
public class TestClassDto {
#Column(name = "field_AB_XYZ") // explicit mapping is required, thus need #Column
private Long myfieldAB;
/* Here, mapping could be implicitly done without using #Column because
** database column name and POJO property is same but it stays empty if I
** ignore #Column */
#Column(name = "hello_world")
private Long helloWorld;
}
Lastly, If I completely remove #Column from POJO's properties, helloWorld property is filled (implicitly) but myfieldAb remains NULL (because mapping is not found as expected).
Below is sample query:
dslContext.select()
.from(SOMETHING)
.where(SOMETHING.NAME.eq("Something"))
.fetchInto(TestClassDto.class)
As of jOOQ 3.15, you either have to annotate
all of your attributes...
none of your attributes...
... with the #Column annotation. There's a pending feature request to mimick JPA more closely and make the #Column annotation optional for some attributes: https://github.com/jOOQ/jOOQ/issues/4586.
In the meantime, instead of using those JPA annotations, you could add auxiliary getters/setters for your column:
public void setFieldAbXyz(Long v) {
this.myfieldAB = v;
}
public Long getFieldAbXyz() {
return myfieldAB;
}
I have an indexed entity, like below :
#MappedSuperclass
public static class Model{
#Id
#GeneratedValue(strategy=GenerationType.Identity)
private Integer id;
private boolean isDeleted;
}
and the indexed class is :
#Entity
#Table("USERS")
#Indexed
public class ProductModel extends Model{
#Field
private String name;
//getters & setters
}
Well, when I do a research on ProductModel, I get the value of the flag isDeleted while its not annotated with #Field.
I'm asking if this is a normal behavior, does Hibernate-search Index the whole Object Or does it fetch the missing data from data base, I need an explanation for this behavior please.
Hibernate Search only stores in the index the fields you declare explicitly (more precisely, it indexes by default and you can ask Hibernate Search to store it by adding the store option to your #Field annotation).
What you observe is that Hibernate Search hydrates the objects with the information of the database after having performed the search. This is one of the main interest in using Hibernate Search: the objects returned are managed entities.
I have been following an excellent guide for generating pojos from a mysql database using hibernate. One can find the guide here for reference:
Generate pojos with hibernate
I am getting pojos which have fields that embed other objects when a foreign key was present. For example, user's have addresses. Hibernate is generating something like the following:
public class User(){
private String name;
private Integer uid;
private Address address;
}
I have a problem, though, in that I want the classes to actually contain the foreign key value. For example, I want the User object to have a class field corresponding to the database field for addressId. So, I want the object to actually look something like this:
public class User(){
private String name;
private Integer uid;
private Integer addressId;
private Address address;
}
Does anyone know how to modify the hibernate code generation process so as to include foreign key values as fields on the object?
Update:
I found a SO post which describes how to ignore the foreign key relationships and just get foreign keys as class fields: How to ignore foreign keys?
The problem here is that I want both. I don't want to ignore the relationships. I want them represented, but I also want the actual foreign key values.
Update:
Let me be more specific as to why I want this solution. We are trying to serialize these hibernate objects. Now, we have a lot of different hibernate pojos which are being reverse engineered. We do not want to manually write a serialization routine for every class. We would have to do that if we followed the convention of "just manually write an access method to the foreign key field on the embedded object". Further, even if we were to do so, the pojo still doesn't know what the field of the foreign key is called. Instead, we are using gson with a type adaptor.
With gson, we are serializing all fields on the pojo and just ignoring fields that contain a hibernate object. The problem, of course, is that we don't have the foreign key fields. We need a few pieces of information here in order to generically serialize any hibernate pojo. We need to know:
The foreign key field name
The foreign key field value
Your approach violates Hibernate convention. Because Hibernate uses reflection, convention is essential for Hibernate to do it's job. Because of this, I suspect Maouven's "follow the convention" approach is easiest. However, if it is non-negotiable, you have two options available.
Your first option is to add a transient getter, to expose the getAddressId() function.
public class User() {
private String name;
private Integer uid;
private Address address;
// Getters, setters...
#Transient
public boolean getAddressId() {
address.getId();
}
}
Your second option is to add a Data Access layer to impose your own conventions on top of Hibernate objects. This layer of abstraction will not be bound by Hibernate's conventions. This way, your POJOs will be wrapped by DAOs (Data Access Objects), which you can design as you see fit.
Update:
Given your unique case, consider modifying your serialization step. GSON normally can't use transient methods, but there is an extension that can do this, as shown here.
Another solution would be to use reflection to copy the object the way you want it, and then use GSON to serialize the copied object.
Your approach will cause redundancy in the class's data. In the first bunch of code -generated by Hibernate-, you can get the addressId you need from the Address property of the User Class :
yourUser.getAddress().getAddressId();
Two possible (theoretically speaking) solutions, but require manual refactoring after reverse engineering by Hibernate Tools:
I'm using annotations just for brevity
1) expose the column with mapping:
#Entity
class User
{
#Id
#Column
private Integer uid;
#Column
private String name;
#Column(name = "ADDRESS_ID", insertable = false, updatable = false)
private Integer addressId;
#ManyToOne
#JoinColumn(name = "ADDRESS_ID")
private Address address;
}
2) use #Transient + #PostLoad:
#Entity
class User
{
#Id
#Column
private Integer uid;
#Column
private String name;
#Transient
private Integer addressId;
#ManyToOne
#JoinColumn(name = "ADDRESS_ID")
private Address address;
#PostLoad
public void postLoad()
{
addressId = Optional.ofNullable(address).map(Address::getId).orElse(null);
}
}
Another solution could be possible using JSON marshaller for JAXB:
#XmlRootElement
class User
{
#XmlID
private Integer uid;
private String name;
#XmlIDREF
private Address address;
}
You can find a quickstart here
I have something like this :
class A :
#Entity
#Indexed
public class A {
#Fields({
#Field(name="a"....)
#Field(name="b"....)
)}
private String someField;
....
}
}
And class B:
#Entity
#Indexed
public class B {
#IndexedEmbedded
#ManyToOne
private A a;
......
}
I would like to use #Field 'a' when indexing etity 'A' and #Field 'b' when indexing entity 'b' ! Is it possible to do that ?
Because lucene index for the class 'B' contains the same field twice (a.someString) but I don't need that, I need just one field for this class.
It is not possible by just using annotations. One solution would be to write a custom field bridge for the many-to-one association a in class B. By writing a custom field bridge you can control yourself which fields you want to index for an instance of type A. The disadvantage of course is that you have to manage the indexing of all properties yourself.
The more important question imo is, why you want this conditional indexing? Do you have a specific problem? I don't think that adding both fields in both cases will affect your search performance. At most your index gets a bit bigger, but unless you are hitting some actual problem/barrier I would not be concerned about this.
UPDATE:
Actually, there is a feature you could use to control this. You can use the includePaths property of #IndexedEmbedded allowing you to explicitly control which fields get added to the index. So in your case:
#Entity
#Indexed
public class B {
#IndexedEmbedded(includePaths="a.b")
#ManyToOne
private A a;
......
}
We have a requirement that every fields of the object must be validated in a special order.
For example, we have Person object like below:
public class Person {
#NotNull
private String firstName;
#NotNull
private String lastName;
// getter and setter
}
When I use the javax.validation.Validator to validate this object, we need to make sure that the firstName always be validated first and then lastName. Is there any way for hibernate validator archive that requirement?
You want to use group sequences. In particular you probably want to redefine the default group for your entity. See also Redefining the Default group for a class as defined by the Bean Validation specification .