Hibernate: getting data from two linked tables using Ctriteria API - java

How can I get data from two linked tables (one-to-many: one User and many Results) by value 'ispassed' (boolean) using Ctriteria API?
private List<?> winners;
try {
SessionFactory factory = HibernateUtil.getSessionFactory();
Session hSession = factory.openSession();
Transaction tx = null;
try {
tx = hSession.beginTransaction();
winners = hSession.createSQLQuery("select * from usertable u, resulttable r where u.id = r.id where r.ispassed = true").list();
tx.commit();
} catch (Exception e) {
if (tx != null)
tx.rollback();
} finally {
hSession.close();
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(winners.size()); // an exception

You can use HQL:
from usertable u, resulttable r where u.id = r.id
where r.ispassed = 1
This will return a list of [User,result] arrays.
Change you code like:
private List<?> winners;
try {
SessionFactory factory = HibernateUtil.getSessionFactory();
Session hSession = factory.openSession();
Transaction tx = null;
try {
tx = hSession.beginTransaction();
winners = hSession.createSQLQuery("from usertable u, resulttable r where u.id = r.id and r.ispassed = true").list();
tx.commit();
} catch (Exception e) {
if (tx != null)
tx.rollback();
} finally {
hSession.close();
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(winners.size());
EDIT:
CriteriaBuilder b = em.getCriteriaBuilder();
CriteriaQuery<Tuple> c = b.createTupleQuery();
Root<EntityX> entityXRoot= c.from(EntityX.class);
Root<EntityY> entityYRoot = c.from(EntityY.class);
List<Predicate> predicates = new ArrayList<>();
//Here you need to add the predicates you need
List<Predicate> andPredicates = new ArrayList<>();
andPredicates.add(b.equal(entityXRoot.get("id"), entityYRoot.get("id")));
andPredicates.add(b.and(predicates.toArray(new Predicate[0])));
c.multiselect(entityXRoot, entityYRoot);
c.where(andPredicates.toArray(new Predicate[0]));
TypedQuery<Tuple> q = em.createQuery(criteria);
List<Tuple> result = q.getResultList();

You can create your entity class like below
#Entity
#Table(name="RESULTS")
public class Results implements Serializable {
#Id
#GeneratedValue()
#Column(name="ID")
private Long id;
#ManyToOne
#JoinColumn(name="USER_ID")
private User userId;
#Column(name = "IS_PASSED")
private Boolean ispassed;
other property
... getter() setter()
}
#Entity
#Table(name="USER")
public class User implements Serializable {
#Id
#GeneratedValue()
#Column(name="ID")
private Long id;
#OneToMany(mappedBy = "userId",cascade=CascadeType.ALL)
private Set<Results> resultsSet;
other property
... getter() setter()
}
And in your hibernate.cfg.xml file if set below property
<property name="hibernate.query.substitutions">true 1, false 0</property>
Execute below HQL query
String sql = "from User as user "
+ "inner join user.resultsSet"
+ "where resultsSet.ispassed= true";
Query query = getCurrentSession().createQuery(sql);
List<User> UserList = query.list();
above is how you can get List of User, now you need to Iterate User list and use getter method get all results.

Related

How to show information about an entity?

I have a problem. After clicking on the "create order" button, the user is redirected to the URL: "localhost:8080/currentorder/{id}" After visiting this URL, the user should see order.text.
Attempts to solve: In the DAO, I create a method that, by the ID passed from the controller, looks for an order in HQL:
public List show(Long id) {
Transaction tx = null;
try (Session session = BogPomogi.getSessionFactory().openSession()) {
session.beginTransaction();
Query query = session.createQuery("from Order where id = :id");
query.setParameter("id", id);
List result = query.getResultList();
session.getTransaction().commit();
return result;
}
}
But as you understand, after that, the timelif could not display anything (I mean order.getStatus()) Now I still think that I need to search the database and return an object, but how? help me please
My code:
Controller
#PostMapping("/")
public String createOrder (#ModelAttribute("order") Orderdao orderdao, String text, Model model, RedirectAttributes redirectAttributes){
orderdao.createOrder(text);
redirectAttributes.addAttribute("id", orderdao.checkLastOrder());
return "redirect:/currentorders/{id}";
}
#GetMapping("/currentorders/{id}")
public String showOrder (#PathVariable("id") Long id, Orderdao orderdao, Model model, Order order){
model.addAttribute("currentOrder", orderdao.show(id));
return "order";
}
Entity
#Entity
#Table(name = "orders")
public class Order implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String text;
private String customer;
private int status;
public Order(String text, String customer, int status) {
this.text = text;
this.customer = customer;
this.status = status;
}
public Order(String customer) {
this.customer = customer;
}
public Order(){
}
//Getters and setters
Method:
public Order show(Long id) {
Transaction tx = null;
try (Session session = BogPomogi.getSessionFactory().openSession()) {
session.beginTransaction();
Query query = session.createQuery("from Order where id = :id");
query.setParameter("id", id);
List result = (List) query.getSingleResult();
session.getTransaction().commit();
return (Order) session.save(result);
}
}
I am missing your code for orderDao.create, but usually you would have a service class (annotated with Springs #Service annotation), which is injected to the controller and which is called to create the entity. You can make this service method return the ID of the just created entity. It could hence be something like public Long createOrder(OrderDao orderDao). Inside there, after calling repository.save(entity), the entity will already have the ID set (try to verify yourself with debugger: Set a breakpoint to the line before you save the entity and check the ID is null, then go one step forward and see that after save, the ID is set).
My answer:
public Order show(Long id) {
Transaction tx = null;
try (Session session = BogPomogi.getSessionFactory().openSession()) {
session.beginTransaction();
Query query = session.createQuery("select text from Order where id = :id");
query.setParameter("id", id);
String result = (String) query.getSingleResult();
session.getTransaction().commit();
session.close();
return new Order(result, "adsfreger", 1);
}
}

Trying to test the existence of a record using hibernate 4

I have an addEmployee webservice in the Spring 4 controller as shown in the code which is accepting emp_name and definition.
The insertion in the database table is happening using Hibernate 4 when the insertIntegertype method is called.
#RequestMapping(value="/addEmployee", method=RequestMethod.GET)
public String addEmployee
(
#RequestParam(value="name", defaultValue="") String emp_name,
#RequestParam(value="definition", defaultValue="") String definition
)
{ int emp_id = 0;
try {
EmpDao empDao = (EmpDao)context.getBean("empDao");
Emp empInsert = new Emp();
empInsert.setName(emp_name+" Attributes");
empInsert.setDefinition(definition);
empInsert.setOwnerName(owner_name_);
emp_id = empDao.insertIntegertype(empInsert);
}catch (Throwable th){
// some code here
}
}
Need to Include the following check:
As mentioned in the code while setting the name of an employee, I am also adding Attributes word in this line empInsert.setName(emp_name+" Attributes");
So, there can be a scenario when the same name is already present in the database and in that scenario, I would like to test
whether that name already exists in the database or not and then only proceed with the insert.
I am wondering is there a way in hibernate which can help me in figuring out this thing?
In case needed, my insertIntegertype hibernate method is defined as follows
public int insertIntegertype(Emp emp)
{
logger.debug("Starting EmpDaoImpl.insert() .....");
Session session = null;
Transaction tx = null;
boolean status = true;
int Emp_id = 0;
try {
session = sessionFactory.openSession();
tx = session.beginTransaction();
session.persist(emp);
tx.commit();
Emp_id = emp.getEmpId();
} catch(Exception ex) {
tx.rollback();
ex.printStackTrace();
status = false;
} finally {
session.close();
}
logger.debug("Completed EmpDaoImpl.insert() .....");
return Emp_id;
}
Approach :
Make a selection query from database with a like "Name%" if not exist make the Insertion
You have 3 options :
1-Using Native Query
Session session = sessionFactory.openSession();
session.beginTransaction();
String sql = "select First_Name FROM employee where First_Name like 'NAME%'"
NativeQuery query = session.createNativeQuery(sql);
List<Object[]> list = query.list();
if (list.isEmpty()) {
session.persist(emp);
}
2-Using HQL
Session session = sessionFactory.openSession();
session.beginTransaction();
Query query = session.createQuery("select u.name from Employee u where u.name like :Name");
List<Object[]> list= query.setParameter("Name", name+ "%").list();
if (list.isEmpty()) {
session.persist(emp);
}
3-Using CriteriaBuilder
Session session = sessionFactory.openSession();
session.beginTransaction();
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<String> criteria = builder.createQuery(String.class);
Root root = criteria.from(class);
Path <String> attribute = root.get(col);
criteria.select(attribute).where(builder.(attribute,NAME + "%"));
List<String> list = session.createQuery(criteria).getResultList();
if (list.isEmpty()) {
session.persist(emp);
}
You should query the database to check if an employee with such name exists. Then you can proceed with saving the employee according to your requirements

Hibernate method giving error while insert into database

I am getting below error while working on the Hibernate code to insert record in the database. Please suggest what wrong I am doing here.
Hibernate: insert into feedback (fb_rating_id, fb_suggestion, fb_topic_id, user_info) values (?, ?, ?, ?)
Exception deleting record :org.hibernate.exception.GenericJDBCException: could not insert: [com.tdp.model.Feedback]
public int insertFeedback(String ratingId, String msg) {
int status = 0;
Session sess = sessionFactory.openSession();
Transaction tx = null;
try {
tx = sess.beginTransaction();
//Criteria crit = sess.createCriteria(Feedback.class);
// crit.add(Restrictions.eq("feedbackId",feedback.getFeedbackId()));
Feedback fbObj = new Feedback();
fbObj.setFbRatingId(Integer.parseInt(ratingId));
fbObj.setFbSuggestion(msg);
fbObj.setFbTopicId(null);
fbObj.setUserInfo("");
sess.save(fbObj);
tx.commit();
status = 1;
} catch (HibernateException e) {
System.out.println("Exception deleting record :" + e);
if (tx != null) {
tx.rollback();
}
} finally {
sess.close();
}
return status;
}
Feedback.java
#Table(name=TDPConstants.FEEDBACK )
public class Feedback {
private Integer feedbackId; //primary key
private Integer fbRatingId;
private Integer fbTopicId;
private String fbSuggestion ;
private String userInfo ;
#Id
#Column(name = "feedback_id",unique = true, nullable = false)
#GeneratedValue(strategy = GenerationType.AUTO)
public Integer getFeedbackId() {
return feedbackId;
}
public void setFeedbackId(Integer feedbackId) {
this.feedbackId = feedbackId;
}
//all other setters & getters
Could it be because you have the conditions commented out and so it is returning more than 1 object? Hibernate throws an exception if you told it to expect 1 result but it has multiple results or no result.
Based on your comment
You have to create a new instance of Feedback and set the data on it and then pass that instance to Hibernate to insert into the database.

org.hibernate.QueryException: could not resolve property: is_approved of: com

I am fetching records from purchase table by userid it was working fine but now want to add one condition that is (is_approved) column value is = 1,i added this condition in that same query it was throughing error
//My DAOHibernate method is below
public int getNumOfPurchasesByUserId(Integer userId) {
System.out.println("########################### Calling getNumOfPurchasesByUserId %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
String sql = "select count(p) from " + Purchase.class.getName() + " p where p.userid = :userid and p.is_approved=1";
Session session = null;
Query q = null;
int count = 0;
try {
session = getHibernateTemplate().getSessionFactory().openSession();
q = session.createQuery(sql);
q.setInteger("userid", userId);
try {
count = ((Long)q.uniqueResult()).intValue();
} catch (Exception e) {}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (session != null) {
session.close();
}
}
return count;
}
//my error is
########################### Calling getNumOfPurchasesByUserId %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
org.hibernate.QueryException: could not resolve property: is_approved of: com.newscom.model.Purchase [select count(p) from com.newscom.model.Purchase p where p.userid = :userid and p.is_approved=1]
at org.hibernate.persister.entity.AbstractPropertyMapping.propertyException(AbstractPropertyMapping.java:81)
at org.hibernate.persister.entity.AbstractPropertyMapping.toType(AbstractPropertyMapping.java:75)
at org.hibernate.persister.entity.AbstractEntityPersister.toType(AbstractEntityPersister.java:1465)
at org.hibernate.hql.ast.tree.FromElementType.getPropertyType(FromElementType.java:315)
at org.hibernate.hql.ast.tree.FromElement.getPropertyType(FromElement.java:487)
at org.hibernate.hql.ast.tree.DotNode.getDataType(DotNode.java:611)
at org.hibernate.hql.ast.tree.DotNode.prepareLhs(DotNode.java:263)
at org.hibernate.hql.ast.tree.DotNode.resolve(DotNode.java:210)
at org.hibernate.hql.ast.tree.FromReferenceNode.resolve(FromReferenceNode.java:117)
at org.hibernate.hql.ast.tree.FromReferenceNode.resolve(FromReferenceNode.java:113)
at org.hibernate.hql.ast.HqlSqlWalker.resolve(HqlSqlWalker.java:880)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.expr(HqlSqlBaseWalker.java:1330)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.exprOrSubquery(HqlSqlBaseWalker.java:4471)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.comparisonExpr(HqlSqlBaseWalker.java:3944)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2047)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:1975)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.whereClause(HqlSqlBaseWalker.java:831)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:617)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:301)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:244)
at org.hibernate.hql.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:256)
at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:187)
at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:138)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:101)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:80)
at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:124)
at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:156)
at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:135)
at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1770)
at com.newscom.dao.hibernate.PurchaseDAOHibernate.getNumOfPurchasesByUserId(PurchaseDA
//In purchase
#Entity
#Table(name = "Purchase")
#NamedQueries(value = {
#NamedQuery(name = "GetPurchaseByUserID", query = "SELECT p from Purchase p where p.userid = :userid order by p.status, p.purchaseid desc"),
private boolean isApproved;
private Date approvalTime;
private Integer approvedBy;
#Column(name="is_approved")
public boolean getIsApproved() {
return isApproved;
}
public void setIsApproved(boolean isApproved) {
this.isApproved = isApproved;
}
You should use property name, not column name in your query:
String sql = "select count(p) from " + Purchase.class.getName() + " p where p.userid = :userid and p.isApproved=1";
Hope it helps.

Hibernate Session Closed Exception,When 10 or more user access the page

I have a spring MVC application with hibernate.I keep on getting the session closed error, when 10 or more users accessed the same page for reading the data or after fast subsequent requests.
Please help, I needed a crucial fix. It is affecting the customer.
I use the below code
try{
session = sessionFactory.openSession();
tx = session.getTransaction();
session.beginTransaction();
Map<Organization, List<Users>> comToUserLst
= new HashMap<Organization,List<Users>>();
String queryString = "FROM Users as usr Inner Join usr.organization
as org where org.id = :id";
Query query = session.createQuery(queryString);
query.setInteger("id", Integer.valueOf(id));
List<?> comLst = query.list();
Iterator<?> ite = comLst.iterator();
while (ite.hasNext()) {
Object[] objects = (Object[]) ite.next();
Users user = (Users) objects[0];
Organization Organization = (Organization) objects[1];
if (comToUserLst.containsKey(Organization)) {
List<Users> usrLst = new ArrayList<Users>();
usrLst.addAll(comToUserLst.get(Organization));
usrLst.add(user);
comToUserLst.put(Organization, usrLst);
} else {
List<Users> userLst = new ArrayList<Users>();
userLst.add(user);
comToUserLst.put(Organization, userLst);
}
}
} catch (HibernateException e) {
tx.rollback();
e.printStackTrace();
} finally {
tx.commit();
session.close();
}
return comToUserLst;
For update
#Transactional
public Account updateAccount(Account account, UserDetail userInfo) {
session = sessionFactory.getCurrentSession();
Account acct = null;
String queryString = "FROM Account where id = :acctId";
Query query = session.createQuery(queryString);
query.setLong("acctId", account.getId());
acct = (Account) query.uniqueResult();
acct.setName(account.getName());
acct.setPhone(account.getPhone());
acct.setRating(account.getRating());
acct.setFax(account.getFax());
acct.setAccountNumber(account.getAccountNumber());
if (!ValidateUtil.isNullOrEmptyCheckStr(account.getParentAccount()
.getName())) {
acct.setParentAccount(account.getParentAccount());
}
acct.setWebsite(account.getWebsite());
acct.setType(account.getType());
acct.setIndustry(account.getIndustry());
acct.setNumberOfEmployees(account.getNumberOfEmployees());
acct.setDescription(account.getDescription());
acct.setAnnualRevenue(account.getAnnualRevenue());
acct.setEmail(account.getEmail());
acct.setBillingAddress(account.getBillingAddress());
acct.setShippingAddress(account.getShippingAddress());
Users user = new Users();
user.setId(userInfo.getUserId());
// modified details
acct.setModifiedBy(user);
acct.setModifiedDate(new Date());
//update use merge
session.merge(acct);
session.flush();
System.out.println("update Account" + acct.getId());
return acct;
}
Exception
org.hibernate.SessionException: Session is closed!
at org.hibernate.internal.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:133)
at org.hibernate.internal.SessionImpl.getTransactionCoordinator(SessionImpl.java:2069)
at org.hibernate.loader.Loader.doQuery(Loader.java:923)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354)
at org.hibernate.loader.Loader.doList(Loader.java:2553)
at org.hibernate.loader.Loader.doList(Loader.java:2539)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2369)
at org.hibernate.loader.Loader.list(Loader.java:2364)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:496)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:387)
at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:231)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1264)
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:103)
at com.oi.service.setup.OrganizationService.getOrgToUserLst(OrganizationService.java:311)
at com.oi.service.setup.OrganizationService$$FastClassBySpringCGLIB$$84e99831.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
In Spring it might need to look like this:
#Autowired
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
#Transactional
public Map getOrgToUserLst() {
Map<Organization, List<Users>> comToUserLst = new HashMap<Organization,List<Users>>();
String queryString = "FROM Users as usr Inner Join usr.organization as org where org.id = :id";
List<?> comLst = this.sessionFactory.getCurrentSession()
.createQuery(queryString)
.setParameter(0, Integer.valueOf(id))
.list();
Iterator<?> ite = comLst.iterator();
while (ite.hasNext()) {
Object[] objects = (Object[]) ite.next();
Users user = (Users) objects[0];
Organization Organization = (Organization) objects[1];
if (comToUserLst.containsKey(Organization)) {
List<Users> usrLst = new ArrayList<Users>();
usrLst.addAll(comToUserLst.get(Organization));
usrLst.add(user);
comToUserLst.put(Organization, usrLst);
} else {
List<Users> userLst = new ArrayList<Users>();
userLst.add(user);
comToUserLst.put(Organization, userLst);
}
}
return comToUserLst;
}
#Transactional
public void saveOrganization(Organization org) {
this.sessionFactory.getCurrentSession().persist(org);
}
#Transactional
public void updateOrganization(Organization org) {
this.sessionFactory.getCurrentSession().merge(org);
}
#Transactional
public void deleteOrganization(Organization org) {
getCurrentSession().delete(org);
}
#Transactional
public void deleteOrganizationById(long id) {
final Organization org = this.getCurrentSession().get(Organization, id);
this.getCurrentSession().delete(org);
}
FOR UPDATE
// Get an account object by ID
public Account getAccount(long id) {
session = sessionFactory.getCurrentSession();
String queryString = "FROM Account where id = :acctId";
Query query = session.createQuery(queryString);
query.setLong("acctId", id);
return (Account) query.uniqueResult();
}
// Set account object's attributes
public Account updateAccount(Account acct, UserDetail userInfo) {
acct.setName(account.getName());
acct.setPhone(account.getPhone());
acct.setRating(account.getRating());
acct.setFax(account.getFax());
acct.setAccountNumber(account.getAccountNumber());
if (!ValidateUtil.isNullOrEmptyCheckStr(account.getParentAccount()
.getName())) {
acct.setParentAccount(account.getParentAccount());
}
acct.setWebsite(account.getWebsite());
acct.setType(account.getType());
acct.setIndustry(account.getIndustry());
acct.setNumberOfEmployees(account.getNumberOfEmployees());
acct.setDescription(account.getDescription());
acct.setAnnualRevenue(account.getAnnualRevenue());
acct.setEmail(account.getEmail());
acct.setBillingAddress(account.getBillingAddress());
acct.setShippingAddress(account.getShippingAddress());
Users user = new Users();
user.setId(userInfo.getUserId());
// modified details
account.setModifiedBy(user);
account.setModifiedDate(new Date());
updateAccount(acct);
}
// Update the account object in the database. Here transaction is necessary
#Transactional
private Account updateAccount(Account acct) {
session = sessionFactory.getCurrentSession();
//update use merge
System.out.println("update Account" + acct.getId());
return session.merge(acct);
}
// This is for testing
public void testUpdate(long id, UserDetail userInfo) {
Account acc = getAccount(id);
updateAccount(acct, userInfo);
}
Reference
How are you fetching your sessions SessionFactory.openSession() or SessionFactory.getCurentSession()? Keep in mind that hibernate sessions are not thread safe, hence you require one session per request response cycle.
You should use sessionFactory.getCurrentSession() in place of openSession(). This will maintain the opening and closing sessions automatically.
Also you should use Spring's Transaction using #Transactional with you method. Spring's Transaction management is more efficient than the Hibernate's getCurrentTransaction()

Categories