Excluding a bean's field in Hibernate criteria result - java

Here is how I'm getting my User beans from Database.
session.createCriteria(User.class).list();
That returns all of User records from database. Interesting part is that, I don't want to get the password field from DB. Just want to exclude that field while retrieving.
Options I have
1) using projections on other fields. That needs to be more code to add in to projections list. So dropped from that idea.
2) With Sql I need to write a manually query, which kills the theme of Hibernate.
Any possibility to exclude a column value of Bean ?

you can try:
Example example = Example.create(cat)
.excludeZeroes() //exclude zero valued properties
.excludeProperty("color") //exclude the property named "color"
.ignoreCase() //perform case insensitive string comparisons
.enableLike(); //use like for string comparisons
List results = session.createCriteria(Cat.class)
.add(example)
.list();
Reference :-
http://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/querycriteria.html#querycriteria-examples
http://docs.jboss.org/hibernate/orm/3.6/javadocs/org/hibernate/criterion/Example.html

Let's assume that following is your POJO:
User.java
private long id;
private String fName;
private String lName;
// getter - setter of all fields
Now suppose you want to get only id & fName fields and not lName.
Apart from the two approaches you've described, there's also a third way to achieve this, which uses HQL.
Query q1 = session.createQuery("Select new User(id, fName) from User");
List<User> users = q1.list();
Modify User.java to have another constructor as follows:
public User(long id, String fName)
{
this.id = id;
this.fName = fName;
}
In short, whatever fields you want to retrieve, you can list them in the constructor as well as in the query.
Hope this helps.

Related

how to make values of column in entity class as lower case while storing using Annotation

I want an entity class through which I can store data to DB, for
specific columns I want in case-sensitive, is there any annotation to
be used above these specific columns to store as requested? please let
me if the question is not clear,Thanks in advance.
#Column(name = "EMAIL",unique=true) //i want store this email id as lower case,
private String email; //never mind in what case user enters
You can do this using #ColumnTransformer
#Column(name = "email")
#ColumnTransformer(write = "LOWER(email)")
private String email;
I try this and it works:
#Column
#ColumnTransformer(write = "LOWER(?)")
private String email;
expression of #ColumnTransformer.write would replace the original "?" placeholder in persisting sql statement. So must provide a compliant-sql expression with "?":
insert into member (email) values (?)
---->
insert into member (email) values (LOWER(?))
detail usage: https://docs.jboss.org/hibernate/orm/5.4/javadocs/org/hibernate/annotations/ColumnTransformer.html

Morphia multi field sort not working for phone book-like sorting

I have a simple document like this:
#Entity("users")
#Indexes(#Index(fields = {#Field("lastName"), #Field("firstName")}))
public class User extends Model {
#Indexed public String email;
public String firstName;
#Indexed public String lastName;
public String employer;
}
Then there is a search function to find entries either on name (first/last) and/or employer.
The goal is to sort the results by last name then first name, entirely like how a phone book is presented.
My search query looks like:
q.field("employer").containsIgnoreCase(input);
q.order("lastName,firstName");
q.limit(25);
q.offset(start);
Now what's happening is the results are being sorted by the first field specified in the q.order() line, but what's not happening is sorting on the lastName and firstName.
As i understand sorting on multiple columns, there needs to be a compound index, which i do have defined for this collection. So i'm just at a miss as to what i'm missing.
I use Datastore Morphia class and the sorting works perfect
List<Page> result = datastore.find(Page.class)
.field("isFeatured").equal(true)
.order("parseDate, parsePriority").limit(limit).asList();

Filter collection by multiple attributes of its elements - QueryDSL

I am working on a dynamic filter component based on QueryDSL with the use of SpringData for query execution. Thus I create Predicate instances from the received data ad pass it to QueryDslPredicateExecutor. For dynamic access to entity attributes I use generic PathBuilder typed to the entity class.
Consider the following (simplified) code:
class Offer {
List<LanguageToName> names;
}
class LanguageToName {
String name;
String language;
}
When I try to query Offer entites, that have in their collection name element with attribute 'abc', I simply create the predicate as follows:
pathBuilder.getCollection("names", LanguageToName.class).any().getString("name")
.like("%" + fieldData.getFieldValue() + "%");
However, I was unable to come up with a solution to filter the collection by multiple attributes of the containing objects with the use of PathBuilder. When I append the code above with .and() and access the collection again via the pathBuilder variable, I naturally get the result equivalent to appending sql query with AND EXISTS..., which is not the desired result. I also tried to use getCollection().contains(), but I was unable to create the Expression<LanguageToName> that would describe such case.
Is there a way to create a Predicate that would filter entities by multiple attributes of the elements from a collection, that is a field of the queried entity?
I had similar issue and finally solved this with subquery (however, it seems to me that it works only for 1 level of nestedness).
My initial predicate was (it was making 2 independent sub-queries):
Predicate predicate = codeTable.customer.id.eq(customerId)
.and(codeTable.qualifierResults.any().customerQualifier.type.eq("TARGET_TYPE"))
.and(codeTable.qualifierResults.any().customerQualifier.referenceType.code.eq("TARGET_CODE"));
But the correct predicate that I ended up with was:
BooleanExpression customerQualifierCondition = JPAExpressions
.selectFrom(codeTableQualifierResult)
.where(codeTableQualifierResult.in(codeTable.qualifierResults),
codeTableQualifierResult.customerQualifier.type.eq("TARGET_TYPE"),
codeTableQualifierResult.customerQualifier.referenceType.code.eq("TARGET_CODE"))
.exists();
Predicate predicate = codeTable.customer.id.eq(customerId).and(customerQualifierCondition);
The idea is to write 1 separate sub-query where you apply all necessary conditions at once (instead of applying them for your collection independently).
I ran across the same problem in my project.
My workaround is to build the exists subquery manually.
Assuming that your both classes are mapped as Entities:
#Entity
#Table(name = "Offer")
public class Offer {
#Id
String id;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "offer")
List<LanguageToName> names;
}
#Entity
#Table(schema = "dcsdba", name = "Language_To_Name")
public class LanguageToName {
#Id
String id;
#ManyToOne(fetch= FetchType.LAZY)
#JoinColumn(name="Offer_id")
private Offer offer;
String name;
String language;
}
A simple query with any():
BooleanExpression namesFilter = QOffer.offer.names.any().name.eq("Esperanto");
maps to
select
offer0_.id as id1_7_
from
offer offer0_
where
exists (
select
1
from
dcsdba.language_to_name names1_
where
offer0_.id=names1_.offer_id
and names1_.name=?
)
A subquery:
BooleanExpression namesFilter = JPAExpressions.selectOne()
.from(languageToName)
.where(languageToName.offer.eq(QOffer.offer)
.and(languageToName.name.eq("Esperanto")))
.exists();
Maps to:
select
offer0_.id as id1_7_
from
offer offer0_
where
exists (
select
1
from
dcsdba.language_to_name languageto1_
where
languageto1_.offer_id=offer0_.id
and languageto1_.name=?
)
which matches perfectly previous SQL.
You can add additional conditions like:
BooleanExpression namesFilter = JPAExpressions.selectOne()
.from(languageToName)
.where(languageToName.offer.eq(QOffer.offer)
.and(languageToName.name.eq("Esperanto"))
.and(languageToName.language.like("E%")))
.exists();

