Environment: JPA 1, Hibernate 3.3.x
I have an JPA entity class (User), how do I selectively fetch member variables say (first_name, last_name) instead of fetching all user attributes using the JPA api.
Do you mean something like this (and in that case, the result of your query will be an Object[]):
SELECT u.firstName, u.lastName FROM User u
Alternatively, you could use a constructor expression in the SELECT clause:
SELECT NEW com.acme.example.UserDetails(u.firstName, u.lastName) FROM User u
The class used in the NEW is not necessarily an Entity, it just has to provide a proper constructor.
If you query for more columns you'll get an object result which you'll have to cast to an object array to retrieve values. Better is to create a viewObject class in which you directly store the results:
select new full.package.name.UserView(u.firstName, u.LastName) from User u
where UserView looks like:
class UserView {
String firstName, String lastName;
// getters, setters/constuctor
}
Related
I am new to JPA and Hibernate.
In one use case, I need to fetch all users from DB with associated email present in given email list.
To do this, I have written a custom JPA query as follows:
#Query("SELECT u from User u where u.email in :emailIds")
List<User> findUsersByEmailIds(#Param("emailIds") List<String> emailIdList);
But, I would like to know, is there any better way to do the same?
As commented by Vishnu, here is the explanation:
Assuming in your User entity you have a field like this:
private String email;
Then in your repository you can go like this:
List<User> findByEmailIn(List<String> emailIdList);
The important key thing to notice here is the Capital E in findByEmailIn while in your entity this field was email (small e). This way you can eliminate the #Query statement completely.
I have a 3 tables:
Item: item_id (pk), short_description, ...
SupplierItem: item_id (fk), supplier_id (fk), vendor_product_number, ...
Supplier: item_supplier (pk), name, ...
Relation between Item and Supplier is many to many. SupplierItem is
intermediate table.
I want use VO and DAO.
How to design this in VO (Java)?
After, How can I do the following query in java code.
select i.item_id, i.short_description, s.vendor_product_number as FONUA_PRODUCT_CODE
from item i
left join supplier_item s
on i.item_id=s.item_id
where ((i.item_id=:item_id) OR :item_id IS NULL)
and i.parent_item_id is null
order by vendor_product_number DESC"
I still do not understand the concept in use VO and DAO.
Thanks
DAO would be the java file where you define your query and get the results of the query call on the database.
The results from the query will be saved by setting them as values to the properties of a particular VO.
For Example:
Your query returns ,
item_id, short_description, vendor_product_number
So let us say that you will have to create another java file say ItemVO.java and declare the particular properties of the ItemVO object,
For Ex:
private String itemId;
private String shortDescription;
private String vendorShortNum;
/*Define your getters and setters*/
In the DAO file you will have to map the query results to the VO file's objects.
ItemVO itemVO= new ItemVO();
itemVO.setItemId(/*the particular column value from the query result*/);
itemVO.setShortDescription(/*the particular column value from the query result*/);
itemVO.setVendorShortNum(/*the particular column value from the query result*/);
When a class annotated with #Entity annotaion hibernate uses queries like SELECT * FROM class_name. But for some reason it is needed to run custom select query for class. Is there a way to provide such query?
Yes, according to the official hibernate reference, you can do it like:
sess.createSQLQuery("SELECT * FROM CATS").addEntity(Cat.class);
or:
sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").addEntity(Cat.class);
Criteria cr = getCurrentSession().createCritiera(class_name.class)
.setProjection(Projections.projectionList()
.add(Projections.property("id"), "id")
.add(Projections.property("name"), "name"))
.setResultTransformer(Transformers.aliasToBean(class_name.class));
List<class_name> list = cr.list();
Act as select id,name from class_name this will return List of class_name containing objects only have id and name and the rest of variables in class_name will be null (as you only selected id and name)
I would recommend you getHibernatTemplate() from HibernateDaoSupport. Afterwards you can call find("from Class where....") and you get back an object which you can cast to your java class easily.
i.e.
List < User > users = (List < User > )getHibernateTemplate("from User");
I have a mongodb with two model classes say User and UserInfo. The criteria is in User class I have to retrieve a multiple fields around 10 fields like "firstName","lastName", etc and in UserInfo Model class I like to retrieve only one field say "age".
At this moment I referenced the UserInfo class's object to the User class like stated below in the Structure and its stores in the DB as {"firstName","John"},{"lastName","Nash"},{userInfo: userInfoID} but if I make an Embedded Relation then it would store all the userInfo's fields and I think to retrieve one ("age") field it is Unwanted to Embed all the userInfo's fields which inturn will make the application slow I think.
Which scenario should I use whether #Reference or #Embedded, I think Embedded will slow down my response to DB but in the websites its given as reference annotation only slows down querying time and needs some sort of Lazy Loading an all, my structure is like below:
class User extends Model{
public String firstName;
public String lastName;
public String loginTime;
public String logoutTime;
public String emailId; etc,etc......
Some more 10 fields like this+userInfo reference object
#Reference
public UserInfo userInfo;
}
class UserInfo extends Model{
public String emailId;
public String age;
public String sex;
public String address;
public String bank; etc,etc......
Some more 10 fields like this
}
As I stated above I want only age field from UserInfo and all fields of User, so which Annotation is best and #Reference or #Embedded. It will be more helpful if I get a single query for User class in which I can retrieve all fields of User and only "age" field of UserInfo. In short I need a query like this when I go for #Reference relationship
field("userInfo.age") for userInfo.emailId = (MorphiaQuery q = User.createMorphiaQuery;
q.field("firstName").equal("John"); q.field("lastName").equal("Nash"); q.field("loginTime").greaterthan("sometime"))//the complex part where I need age of particular userInfo but I have only the ID of the userInfo since I am using Reference and that Id too got from a **subQuery**....
Please don't write two queries I need a single query or maybe a query with subquery. To be more clear I can tell in SQL language:
SELECT age FROM UserInfo where emailId = u.emailId
(SELECT * FROM User WHERE firstName='John' AND lastName='Nash' AND
logintime='someTime') AS u;
I need this exact same query without writing two morphia queries which consumes more time by referring two tables.
Mongo does not support query across tables / collections. And such page would satisfy you:
MongoDB and "joins"
As in sql, the join query is also build intermediate result set and make query again:
Understanding how JOIN works when 3 or more tables are involved. [SQL]
When you build your model, you should not consider a lot about what single query but structural modeling:
http://docs.mongodb.org/manual/core/data-modeling/
For your case, if you are using embeded, you can make this in one query and specify the fields you need by using queries like:
db.User.find({"some_field":"some_query"},{"firstName":1,....,"userInfo.age":1})
Check projections here:
http://docs.mongodb.org/manual/reference/method/db.collection.find/
If you are using reference or even soft link like using Morphia Key<> to lazy load the UserInfo, it requires two queries.
If it's not real-time application, you can also try mongo map-reduce to merge collection to handle big data, though the map-reduce is too bad for mongo though.
I'm reasonably sure you can't with just one query.
I need to set a table name dynamically so that I use query.setText(tname,abc)
e.g: select a.name from :tname where a.id = '2'
I used setText() because when I use setString() it says "tname is a invalid parameter" because I assume that Hibernate adds '' when setting string parameters.
But even setText() does not help and gives the same exception.
How can I set the table name dynamically?
Reply to PSR:
So you mean replace table name as a java string replacement. But then we can not take support of sql injections prevention etc from hibernate right? Also How we bind parameters in hibernate in a situation where like statement,
Eg: name like "%:name%"
This also gives me Illegal argument exception: Parameter does not exist as a named parameter when i try to bind it using query.setString(name,"def");
Hibernate will not do this for you, because it works with PreparedStatements, and you can't prepare a statement where the table being queried isn't known yet.
I don't see why you would be exposing table names to end users, so preventing SQL injection doing a regular string substitution should be easy. You use some sort of business logic to determine the correct table from a list that only you know. The table name isn't coming from user input at all.
Depending on your choice of RDBMS, you may find a discriminator column, or table inheritance with partitioning to be a better way of handling a situation where identical queries are made against different tables.
It is not possible to set table name dynamically.You can set dynamically column names.it is not possible to set table name
try like this
select a.name from '+table name+'where a.id = '2'
In my opinion, There are 2 ways to resolve this issue:
1- If you are using Spring and Hibernate together, you could use SpEL and it would be like #{#entityName} as it is described here
#Entity
public class User {
#Id
#GeneratedValue
Long id;
String lastname;
}
public interface UserRepository extends JpaRepository<User,Long> {
#Query("select u from #{#entityName} u where u.lastname = ?1")
List<User> findByLastname(String lastname);
}
2-You could use CriteriaBuilder like
CriteriaQuery<YourEntity> cr = cb.createQuery(YourEntity.class);
Root<YourEntity> root = cr.from(YourEntity.class);
cr.select(root);
I copied the source codes from the provided links and they are described there much better