我在java中有一个类,有两个类似于这里的方法。
public Object noOfEmployees() {
List<Employee> emp = null;
String u = user.getUserName();
if ("user1".equals(u)) {
Query query = getHibernateTemplate().getSessionFactory().openSession()
.createSQLQuery("select * from employee where job='System Analyst'")
.addEntity(EMPLOYEE.class);
emp = query.list();
getHibernateTemplate().getSessionFactory().openSession().close();
} else if ("user2".equals(u)) {
Query query = getHibernateTemplate().getSessionFactory().openSession()
.createSQLQuery("select * from employee where job='DBA'")
.addEntity(EMPLOYEE.class);
emp = query.list();
getHibernateTemplate().getSessionFactory().openSession().close();
}
return emp.size();
}
当我运行应用程序时,这就是我得到输出的方式:
以&#39; user2&#39;
登录休眠:从员工中选择*,其中job =&#39; DBA&#39;
Hibernate:从员工中选择*,其中job =&#39; DBA&#39;和排名=&#39; 2&#39;
休眠:从员工中选择*,如果存在=&#39;是&#39;
以&#39; user1&#39;
登录Hibernate:从员工中选择*,其中job =&#39; System Analyst&#39;
Hibernate:从员工中选择*,其中job =&#39; System Analyst&#39;和排名=&#39; 3&#39;
休眠:从员工中选择*,如果存在=&#39;是&#39;
再次登录为&#39; user2&#39;,前两个方法被执行。
休眠:从员工中选择*,其中job =&#39; DBA&#39;
Hibernate:从员工中选择*,其中job =&#39; DBA&#39;和排名=&#39; 2&#39;
当我以任何用户身份登录时,这次甚至第一种方法都没有被执行。
我注意到遇到 query.list()时代码卡住了。我知道不建议使用hibernateTemplate,但整个应用程序都是使用它编写的。我刚刚开始学习弹簧和冬眠。一旦我对这些事情感到满意,我就会开始做出改变。
任何与query.list()性能相关的建议以及改进代码的方法都非常受欢迎。
谢谢!
答案 0 :(得分:0)
显然,问题在于此代码
Query query = getHibernateTemplate().getSessionFactory().openSession().
...
getHibernateTemplate().getSessionFactory().openSession().close();
使用此getHibernateTemplate().getSessionFactory().openSession().close()
,您将获得一个新会话并关闭它!
你应该使用HQL
Query query = session.createQuery("from Employee where job='System Analyst'");
List<Employee> emp = query.list();
使用Hibernate Template
的方式完全不正确。
参考如何使用
https://docs.spring.io/spring/docs/current/spring-framework-reference/html/classic-spring.html
一个例子
public class ProductDaoImpl {
private HibernateTemplate hibernateTemplate;
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
public Collection loadProductsByCategory(final String category) throws DataAccessException {
return this.hibernateTemplate.execute(new HibernateCallback() {
public Object doInHibernate(Session session) {
Criteria criteria = session.createCriteria(Product.class);
criteria.add(Expression.eq("category", category));
criteria.setMaxResults(6);
return criteria.list();
}
};
}
}
答案 1 :(得分:0)
你的代码在很多层面都存在缺陷......对于初学者来说,你不应该使用HibernateTemplate
,除非你是一个非常古老的应用程序,否则使用普通的SessionFactory
。有关详细信息,请参阅http://docs.spring.io/spring/docs/current/spring-framework-reference/html/orm.html#orm-hibernate-straight。
第二个使用Spring时使用Spring来管理你的资源,在这种情况下是Session
,或者如果你想自己做,至少要管理它!
因此,简而言之,请使用SessionFactory
并使用getCurrentSession
代替openSession
。并使用正确的查询。
@Autowired
private SessionFactory sf;
@Transactional
public Long noOfEmployees() {
final String query = "select count(*) from employee where job=:job";
Query q = sf.getCurrentSession().createSQLQuery(query);
if ("user1".equals(u)) {
q.setParameter("job", "System Analyst");
} else if ("user2".equals(u) ) {
q.setParameter("job", "DBA");
}
return (Long) query.uniqueResult();
}
@Transactional
会让spring管理资源,假设您在上下文中有<tx:annotation-driven />
并正确添加了HibernateTransactionManager
。
答案 2 :(得分:0)
我试图在某种程度上改变我的多级错误代码。感谢@ M.Deinum和@ v.ladynev的快速反应。
下面给出的是仅提到从HibernateTemplate转移到SessionFactory的更改的片段:
//IndexService
@Transactional
public class IndexService {
User user;
SessionFactory sf;
public IndexService(User user, SessionFactory sf) {
this.user = user;
this.sf = sf;
}
//This method is used to get the number of employees based on users.
public Object noOfEmployees() {
String u = user.getUserName();
final String query = "select count(*) from employee where job=:job";
Query q = sf.getCurrentSession().createSQLQuery(query);
if ("user1".equals(u)) {
q.setParameter("job", "System Analyst");
} else if ("user2".equals(u) ) {
q.setParameter("job", "DBA");
}
return q.uniqueResult();
}
--------------------------------------------------------------------------------------
//Index
@Controller
@Transactional
public class Index {
@Autowired
User user;
@Autowired
SessionFactory sf;
@RequestMapping("/index")
public ModelAndView getIndex() {
System.out.println("user.getUserName() In Index = " + user.getUserName());
ModelAndView modelAndView = new ModelAndView("index");
IndexService indexService = new IndexService(user, sf);
modelAndView.addObject("noOfEmployees", indexService.noOfEmployees());
return modelAndView;
}
}
--------------------------------------------------------------------------------------
//spring-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="basicDataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url"
value="jdbc:mysql://localhost/database_name"></property>
<property name="username" value="user"></property>
<property name="password" value="password"></property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="basicDataSource"></property>
<property name="mappingResources" value="myBeans.hbm.xml" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
从HibernateTemplate更改为SessionFactory时遇到的问题:
1. SessionFactory的 在索引类中, @Autowired
SessionFactory sf; 并将其作为参数传递。 IndexService indexService = new IndexService(user,sf); 2.没有Hibernate Session绑定到线程,并且配置不允许在这里创建非事务性的 我也把@Transactional放在索引之上。它是我应用程序中的控制器。 再次感谢@ M.Deinum和@ v.ladynev!