三、通過session操作hibernate(hql語句)

在沒有將spring和hibernate整合在一起的時候,要使用hibernate,在持久層需要如下步驟:

 

一、在還沒有對hibernate進行spring的整合的時候,我們需要寫一個session工具類來產生sssion操作數據庫

SessionUtil.java類:

package com.ge.hibernatexml.util;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

public class SessionUtil {
	
	private static Configuration cfg;
	private static ServiceRegistry serviceRegistry;
	private static SessionFactory sessionFactory;
	
	private static ThreadLocal<Session> local = new ThreadLocal<Session>() {
		protected Session initialValue() {
			return sessionFactory.openSession();
		};
	};
	

	static {
		cfg = new Configuration().configure();
		serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
				cfg.getProperties()).build();
		sessionFactory = cfg.buildSessionFactory(serviceRegistry);
	}

	
	public static Session getSession() {
		Session session = local.get();
		if(session == null) {
			session =  sessionFactory.openSession();
			local.set(session);
		}
		return session;
	}
}

 

二、然後利用切面進行事務的的管理:

TransactionAspect.java類:

package com.ge.hibernatexml.aspect;

import java.lang.reflect.Field;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.springframework.stereotype.Component;

import com.gezhi.hibernatexml.util.SessionUtil;

@Component
@Aspect
public class TransactionAspect {

	private Transaction tx;
	
	
	/**
	 * 定義切入點表達式
	 */
	@Pointcut("execution(* com.ge.hibernatexml.*mag.dao.impl.*Impl.*(..))")
	public void pointcut() {}
	
	/**
	 * 定義前置通知
	 * @param join
	 */
	@Before("pointcut()")
	public void beforeAdvice(JoinPoint join) {
		
		Session session = SessionUtil.getSession();
		
		Object obj = join.getTarget();//得到目標對象
		Class<?> cls = obj.getClass();
		try {
			Field field = cls.getDeclaredField("session");
			field.setAccessible(true);
			field.set(obj, session);
			
			//開啓該session對應的事務操作能力
			tx = session.beginTransaction();
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
	}
	
	@AfterReturning(pointcut="pointcut()",returning="rev")
	public void afterReturningAdvice(JoinPoint join,Object rev) {
		tx.commit();
	}
	
	@AfterThrowing(pointcut="pointcut()",throwing="e")
	public void afterThrowingAdvice(JoinPoint join,Exception e) {
		tx.rollback();
	}
	
}

 

三、在spring的配置文件applicationContext.xml中要開啓切面支持:

<!-- 開啓切面的動態代理支持 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

 

下面就可以進行數據庫的操作了。

一、對於增刪改,可以直接調用hibernate內置的方法進行調用,操作底層數據庫:

@Repository
public class UserDaoImpl implements IUserDao {

	private Session session;

	@Override
	public void saveUserBean(UserBean user) {
		// TODO Auto-generated method stub
		session.save(user);
	}

	@Override
	public void updateUserBean(UserBean user) {
		// TODO Auto-generated method stub
		session.update(user);
	}

	@Override
	public void deleteUserBean(UserBean user) {
		// TODO Auto-generated method stub
		session.delete(user);
	}
}

 

二、對於查詢而言,他有兩個方法(get和load)是根據id進行數據查詢

@Repository
public class UserDaoImpl implements IUserDao {

	private Session session;


	@Override
	public UserBean getUserBeanById(int id) {
		// TODO Auto-generated method stub
		return (UserBean) session.get(UserBean.class, id);
	}

	/**
	 * 
	 */
	@Override
	public UserBean loadUserBeanById(int id) {
		// TODO Auto-generated method stub
		/*
		 * get()和load()的區別: get()在查詢對象時,採用的是即時查詢方法,它從一級緩存開始,進行二級緩存,到達數據庫,它一定會得到一個最終的結果。
		 * load()在查詢對象時,採用的是延遲查詢方法,它從一級緩存開始,進行二級緩存,如果二級緩存中沒有對應的數據,它將默認數據庫中一定存在那條數據,
		 * 並返回該對象的代理對象, 直到程序發生調用時,纔去查詢,找到了就正常返回,找不到,拋異常:ObjectNotFoundException
		 */

		// 延遲加載對象,一定不能關閉Session
		return (UserBean) session.load(UserBean.class, id);
	}
}

 

三、自定義查詢語句

