Selecting native collections defined with #ElementCollection from Entities in JPA - jpa

Let's suppose we have an Entity of this type:
#Entity
#Table(name="User")
public class User {
#Id
long id;
#ElementCollection
List<String> phones;
}
My goal is to have the complete list of phones, for all users, something like: "SELECT x.phones FROM User x"
I tried to build a Spring Data JPA query of this kind:
#Query("SELECT x.phones FROM User x")
List<String> findAllPhones();
But I get this exception:
org.hibernate.QueryException: not an entity
at org.hibernate.hql.internal.ast.tree.FromElementType.renderIdentifierSelect(FromElementType.java:188)
I had to resort to a native sql query to solve the problem.
Otherwise I have to wrap the phone number inside a new Entity, but I exactly want to avoid that.
Is there any way to solve this kind of problem using plain JPA or (even better) only Spring Data JPA methods?

Related

Spring data jpa querydsl projection with joins

I'd like to optimize a queryDSL + Spring data query. Currently I am using a BooleanBuilder as the predicate, which would be fine, but it joins too many tables. I don't need all the columns from the tables and I don't need some of the tables at all. I believe using a projection would reduce the number of tables joined.
I tried with using a Projections.bean() and also with extending MappingProjection, but both approaches result in not using joins but selecting from multiple tables which results in less rows than what's needed.
My data structure consists of a Booking entity and some related entites like User, so looks something like the following:
#Entity
public class Booking {
#ManyToOne
#JoinColumn(name = "userId", nullable = false)
private User endUser;
}
#Entity
public class User {
#OneToMany(cascade = CascadeType.ALL, mappedBy = "endUser", fetch = FetchType.LAZY)
private List<Booking> bookings;
}
I implemented a custom queryDSL projection repository as described here: Spring Data JPA and Querydsl to fetch subset of columns using bean/constructor projection
I'm trying a projection like the following:
Projections.bean(Booking.class,
booking.uuid,
Projections.bean(User.class,
booking.endUser.uuid
).as(booking.endUser.getMetadata().getName()
);
The sql generated by the current solution looks something like this:
select (...)
from booking booking0_,
user user12_
where booking0_.user_id=user12_.id
So, how can I make QueryDSL join the tables instead of selecting from all of them?
Am I on the right path to try to optimize the query? Does the projection make sense?
I ended up creating a DB view, making an Entity for it and then querying that with querydsl. This is really simple, straightforward and the performance is good too.
This is probably where ORMs are just not capable enough.

How to retrieve nested data in JPQL?

working with OpenJPA2 persistence. I have a very simple entity class, that does have a String property and a List property. I do persist its instances flawlessly with the nested List (in a JSF2 web project). I check the database and there appears two tables (I use automatic schema generation), one for the entity itself, and other table for the nested List. All data persisted using EntityManager is stored fine on both tables.
Problem is I cannot retrieve nested data. I mean, I do a Query for getting all instances of the entity, but the List of all instances come empty.
(DB Engine is MySQL. ORM is OpenJPA2. Server is TomEE 1.6. IDE is Netbeans 8. I use automatic schema generation, so I DO NOT WANT to design the database tables, and I DO WANT to let the ORM create the tables, so I can work purely with objects and forget about DB.)
following is Entity Class code:
#Entity
public class Cliente implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String nombre;
#ElementCollection
private List<String> emails = new ArrayList<String>();
// getters and setters omitted for brevity.
It does have an associated Facade Class, which is ClienteFacade. It includes the getAll method which uses a JPQL Query.
public List<Cliente> listaClientes(){
Query query = em.createQuery("SELECT c FROM Cliente c");
return query.getResultList(); }
Problem is, I get all instances of the entity in a List, but all lists of List emails come out empty. I think problem may be in the JPQL query. Still trying to learn JPQL with some difficulty... so please, How can I retrieve the nested data with JPQL?
Many thanks!
Try #ElementCollection(fetch = FetchType.EAGER) because the default type is lazy. That means that the lists are not loaded directly.

Spring Data JPA finder for dynamic fields as Map

My requirement is to have few custom fields in the domain objects. These fields may vary as per the clients.
We are using Spring Data JPA to execute finders. Spring data implicitly provides finders for static fields of the domain and can also handle finders for the fields in the object graph.
I want to know if there is a way to find data on the custom fields? Can someone suggest me a strategy to achieve the same. Below is the sample of my domain class.
public class Employee{
private String name;
private String age;
private Map customeFields; (May vary as per client)
}
I was thinking of overriding QueryLookupStrategy and create my CustomJpaQuery on lines of PartTreeJpaQuery to achieve it. Is there any better approach? Does spring data jpa provides an easy mechanism to override query creation mechanism?
If you are using hibernate (not sure about other JPA implementations) you may add methods with #Query annotations like this:
#Query("select e from Employee as e where e.customeFields[:key] = :value")
List<Employee> findSomeHow(#Param("key") String key, #Param("value") String value)

Does Hibernate Search load entity associations and can I mix free text queries with native SQL?

package example;
...
#Entity
#Indexed
public class Book {
#Id
#GeneratedValue
private Integer id;
#Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
private String title;
#Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
private String subtitle;
#Field(index = Index.YES, analyze=Analyze.NO, store = Store.YES)
#DateBridge(resolution = Resolution.DAY)
private Date publicationDate;
#IndexedEmbedded
#ManyToMany
private Set<Author> authors = new HashSet<Author>();
#OneToMany(mappedBy="book")
List<BookPages> bookPages;
}
1) If the search result is of type Book.class does the result contain #ManyToOne objects (bookPages) or do I have to load them separately? Because I need them for showing the result.
2) Is it possible to add a native sql clause to the search? Because I need to limit the result and for that I have to JOIN another table which is not declared in Book.class.
That is a basic Hibernate ORM question, not related to Hibernate Search. Yes you can always navigate from one entity to its relations by just invoking the getter / accessing the fields: depending on your (configurable) fetch strategy it will either have the relation preloaded in "one shot" when loading the main entity (likely with a JOIN) or fetch it transparently on demand. This configuration is however not have any effect on functionality, more a performance tuning option.
No you can't mix SQL with an Hibernate Search (Fulltext) query; what you can do is to expose the needed data from the other table in the mapping - which would be a cleaner mapping anyway - and then use the Hibernate Search annotations to make sure all fields you need are indexed as well, so that you can include the restrictions in the FullTextQuery directly; fill perform much faster as well than any SQL.
It is not possible to mix native SQL with hibernate search query, as there is no way to intersect the results from both queries without iterating on at least one of the results.
See the documentation reference about this exact question.
Hibernate Search - FAQ - Can I mix HQL and Lucene queries?
http://hibernate.org/search/faq/

