做了四年的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的自定义查询能力极大地提高了开发效率,通过HQL、命名查询、Criteria API和直接SQL查询,我们可以根据项目需求选择最合适的方式来处理数据。`QueryDAO`和`QueryNamedDAO`的实现细节可能包含了对这些查询...
在`hibernate.cfg.xml`或实体类的`@NamedQuery`注解中定义命名查询: ```xml <query name="getStudentsOverAge"> FROM Student WHERE age > 20 </query> ``` 在代码中使用: ```java Query query = session...
5. **命名查询(Named Queries)**: 如果某些查询模式经常被使用,可以定义命名查询,将其写入XML映射文件中,以提高代码可读性和复用性。 6. **动态HQL**: 对于更动态的查询,可以构建HQL字符串,但这可能会...
- `findByNamedQuery(queryName, params)`: 使用预定义的命名查询,这些查询可以在`hbm.xml`映射文件中定义,或通过`@NamedQuery`注解在实体类上声明。 - `countByExample(entity)`: 计算满足特定条件的记录数,...
@NamedQuery(name="User.findAll", query="SELECT u FROM User u") ``` 2. `@Query` JPA的动态查询,可以直接在注解中编写HQL或JPQL查询语句。 六、事务管理注解 1. `@Transactional` 标记在方法上,表示该...
public void namedQuery(Session session) { Query<Student> query = session.getNamedQuery("findStudentsByName"); query.setParameter(0, "John Doe"); List<Student> students = query.list(); // 处理查询...
在配置文件中,你可以定义命名查询(Named Query),例如: ```xml <hibernate-mapping> <!-- class mapping details --> <query name="findUsersByName"> <![CDATA[from User as u where u.name = ?]]> </...
例如,可以直接在Entity类上使用`@NamedQuery`和`@NamedNativeQuery`注解来定义HQL和SQL查询,这种方式更具有代码内联性,但可能会增加实体类的复杂性。 【优点总结】 1. 维护分层架构:将查询语句集中管理,避免...
以及`List<T> findByNamedQuery(String namedQuery, Map, Object> params)`,使用预定义的命名查询。 3. **分页查询**:在大型项目中,通常需要实现分页功能,我们可以提供`List<T> findPage(int pageSize, int ...
- `@NamedQuery`: 预定义命名查询,可以在多个地方重用。 7. **缓存** - `@Cacheable`: 标记实体类或方法支持缓存,提高性能。 - `@Cache`: 配置缓存区域和策略,如读写策略、时间戳等。 8. **转换器与自定义...
- `@NamedQuery`: 预编译的命名查询,可以在多个地方重复使用。 **8. 最新版本与兼容性** Hibernate Annotation API的最新版本通常与Hibernate ORM保持同步,提供更多的特性和改进。确保你的项目使用的是与所使用的...
- 命名查询(Named Query)是预定义的 HQL 查询,可以在 XML 映射文件中定义,然后通过 `session.getNameQuery("queryName")` 调用。 7. **查询结果处理**: - `uniqueResult()` 返回查询结果的唯一对象,如果...
命名查询(Named Query)是预先定义在映射文件或实体类上的HQL或SQL查询,可提高代码的可读性和可维护性。 10. **缓存机制** Hibernate 提供了第一级缓存(Session级别)和第二级缓存(SessionFactory级别)。第一...
同时,`@NamedQuery`可以定义预编译的命名查询,提高性能。 【Hibernate验证器】`Hibernate Validator`是Hibernate提供的一个验证框架,它允许在实体Bean上添加如`@NotNull`,`@Size`等验证规则,确保数据的正确性...
- **动态查询**:利用 **@NamedQuery** 定义命名查询或使用 Criteria API 和 Query API 动态构建查询条件。 #### 六、最佳实践 1. **统一编码风格**:为了保持代码的一致性和可读性,建议团队内部统一使用一致的...
- **查询**:`@NamedQuery`、`@NamedNativeQuery`。 #### 五、通过XML覆写元数据 虽然本文档主要讲解了注解式开发,但有时也需要通过XML文件来覆写部分元数据。这主要包括以下几个方面: - **全局级别的元数据**...
- **命名查询**:使用 `@NamedQuery` 注解定义命名查询,便于代码中调用。 - **原生 SQL 查询映射**:使用 `@NamedNativeQuery` 定义原生 SQL 查询,通过 `@SqlResultSetMapping` 注解映射查询结果。 #### 五、元...
外置命名查询(Externalizing named queries) 10.4.2. 过滤集合 10.4.3. 条件查询(Criteria queries) 10.4.4. 使用原生SQL的查询 10.5. 修改持久对象 10.6. 修改脱管(Detached)对象 10.7. 自动状态检测 10.8. 删除...
#### 实验十三:Query-namedQuery **实验目的:** - 理解并使用`namedQuery`功能。 **实验步骤:** - 定义一个命名查询并在`SessionFactory`中注册它,然后使用`Session`的`getNamedQuery`方法执行查询。 #### ...