I would like to query audit entity in my JPA environment.
At first I do AuditQuery and it works well, but now I need more advance query witch I can't do with AuditQuery.
Now I need something like
this.em.createQuery("FROM ENTITY_AUD").getResultList();
but I get error :
QuerySyntaxException: ENTITY_AUD is not mapped [ENTITY_AUD]
I understand that this is due that I don't have entity with all properties, but I don't want to have entity because it is audit entity.
Is there a way around it? For me it would be ok to get List of Object.
You can always create native SQL query in JPA. Replace createQuery with createNativeQuery in your code:
List<Object[]> list =
this.em.createNativeQuery("SELECT * FROM ENTITY_AUD").getResultList();
Add a NamedQuery in your Audit class
#Entity
#Table(name = "ENTITY_AUD")
#NamedQueries({
#NamedQuery(name = "Audit.findAll", query = "SELECT a FROM Audit a")})
public class Audit implements Serializable {
...
}
then use the named query
List<Audit> auditList = entityManager.createNamedQuery("Audit.findAll").getResultList();
Read : Implementing a JPA Named Query
Related
I have a project to do integration with snowflake database using ORM like JPA/Hibernate
but for the resultset from snowflakes always returns fields in UPPERCASE which conflicts with JPQL default behevior.
Example below is a select query using JPQL as you can see all fields are in lowercase
select podioitem0_.ID as id1_0_0_, podioitem0_.JSON as json2_0_0_ from INLIFE_MARK.PUBLIC.podio_item podioitem0_ where podioitem0_.ID=?
The Resultset from snowflake returns Uppercase columns
Given the samples above I get this error
o.h.engine.jdbc.spi.SqlExceptionHelper : Column not found: json2_0_0_
Its because when trying to map json2_0_0_ column from resultset the mapper cant find it because the columns from resultset are on uppercase.
So Question, is there a way to tell JPQL or jpa/hibernate to generate the JPQL query in Uppercase? at least for the column names so I hope it would look like this?
select podioitem0_.ID as ID1_0_0_, podioitem0_.JSON as JSON2_0_0_ from INLIFE_MARK.PUBLIC.podio_item podioitem0_ where podioitem0_.ID=?
Additional details below
properties
spring.jpa.show-sql=true
spring.jpa.database=SQL_SERVER
spring.jpa.hibernate.ddl-auto=none
spring.jpa.hibernate.naming.implicit-
strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl
spring.jpa.hibernate.naming.physical-
strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.SQLServerDialect
Sample Entity Class
#ToString
#Entity
#Table(schema = "PUBLIC", catalog = "INLIFE_MARK", name = "podio_item")
public class PodioItem {
#Id
#Column(name = "id")
public Long id;
#Column(name = "json", columnDefinition="varbinary")
public byte[] json;
}
I am using CrudRepository to save and find objects
#Repository
public interface PodioItemRepository extends
CrudRepository<PodioItem, Long> {
}
I was hoping maybe somekind of property as a solution but any suggestion is welcome.
Please see: How to add quotes to aliases in generated sql via Hibernate?
Just add &CLIENT_RESULT_COLUMN_CASE_INSENSITIVE=true to your snowflake connection string.
I have an entity with a lot of attributes, relationships inside. In a few cases I just need 2 simple attributes, not the rest. I tried using entity graphs, but I always get the complete entries, with all attributs, relationships...
The entity graph in my EECase-entity:
#NamedQueries({
#NamedQuery(name = EECase.QUERY_ALLCASES, query = "SELECT DISTINCT c FROM EECase c")
})
#NamedEntityGraph(name = "Case.forDropdown", attributeNodes = {
#NamedAttributeNode("caseNumber"),
#NamedAttributeNode("firstNames"),
#NamedAttributeNode("lastName")
})
In my bean I try to get the filtered cases with:
public List<EECase> getCasesForDropdown() {
TypedQuery<EECase> query = getManager().createNamedQuery(EECase.QUERY_ALLCASES, EECase.class);
EntityGraph<EECase> graph = (EntityGraph<EECase>) getManager().getEntityGraph("Case.forDropdown");
query.setHint("javax.persistence.fetchgraph", graph);
List<EECase> queryEntity = (List<EECase>) query.getResultList();
return queryEntity;
}
It seems the setHint is getting ignored?
Even if you define a hint, its still an optional thing.
I would suggest a small alternative in the form of a result class in the select being a projection (advised option if you do not plan to update the entity afterwards):
#NamedQueries({
#NamedQuery(name = EECase.QUERY_ALLCASES
, query = "SELECT new com.domain.EECase(c.caseNumber, c.firstName, c.lastName)
FROM EECase c")
})
Keep in mind to place a proper constructor to accept the columns of the projection in a given order.
You can also use a separate POJO to map the results of that query. Not necessarily the entity class itself.
Also keep in mind that you wont be able to select entire dependent entity.. only plain attributes (i assumed that is the case).
I am using Spring JPA and in order to ad a List of String to my Entity I am using #ElementCollection as below.
#ElementCollection
private Map<Integer, String> categories;
When I use this it generates a table called subscription_categories this contains the following columns subscription(varchar), catergories(varchar) and caterogies_key (int)
If I use my SQL tool on my desktop I can query this table fine with the following
select `subscription_categories`.`subscription` from `subscription_categories` where `subscription_categories`.`categories`='TESTING';
However, when I attempt to use this in Spring Data it fails with a "... not mapped" error
Here are a few attempts below:
#Query("select s.subscription from subscription_categories s where s.categories = ?1")
List<Subscription> findUsernameByCategory(String category);
#Query("select s.subscription from categories s where s.categories = ?1")
List<Subscription> findUsernameByCategory(String category);
Both return the same error.
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException:
categories is not mapped
My question is this:
How can I query the table created by the #ElementCollection?
You can't directly query from #ElementCollection. You should query base entity (I assume its name is Subscription).
#Query("select s from Subscription s where s.categories = ?1")
List<Subscription> findUsernameByCategory(String category);
If you want query by key, then use
#Query("select s from Subscription s where index(s.categories) = ?1")
List<Subscription> findUsernameByCategoryKey(Integer key);
I'd also side with #talex on this and argue that you need to base your query on the parent/container/base object of the #ElementCollection.
In my experience following query should suffice:
#Query("select category from Subscription subscription inner join subscription.categories category")
Side-note: Querying subscription_categories seems to be the wrong path, since this table is part of a different layer (the database layer in Sql/Jpql), while the query should be formed on the Hibernate layer (hql), which uses your entity/class-names as references.
I have used Upper-case class names, instead of lower-case table names.
I have a named query as below;
#NamedQuery(name = "MyEntityClass.findSomething", query = "SELECT item FROM MyTable mytbl")
Now I want to append dynamic sort clause to this query (based on UI parameters)
Can I get an example using JPQL for doing the same (like how to set a dynamic ORDER BY in the Entity class)
I have already tried using CriteriaQuery, but was looking for a JPQL implementation now.
NamedQueries are by definition NOT dynamic, it is not correct to change them programmatically.
So the way to go is to create a JPQL query (but not a named query) like this:
TypedQuery<MyEntity> query = em.createdQuery("SELECT item FROM MyEntity item ORDER BY "+sortingCol, MyEntity.class);
On the other hand, if you REALLY want to use the named query, you could do that the following way:
#NamedQuery(name = "MyEntityClass.findSomething", query = MyEntity.NAMED_QUERY)
#Entity
public class MyEntity {
public static final NAMED_QUERY= "SELECT item FROM MyTable mytbl";
//+your persistent fields/properties...
}
//and later in your code
TypedQuery<MyEntity> query = entityManager.createQuery(MyEntity.NAMED_QUERY + " ORDER BY " + sortingCol, MyEntity.class);
Complementing for JPA 2.1
As of JPA 2.1 it is possible to define named queries programmatically.
This can be achieved using entityManagerFactory.addNamedQuery(String name, Query).
Example:
Query q = this.em.createQuery("SELECT a FROM Book b JOIN b.authors a WHERE b.title LIKE :title GROUP BY a");
this.em.getEntityManagerFactory().addNamedQuery("selectAuthorOfBook", q);
// then use like any namedQuery
Reference here
This can be useful, for instance, if you have the orderby field defined as a application parameter. So, when the application starts up or on the first run of the query, you could define the NamedQuery with the defined OrderBy field.
On the other side, if your OrderBy can be changed anytime (or changes a lot), then you need dynamic queries instead of NamedQuery (static). It would not worth to (re)create a NamedQuery every time (by performance).
#NamedQuery
Persistence Provider converts the named queries from JPQL to SQL at deployment time.
Until now, there is no feature to create/update the query with #NamedQuery annotation at runtime.
On the other hand, you can use Reflection API, to change the annotation value at runtime. I think It is not solution, also it is not you wanted .
em.createQuery()
Persistence Provider converts the dynamic queries from JPQL to SQL every time it is invoked.
The main advantage of using dynamic queries is that the query can be created based on the user inputs.
I have just recently decided to redesign my database and I used annotated objects instead of hbm files. The problem is that now I am unable to build a configuration in order to check my queries. Any ideas?
edit: By hibernate perspective I mean the Hibernate Console Perspective you can find in 3.9.1 of the following link:
http://docs.jboss.org/tools/2.1.0.Beta1/hibernatetools/html/plugins.html
You can define named queries like this
#Entity
#Table(name = "yourTable")
#NamedNativeQueries(value = {
#NamedNativeQuery(name="nativeSelectName",
query = "select blah blah blah", resultClass = YourEntityClass.class)
})
#NamedQueries(value = {
#NamedQuery(name = "hqlQuery",
query = "from YourEntityClass where ...")