  • 通過查詢id返回一個Map數據(用?進行預編譯的形式)
@Override
public Map<String, Object> queryUserBeanById(Integer id) {
	// TODO Auto-generated method stub
	String hql = "select new map(u.userName as userName,u.loginName as loginName,u.password as password) From UserBean as u where id = ?";
	Query query = session.createQuery(hql);
	query.setInteger(0, id);
	List<?> datas = query.list();
	if (datas != null)
		return (Map<String, Object>) datas.get(0);
	return null;
}

在hibernate中,我們可以使用兩種方式來進行自定義語句的編寫,第一種,利用hql語句。

從上面可以看到,hql語句和sql語句有一些區別,因爲是面對對象編程了,所以UserBean對應了t_user;

通過map來接收指定的一些數據,那麼就會以hql語句中map中的別名作爲鍵,具體查出來的值爲具體的值進行返回;

createQuery(hql)是執行hql的語句的預編譯,返回一個Query類型的查詢接口,同過這個接口對預編譯的語句進行賦值,默認第一個?的位置是0。

query.list()是執行查詢結果,返回一個list集合的結果集,因爲這裏通過id只能查詢出一條結果,所以,用list的get方法,get(0)就可以獲得這條數據。

 

  • 通過查詢對象返回一個Map類型的list集合(通過取別名“:參數名”的形式進行預編譯)
@Override
public List<Map<String, Object>> findUserBeanMapByObject(UserBean user) {
	// TODO Auto-generated method stub
	String hql = "select new map(u.loginName,u.userName,u.age) From UserBean as u where u.userName like concat(:userName,'%') and u.gender = :gender";
	Query query = session.createQuery(hql);// 產生一個Query接口的實例,並針對HQL進行預編譯
	query.setProperties(user);
	return query.list();
}

通過取別名的方式來代替?,從hql語句中我們可以看到,我們傳進來是一個對象,那麼只要我們的對象屬性的名稱和hql語句中需要賦值的字段的名字保持一致就可以了,用“ :參數名”來替代上面預編譯的問號,就是“:”後面的參數名與對象屬性一致,這樣我們就可以直接用query.setProperties(對象) 的形式進行賦值了

 

如果我們用的“ :參數名”沒有和對象的屬性的名稱對應,那麼就需要如下這種方式了進行賦值(別名賦值):

@Override
	public UserBean findUserBeanByLoginNameAndPwd(String loginName, String pwd) {
		// TODO Auto-generated method stub
		/*
		 * 按照參數別名進行設值
		 */
		String hql = "From UserBean as u where u.loginName = :ln and u.password = :pwd";
		Query query = session.createQuery(hql);// 產生一個Query接口的實例,並針對HQL進行預編譯
		query.setString("ln", loginName);
		query.setString("pwd", pwd);
		List<?> datas = query.list();
		if (datas != null)
			return (UserBean) datas.get(0);
		return null;
	}

hql語句省略了前面的select部分,默認返回的是表關聯對象的集合,這裏就是UserBean的集合。

 

如果用?來進行預編譯,就用下標形式賦值:

​
// select * from t_user as u where u.login_name = ? and u.user_pwd = ?
		
// 按照位置進行設值 
String hql = "From UserBean as u where u.loginName = ? and u.password = ?"; 
Query query = session.createQuery(hql);//產生一個Query接口的實例,並針對HQL進行預編譯 
query.setString(0, loginName);//在JDBC中,第1個?下標是1,在Hibernate中,下標是0 
query.setString(1, pwd);
List<?> datas = query.list();


​

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章