JPA Error compiling query when using Oracle objects within a query

The following JPA query doesn't compile -
SELECT a FROM CUSTOMER a WHERE a.activeCustomer = 'N' AND a.customerInfo.city IN :cityName ORDER BY a.customerId
where the table CUSTOMER in Oracle database has a base type - CUSTOMERINFO which in turn has various values such as -
city
country
This base type CUSTOMERINFO is extended by LOCALBUSINESSCUSTOMERINFO and MNCBUSINESSCUSTOMERINFO and a few others.
I think this may be due to the fact that when I define the column in my entity I define it as follows -
#Entity
#Table(name = "CUSTOMER", schema = "DBA")
#Converter(name="CustomerInfoConvertor", converterClass=CustomerInfoConvertor.class)
public class Customer implements Serializable {
#Basic
#Convert("CustomerInfoConvertor")
#Column(columnDefinition = "CUSTOMERINFO")
private ICustomerInfo customerInfo;
}
I have tried this query using SQL and it works fine but using it from JPA (JPQL) throws compilation error.
Thanks for your help!
You have mapped your customerInfo as a basic, so it is a basic in JPQL.
The column is of an Object object type?
In EclipseLink 2.3 you can map this as an Embeddable and the #Struct annotation, and use an Embedded mapping from the Customer. Does the customer table have other columns or is it a type table? If it is a type table, then use the #Struct to map it.