I'm having difficulty adding index fields to embedded objects using hibernate search.
I have a simple example whereby a Company can have many CompanyAddress(es) - example of my setup is shown below:
Company.java
#Data
#Entity
#Table(name="COMPANY")
#Indexed
public class Company implements Serializable {
...
#OneToMany(mappedBy="company", fetch=FetchType.LAZY,
cascade=CascadeType.ALL, orphanRemoval = true)
#JsonManagedReference
#IndexedEmbedded(depth=1, includePaths={"postalCode"})
private Set<CompanyAddress> address;
...
}
CompanyAddress.java
#Data
#NoArgsConstructor
#Entity
#Table(name="COMPANY_ADDRESS")
#Indexed
public class CompanyAddress implements Serializable {
#ManyToOne
#JoinColumn(name="company_id", referencedColumnName = "id")
#JsonBackReference
#ContainedIn
private Company company;
#Column(name="POSTAL_CODE", length=10)
private String postalCode;
}
When I try to index I get the following error:
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.search.exception.SearchException: HSEARCH000216: Found invalid #IndexedEmbedded->paths elements configured for member 'address' of class 'com.example.model.Company'. The invalid paths are [address.postalCode]
Now if I swap the #Contained and #IndexedEmbedded to be on the address object I can index and find companies from addresses however I would wish to be able to include address fields in the Company index.
I'm using hibernate search 5.11.11.Final.
Any guidance would be much appreciated.
Ok I solved this - adding an #Field annotation to the postalCode attribute meant the field was indexed and the error didn't occur.
Hopefully this will be useful for anyone else with similar problems.
Related
I am using Spring Boot and Jackson and Hibernate to create an API. Hibernate connects to a MySQL database.
I understand the good practices but I'm stuck on a particular point.
I have an n:m relationship that contains an extra field.
Ex: Author(id, ...) -> Written(idAuthor, idBook, date) <- Book(id, ...)
I understand how to map a traditional n:m relationship, but this technique does not apply to me this time.
For this, I found a source on the internet that showed the solution: create an intermediate class in my code that contains an Author type object and a Book type object + my additional fields.
#Entity
#Table(name = "Author")
public class Author implements Serializable {
/...
#Id
#GeneratedValue
private int id;
#OneToMany(mappedBy = "author", cascade = CascadeType.ALL)
private Set<Written> written= new HashSet<>();
/...
}
#Entity
#Table(name = "Book")
public class Book implements Serializable{
/...
#Id
#GeneratedValue
private int id;
#OneToMany(mappedBy = "book", cascade = CascadeType.ALL)
private Set<Written> written= new HashSet<>();
/...
}
public class Written implements Serializable {
#Id
#ManyToOne
#JoinColumn(name = "idAuthor")
private Author author;
#Id
#ManyToOne
#JoinColumn(name = "idBook")
private Book book;
//Extra fields ....
}
That's a bidirectional link.
With this code, I get an infinite recursivity error:
Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: java.util.ArrayList[0]->com.exampleAPI.api.model.Book["written"])]
I tried to use #JsonIgnore, #JsonManagedReference and #JsonBackReference on the Written class, also tried to use transient keyword, but nothing worked.
I can't find any source on the internet that could help me, and neither can the documentation for this particular case.
Can someone help me?
When unhandled bidirectional relationship occurs, Jackson faces infinite recursion.
I tried to use #JsonIgnore, #JsonManagedReference and #JsonBackReference on the Written class
You need to use #JsonManagedReference and #JsonBackReference annotations separately to prevent these cycles between Book and Written. A side note, transient has nothing to do with the persistence but the serialization. JPA works with the #Transient annotation.
public class Book implements Serializable {
#OneToMany(mappedBy = "book", cascade = CascadeType.ALL)
#JsonBackReference
private Set<Written> written= new HashSet<>();
...
}
public class Written implements Serializable {
#Id
#ManyToOne
#JoinColumn(name = "idBook")
#JsonManagedReference
private Book book;
...
}
Important: Don't send database entities through REST (probably what you are up to do). Better create a DAO object without bidirectional relationship and map entities into DAOs. There are several libraries able to do that: I highly recommend MapStruct, however ModelMapper is also an option. If there is a lower number of such entities, using constructors/getters/setters would be enough.
I want to make hibernate query from pojo class, but pojo class uses mappedBy. I don't know how can I make proper query.
Already I have tried many ideas, like ts.clientAccount.clientAccountMapping.id but it gives error. clientAccountMapping is mapped in clientAccount pojo
first class
public class Transaction{
#ManyToOne
#JoinColumn
private ClientAccount clientAccount;
}
second class
public class ClientAccount{
#JsonIgnore
#OneToMany(mappedBy = "clientAccount", cascade = CascadeType.ALL)
private Set<ClientAccountMapping> clientAccountMapping;
}
third class
public class ClientAccountMapping{
#Id
#GeneratedValue(generator="system-uuid")
#GenericGenerator(name="system-uuid", strategy = "uuid")
private String id;
}
Always my compiler gives the following exception:
org.hibernate.QueryException: illegal attempt to dereference collection [transactio0_.idtransactio0_.clientAccount_accountIdclientAccount.clientAccountMapping]
you have to use join here. like : From ClientAccount c join c.clientAccountMapping
Reference : https://docs.jboss.org/hibernate/core/3.3/reference/en/html/queryhql.html
I'm trying to implement a Repository to work with Views. The fact is that I'm trying to use the SimpleJpaRepository implementation, but I'm getting a lot of errors on execution time because my DTO is not an #Entity. It is only a #Table, and it seems that this kind of elements are not mapped into the Metamodel of JPA.
This is my DTO:
#Table(name = "v_language")
public class VLanguage {
#Column(name = "isocode")
private String isocode;
#Column(name = "name")
private String name;
#Column(name = "isdefault")
private String isdefault;
// getters and setters
...
}
I tried to define a customized base repository with minimal functionality (only a findAll() method) with the same implementation of SimpleJpaRepository, but when building the Query it fails when doing:
Root<U> root = query.from(domainClass);
With this exception:
Caused by: java.lang.IllegalArgumentException: Not an entity: class es.prodevelop.pui.common.jpa.model.views.dto.VLanguage
at org.hibernate.jpa.internal.metamodel.MetamodelImpl.entity(MetamodelImpl.java:194)
at org.hibernate.jpa.criteria.QueryStructure.from(QueryStructure.java:124)
at org.hibernate.jpa.criteria.CriteriaQueryImpl.from(CriteriaQueryImpl.java:156)
at es.prodevelop.pui.common.jpa.configuration.AbstractRepository.applySpecificationToCriteria(AbstractRepository.java:213)
at es.prodevelop.pui.common.jpa.configuration.AbstractRepository.getQuery(AbstractRepository.java:174)
at es.prodevelop.pui.common.jpa.configuration.AbstractRepository.findAll(AbstractRepository.java:151)
...
Does anybody know how to solve it?
you are missing the #Entity annotation.
please annotate your class and try again.
I am getting an error when using an Oracle DB and Spring Data. The error is:
ORA-00942: table or view does not exist
The cause of this error is that the user I am connecting with does not have access to the tables in the schemas I wish to connect to.
I read that 2 fixes to this are to create synonyms in my database or to specify the schema that each entity/table belongs to.
I am going to try the Schema approach first. How do I do so?
My example entity below, a Dog in the Vet Schema:
#Entity
#Table(name = "Dog")
public class Dog
{
#Id
private String id;
#Column(name = "NAME")
private String name;
#Column(name = "Owner")
private String owner;
//getters and setters etc...
The #Table annotation provides the schema attribute:
#Table(name = "Dog", schema = "Vet")
You must prefix your tables with the schema name and with a . inbetween them:
#Table(name = "VET.Dog")
I'm attempting to build an application level view with Spring JPA. I'm also using lombok.
There is an existing client already using this web service which can't be changed at this time.
We have a new client which needs the same data and even more now. So I thought this could
be addressed with an application level view so to speak.
The basic scope of the problem is I have 3 entities: A, B and C.
A and C are entities pointed at the same table. C has more properties than A.
Both C and A have references to B.
#Entity
#Getter
#Setter
#Table(name="Foo", schema="dbz")
public class A {
#Id
#Column(name="FOO_I")
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#OneToMany(fetch =FetchType.EAGER, cascade= CascadeType.ALL)
#JoinColumn(name="FOO_I",nullable=false)
private Set<B> items = new HashSet<B>();
#Column(name="X")
private String x;
}
#Entity
#Getter
#Setter
#Table(name="Bar", schema="dbz")
public class B {
#Id
#Column(name="BAR_I")
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Column(name="Y")
private String y;
#Column(name="Z")
private int z;
}
#Entity
#Getter
#Setter
#Table(name="Foo", schema="dbz")
public class C {
#Id
#Column(name="FOO_I")
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#OneToMany(fetch =FetchType.EAGER, cascade= CascadeType.ALL)
#JoinColumn(name="FOO_I",nullable=false)
private Set<B> items = new HashSet<B>();
#Column(name="X")
private String x;
#Column(name="MoreData")
private String moreData;
//And much more other data...
}
When I comment out the #Entity and #Table on class C and rebuild, I don't get an exception in my validation tests.
When I leave the #Entity and #Table annotations on class C, I get the following exception:
Caused by: org.hibernate.MappingException: Duplicate property mapping of _items_FOO_IBackref found in com.acme.Bar
If I rename items to bars in C, then I get the following exception:
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: com.acme.Bar column: FOO_I (should be mapped with insert="false" update="false")
Is there any way to get hibernate to accept 2 java classes backed by the same table which relate to another entity? I'm not sure if I am missing something here or if this is a framework limitation.
You are using component mapping so use #Embedded annotation for the A class without using #Entity, #Id and #Table annotations here is a useful link;
http://www.dzone.com/tutorials/java/hibernate/hibernate-example/hibernate-mapping-component-using-annotations-1.html