Hibernate的命名查询(NamedQuery)

做了四年的JavaEE开发,用了hibernate四年,今天才知道,原来还可以把HQL语句或SQL语句写在Hibernate实体类对应的映射文件中的。

打开Hibernate的Session的源码,我们可以看到有一个getNamedQuery(String name);的方法,如下:

/**
	 * Obtain an instance of <tt>Query</tt> for a named query string defined in the
	 * mapping file.
	 *
	 * @param queryName the name of a query defined externally
	 * @return Query
	 * @throws HibernateException
	 */
	public Query getNamedQuery(String queryName) throws HibernateException;

 

这个方法就是可以执行定义在Hibernate实体类映射文件中的HQL或Sql语句。

具体做法下面我一一讲解,首先测试在映射文件中定义HQL语句。

我在User实体类的映射文件中定义了一个name为getUserByName的HQL查询语句,代码如下:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"D:\tools\hibernate\dtd\hibernate-mapping-3.0.dtd">
<hibernate-mapping 
	package="com.xigua.domain">
	<class name="User">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
		<property name="birthday"/>
	</class>
	
	<!-- 定义一个查询,名称为getUserByName -->
	<query name="getUserByName">
		<![CDATA[from User where name = :name]]>
	</query>
</hibernate-mapping>

 

然后编写测试类使用Session中的getNamedQuery(String name)方法进行测试,代码如下:

package com.xigua.test;

import java.util.Date;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.xigua.domain.User;
import com.xigua.utils.HibernateUtil;

public class Test9 {

	public static void main(String[] args) {
		addUser();
		String name = "xigua";
		List<User> list = namedQuery(name);
		if(list != null && !list.isEmpty()) {
			for(User user : list) {
				System.out.println(user.getId() + ", " + user.getName() + ", " + user.getBirthday());
			}
		}
	}
	
	public static void addUser() {
		Session session = null;
		Transaction tx = null;
		try{
			session = HibernateUtil.getSession();
			tx = session.beginTransaction();
			User user = new User();
			user.setName("xigua");
			user.setBirthday(new Date());
			session.save(user);
			
			user = new User();
			user.setName("donggua");
			user.setBirthday(new Date());
			session.save(user);
			tx.commit();
		} catch(Exception e) {
			if(tx != null) {
				tx.rollback();
			}
		} finally {
			if(session != null) {
				session.close();
			}
		}
	}
	
	public static List<User> namedQuery(String name) {
		Session session = null;
		try{
			session = HibernateUtil.getSession();
			Query query = session.getNamedQuery("getUserByName");
			query.setParameter("name", name);
			return query.list();
		}catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(session != null) {
				session.close();
			}
		}
		
		return null;
	}

}

 注意红色部分代码。

 

在映射文件中除了可以定义HQL语句,也还是可以定义Sql语句的。

前面的User实体类的映射文件修改如下:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"D:\tools\hibernate\dtd\hibernate-mapping-3.0.dtd">
<hibernate-mapping 
	package="com.xigua.domain">
	<class name="User">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
		<property name="birthday"/>
	</class>
	
	<!-- 定义一个查询,名称为getUserByName 
	<query name="getUserByName">
		<![CDATA[from User where name = :name]]>
	</query>
	-->
	
	<sql-query name="getUserByName">
		<![CDATA[select id, name from user where name = :name]]>
	</sql-query>
</hibernate-mapping>

 

测试代码如下:

package com.xigua.test;

import java.util.Date;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.xigua.domain.User;
import com.xigua.utils.HibernateUtil;

public class Test10 {
	
	public static void main(String args[]) {
		addUser();
		String name = "xigua";
		User user = namedSqlQuery(name);
		if(user != null) {
			System.out.println(user.getId() + ", " + user.getName());
		}
		
	}
	
	public static void addUser() {
		Session session = null;
		Transaction tx = null;
		try{
			session = HibernateUtil.getSession();
			tx = session.beginTransaction();
			User user = new User();
			user.setName("xigua");
			user.setBirthday(new Date());
			session.save(user);
			
			user = new User();
			user.setName("donggua");
			user.setBirthday(new Date());
			session.save(user);
			tx.commit();
		} catch(Exception e) {
			if(tx != null) {
				tx.rollback();
			}
		} finally {
			if(session != null) {
				session.close();
			}
		}
	}
	
	public static User namedSqlQuery(String name) {
		Session session = null;
		try{
			session = HibernateUtil.getSession();
			Query query = session.getNamedQuery("getUserByName");
			query.setParameter("name", name);
			Object[] obj = (Object[]) query.uniqueResult();
			if(obj != null) {
				User user = new User();
				user.setId(Long.valueOf(obj[0].toString()));
				user.setName(obj[1].toString());
				return user;
			}
		}catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(session != null) {
				session.close();
			}
		}
		
		return null;
	}

}

 

映射文件中还有些其它的配置,暂时还没具体搞懂,比如下面红色的代码:

<sql-query name="getUserByName">
		<![CDATA[select id, name from user where name = :name]]>
		<query-param name="name" type="string"/>
		<return></return>
		<return-join alias="" property=""></return-join>
		<return-scalar column=""/>
		<synchronize table=""/>
	</sql-query>

 

 

还有一点像说明的是<query>跟<sql-query>的配置是可以放到<class>节点里面的。

我现在是放在<class>节点外面,表示全局可用,这里需要注意不要跟其它映射文件中定义的<query>或<sql-query>同名。

如果将<query>或<sql-query>放在<class>节点里面,在java代码中使用的时候需要将package名跟class名都写上,具体见下面配置的映射文件代码跟测试代码。

映射文件代码:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"D:\tools\hibernate\dtd\hibernate-mapping-3.0.dtd">
<hibernate-mapping 
	package="com.xigua.domain">
	<class name="User">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
		<property name="birthday"/>
		
		<!-- 定义一个查询,名称为getUserByName (这里将<query>放到<class>节点里面来)--> 
		<query name="getUserByName">
			<![CDATA[from User where name = :name]]>
		</query>
	
	</class>
	
	
	
</hibernate-mapping>

 java测试代码(注意下图红色部分字符串)

package com.xigua.test;

import java.util.Date;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.xigua.domain.User;
import com.xigua.utils.HibernateUtil;

public class Test9 {

	public static void main(String[] args) {
		addUser();
		String name = "xigua";
		List<User> list = namedQuery(name);
		if(list != null && !list.isEmpty()) {
			for(User user : list) {
				System.out.println(user.getId() + ", " + user.getName() + ", " + user.getBirthday());
			}
		}
	}
	
	public static void addUser() {
		Session session = null;
		Transaction tx = null;
		try{
			session = HibernateUtil.getSession();
			tx = session.beginTransaction();
			User user = new User();
			user.setName("xigua");
			user.setBirthday(new Date());
			session.save(user);
			
			user = new User();
			user.setName("donggua");
			user.setBirthday(new Date());
			session.save(user);
			tx.commit();
		} catch(Exception e) {
			if(tx != null) {
				tx.rollback();
			}
		} finally {
			if(session != null) {
				session.close();
			}
		}
	}
	
	public static List<User> namedQuery(String name) {
		Session session = null;
		try{
			session = HibernateUtil.getSession();
			Query query = session.getNamedQuery("com.xigua.domain.User.getUserByName");
			query.setParameter("name", name);
			return query.list();
		}catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(session != null) {
				session.close();
			}
		}
		
		return null;
	}

}

 

你可能感兴趣的:(Hibernate,NamedQuery)