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
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
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();
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();
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.
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