Hibernate find an existing object in db

Simple question here :
If i've got an object with initialized and uninitialized values in it. Is there an easy way to find in my db all the Entities that fit this one with hibernate ? (without listing and checking every variable of the object)
Example :
I got this class :
public class User {
private int id;
private String name;
private String email;
private boolean activ;
}
I would like to be able to do that :
User user1 = new User();
user.setActive() = true;
User user2 = new User();
user.setActive(true);
user.setName("petter")
listUser1 = findAllUser(user1);
listUser2 = findAllUser(user2);
Here listUser1 will contain all the active users and listUser2 will contain all the active user that are named petter.
Thx guys !
Edit/Solution
So my here is my code (i used a class wich is similar at the one of my example).
It work just fine but the problem is that according to Eclipse : "The method createCriteria(Class) from the type SharedSessionContract is deprecated"...
public static List<Personne> findAllPersonne(Personne personne) {
List<Personne> listPersonne;
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("testhibernate0");
EntityManager entityManager = entityManagerFactory.createEntityManager();
Session session = entityManager.unwrap(Session.class);
Example personneExample = Example.create(personne);
Criteria criteria = session.createCriteria(Personne.class).add(personneExample);
listPersonne = criteria.list();
entityManager.close();
return listPersonne;
}
So .. How could i do that in a better way? I've looked into CriteriaQuery but i can't find how to use it with an example.
Yes it exists : the key word for google is "query by exemple" or "qbe".
https://dzone.com/articles/hibernate-query-example-qbe
In general, if an entity instance is already in your Persistence context, you can find it by primary key with EntityManager.find. Otherwise, you can pick up a result from your database by way of JPQL or native querying.
For your particular use case, it sounds like a querying solution would be the best fit; use one of the linked query creation methods from your entity, then use the Query.getResultList() method to pick up a list of objects that match the query criteria.
QueryByExample is also a good and valid solution, as Mr_Thorynque indicates, but as the article he linked mentions, that functionality is specific to certain JPA providers (Hibernate among them) and not JPA provider agnostic.

JPA Cacheable specific example on how to use it

I am kind of new to JPA and have read a bit about second level caching in JPA. And I think it should apply correctly to my scenario.
I have a table (say A) whose content will never change unless a new release is applied.
I need to query some data from the database : for that I have a JPQL working correctly and that uses a join between table A and an additional table (say B).
Since the contents of table A never change through the life of application, I could essentially mark this table A as Cacheable and reuse the content from Cache - rather than going to the database for that.
I have read about #NamedQuery that enables a one time JPQL to SQL translation for the life of the application. And it is not what I am looking for.
I want to know how should I go about using the Cacheable property for my purpose.
This is what I have done so far :
Marked tableA as cacheable -
#Entity
#Cacheable
#Table(name = "TableA")
public class Table{
#Id
#NotNull
#Column(updatable = false)
private String uuid;
#NotNull
#Size(min = 1)
private String description;
.
.
.
}
2. There is a DAO that does a find using the JPQL -
public Collection findAll(String description) {
final Cache cache = entityManager.getEntityManagerFactory().getCache();
if (cache.contains(TableA.class, "abc")) {
System.out.println("cached");
} else {
System.out.println("not cached");
}
final Query query = entityManager
.createQuery("Select distinct A from TableA A, IN(A.TableB) B where A.description = :description"); //$NON-NLS-1$
query.setParameter("description", description); //$NON-NLS-1$
return query.getResultList();
}
</code>
Can I take advantage of using Cacheable property in my scenario. If so, then could you suggest how?
Also, "not cached" gets printed always no matter what the value of string I use (from table) instead of "abc".
Appreciate your help. Thanks

Categories