`

xml解析Student.jpa.xml

    博客分类:
  • JPA
阅读更多

以下是对配置文件的解析过程

Student.jpa.xml配置文件主要描述dao接口方法的hql语句:

<?xml version="1.0" encoding="UTF-8"?>

<!-- 对StudentDaoi接口中的所有方法进行外置命名实现 -->
<hqlMap namespace="Student">
	
	<!-- jpa查询语句 -->
	<select id="findAllStudent">
		SELECT mode FROM Student mode
	</select>
	
	<!-- jpa根据id查询 ,参数类型为Integer,如果不写parameterClass,则默认为语句里面只有一个参数-->
	<select id="findByIdStudent">
		SELECT mode FROM Student mode WHERE mode.stuId=?
	</select>
	
	<!-- jpa根据name查询,参数类型为String -->
	<select id="findByNameStudent">
		SELECT mode FROM Student mode WHERE mode.stuName=?
	</select>
	
	<!-- 多个参数封装成map形式的 -->
	<select id="findByMap">
		SELECT mode FROM Student mode WHERE mode.stuName=:stuName AND mode.stuSex=:stuSex
	</select>
	
	<!-- 多个参数封装成list形式的 -->
	<select id="findByList">
		SELECT mode FROM Student mode WHERE mode.stuName=? AND mode.stuSex=?
	</select>
	
	<!-- 保存单个实体方法 -->
	<insert id="saveStudent"></insert>
	
	<!-- 更新单个实体 -->
	<update id="updateStudent"></update>
	
	<!-- 根据id删除数据 -->
	<delete id="deleteStudent">
		DELETE Student mode WHERE mode.stuId=?
	</delete>
	
	
	<!-- 批量删除操作 -->
	<delete id="batchDelete">
		<![CDATA[
			DELETE Student mode WHERE 1=1 where mode.stuId IN
		]]>
		<!-- 
			使用iterate标签,目前参数只支持list类型
			当迭代的时候,里面自动获取具体的参数对象
			下面解析出来的结果是(?,?,?,?),里面支持无限级嵌套
		 -->
		<iterate conjunction="," open="(" close=")">
			#value#
		 </iterate>
	</delete>
	
	<!-- 统计操作(不带条件的) -->
	<select id="count">
		SELECT COUNT(mode) FROM Student mode
	</select>
	
	
	<!-- 处理条件的模板ql语句 -->
	<hql id="condition_hql">
			<iterate property="conditions" prepend=" AND " conjunction=" AND ">
				<isEqual property="operation" compareValue="EQ">
					<![CDATA[
					($propertyName$ = #propertyValue#)
					]]>
				</isEqual>
				<isEqual property="operation" compareValue="GE">
					<![CDATA[
					($propertyName$ >= #propertyValue#)
					]]>
				</isEqual>
				<isEqual property="operation" compareValue="LE">
					<![CDATA[
					($propertyName$ <= #propertyValue#)
					]]>
				</isEqual>
				<isEqual property="operation" compareValue="LIKE">
					<![CDATA[
					($propertyName$ LIKE #propertyValue#)
					]]>
					
				</isEqual>
				<isEqual property="operation" compareValue="BETWEEN">
					<![CDATA[
					($propertyName$ BETWEEN #propertyValue[0]# AND #propertyValue[1]#)
					]]>
				</isEqual>
				<isEqual property="operation" compareValue="IN">
					<![CDATA[
					($propertyName$ IN
					]]>
					<iterate open="(" close="))" conjunction=","
						property="propertyValue">
						#value#
					</iterate>
				</isEqual>
			</iterate>
	</hql>
	
	<!--多属性排序模板-->
	<hql id="order_hql">
			<iterate property="orders" prepend=" ORDER BY " conjunction=",">
				<isEqual property="orderType" compareValue="ASC">
					<![CDATA[$propertyName$ ASC]]>
				</isEqual>
				<isEqual property="orderType" compareValue="DESC">
					<![CDATA[$propertyName$ DESC]]>
				</isEqual>
			</iterate>
	</hql>
	
	<!-- 统计操作(带条件的) -->
	<select id="countByCondition">
		<![CDATA[
			SELECT COUNT(mode) FROM Student mode WHERE 1=1
		]]>
		<!--支持模板hql语句-->
		<include refid="condition_hql"/>
	</select>
	
	<!-- 分页结果集查询 -->
	<select id="findByPageStudent">
		<![CDATA[
			SELECT mode FROM Student mode WHERE 1=1 
		]]>
		<include refid="condition_hql"/>
		<include refid="order_hql"/>
	</select>
	
</hqlMap>

  StudentJpaXml.java是模拟解析配置文件全过程:

package org.forever.xml;

import java.io.InputStream;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.tree.DefaultCDATA;
import org.dom4j.tree.DefaultText;
import org.forever.pagination.Condition;
import org.forever.pagination.Operation;
import org.forever.pagination.Order;
import org.forever.pagination.OrderType;
import org.forever.xxxx.domain.Student;


public class StudentJpaXml {
	private static Log log = LogFactory.getLog(StudentJpaXml.class);
	private static Document doc;
	private static StringBuffer hql;
	private static List<Object> param_list;
	
	public static void main(String[] args) throws Exception {
		SAXReader reader = new SAXReader();
		InputStream in = StudentJpaXml.class.getClassLoader()
		.getResourceAsStream("org/forever/xxxx/domain/Student.jpa.xml");
		doc = reader.read(in);
		param_list = new ArrayList<Object>();//搜集参数值的list
		Object param = null;//模拟dao接口方法的参数
		
		//findAllStudent();
		Element element = getSingleNode("/hqlMap/select[@id='findAllStudent']");
		//findByIdStudent(int id);
		element = getSingleNode("/hqlMap/select[@id='findByIdStudent']");
		param = 2;
		//findByNameStudent(String name);
		element = getSingleNode("/hqlMap/select[@id='findByNameStudent']");
		param = "陈均";
		//findByMap(Map map);
		element = getSingleNode("/hqlMap/select[@id='findByMap']");
		Map<String, Object> param_map = new HashMap<String, Object>();
		param_map.put("stuName", "chenjun");
		param_map.put("stuSex", "男");
		param = param_map;
		//findByList(List list);
		element = getSingleNode("/hqlMap/select[@id='findByList']");
		List<Object> list = new ArrayList<Object>();
		list.add("chenjun");
		list.add("男");
		param = list;
		//countByCondition(Student student);
		element = getSingleNode("/hqlMap/select[@id='countByCondition']");
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		Date startTime = dateFormat.parse("2010-02-01");
		Date endTime = dateFormat.parse("2010-03-02");
		List<Condition> conditions = Arrays.asList(
			new Condition("stuGrade", "一年级",Operation.EQ),
			new Condition("stuAge",12,Operation.GE),
			new Condition("stuAge",19,Operation.LE),
			new Condition("stuClass", "二班", Operation.EQ),
			new Condition("stuName", "%stor%", Operation.LIKE), 
			new Condition("stuAge", new Object[] { 14, 18 }, Operation.BETWEEN),
			new Condition("stuSex", Arrays.asList("男","女"),Operation.IN),
			new Condition("stuTime",new Object[]{startTime,endTime},Operation.BETWEEN)
		);
		Student student = new Student();
		student.setConditions(conditions);
		param = student;
		//findByPageStudent(Student student);
		element = getSingleNode("hqlMap/select[@id='findByPageStudent']");
		List<Order> orders = Arrays.asList(
				new Order("stuName", OrderType.ASC),
				new Order("stuAge", OrderType.DESC)
		);
		student.setOrders(orders);
		
		hql = new StringBuffer();
		
		//动态hql解析
		parseHQL(element,param);
		//解析参数
		parseParam(param);
		
		
		log.info("解析后的hql语句:" + hql.toString());
		log.info("参数个数:"+param_list.size()+"个------>");
		for (int i = 0; i < param_list.size(); i++) {
			log.info("第" + (i+1) + "个参数值:" + param_list.get(i)); 
		}
		
	}
	
	//解析非引用类型参数
	private static void parseParam(Object param) {
		if (isPrimitive(param)) {
			param_list.add(param);
		} else if (param instanceof List<?>) {
			param_list = (List) param;
		} else if (param instanceof Map<?, ?>) {
			Map<String,Object> map = (Map) param;
			for (String key : map.keySet()) {
				String name = ":" + key;
				int start = hql.indexOf(name);
				int end = start + name.length();
				hql.replace(start, end, "?");
				param_list.add(map.get(key));
			}
		}		
		
	}

	/**
	 * 解析元素
	 * 该内容可能是以下几种情况:文本、元素、文档注释,CDATA
	 * 元素可能又会有上面的情况,所以是递归的解析
	 * 参数有以下3种:基本类型,集合类型(Map,List),引用类型
	 * 该递归方法只考虑引用类型
	 * @param element 待解析的标签元素
	 * @param param 接口方法的参数
	 * @param hql hql字符串
	 * @param param_list 存放参数集合
	 * @throws Exception 
	 */
	public static void parseHQL(Element element,Object param) throws Exception{
		
		for (Object item : element.content()) {
			if(item instanceof DefaultText){
				parseText(item,param);
			}else if(item instanceof DefaultCDATA){
				parseCDATA(item,param);
			}else if(item instanceof Element){
				parseElement(item,param);
			}
		}
	}
	
	//解析元素标签
	private static void parseElement(Object item, Object param) throws Exception {
		//元素有以下几种:
		//include,isEqual,iterate
		Element element = (Element)item;
		String name = element.getName();
		if("include".equals(name)){//模板标签
			String refid = element.attributeValue("refid");//获取引用的sqlid
			//找到该元素的模板进行解析,递归操作
			Element hqlE = getSingleNode("/hqlMap/hql[@id='"+refid+"']");
			if(hqlE==null){
				throw new RuntimeException("配置文件不存在id="+refid+"的标签!");
			}
			parseHQL(hqlE, param);
		}else if("iterate".equals(name)){
			String property = element.attributeValue("property");//参数的属性
			String prepend = element.attributeValue("prepend");//开始字符串
			String conjunction = element.attributeValue("conjunction");//迭代一次所加字符串
			String open = element.attributeValue("open");
			String close = element.attributeValue("close");
			if(null != prepend){
				hql.append(prepend);
			}
			if(null != open){
				hql.append(open);
			}
			
			//目前迭代标签只支持List类型的
			Field field = getField(param, property);
			field.setAccessible(true);
			List list = new ArrayList<Object>();
			try {
				list = (List)field.get(param);
			} catch (Exception e) {
				e.printStackTrace();
				throw new RuntimeException("获取迭代标签属性值失败!");
			} 
			if(conjunction==null){
				conjunction = " ";
			}
			
			for (Object object : list) {
				parseHQL(element, object);
				hql.append(conjunction);
			}
			
			hql.delete(hql.lastIndexOf(conjunction), hql.length());
			if(null != close){
				hql.append(close);
			}
			
		} else if("isEqual".equals(name)){
			String property = element.attributeValue("property");//属性
			String compareValue = element.attributeValue("compareValue");//比较的值
			Field field = getField(param, property);
			try {
				field.setAccessible(true);
				Object value = field.get(param);
				if(compareValue!=null && compareValue.equals(value.toString())){//满足条件
					parseHQL(element, param);
				}
			} catch (Exception e) {
				e.printStackTrace();
				throw new RuntimeException("获取迭代标签属性值失败!");
			} 
			
		}
		
		
		
	}
	
	//反射获取属性字段
	private static Field getField(Object param, String property){
		Field field = null;
		try {
			field = param.getClass().getDeclaredField(property);
		} catch (Exception e1) {
			// 去父类中找寻,在此支持一级父类找寻,如果多级,那就递归呗
			try {
				field = param.getClass().getSuperclass().getDeclaredField(property);
			} catch (Exception e) {
				e.printStackTrace();
				throw new RuntimeException("反射获取属性字段失败!");
			} 
		}
		return field;
	}

	//解析元素据类型
	private static void parseCDATA(Object element, Object param) throws Exception {
		DefaultCDATA cdata = (DefaultCDATA)element;
		String text = cdata.getText().trim();
		log.info("CDATA文本内容:" + text);
		if("".equals(text)){
			return;
		}
		
		hql.append(" " + text + " ");
		parseJH(param);
		parse$(param);
		
	}

	/**
	 * 是否是基本类型(8种基本类型和包装类型)
	 * @param param
	 * @return
	 */
	public static boolean isPrimitive(Object param) {
		// 等等....
		if (param == null)
			return false;

		if (param.getClass().isPrimitive() || param instanceof Integer
				|| param instanceof String || param instanceof Long
				|| param instanceof Short || param instanceof Double
				|| param instanceof Float || param instanceof Byte
				|| param instanceof Boolean) {
			return true;	
		}

		return false;
	}
	
	
	
	
	//解析文本类型
	public static void parseText(Object element,Object param) throws Exception{
		DefaultText dt = (DefaultText)element;
		String text = dt.getText().trim();
		log.info("text文本内容:" + text);
		if("".equals(text)){
			return;
		}
		
		hql.append(" " + text + " ");
		parseJH(param);
		parse$(param);
		
	}
	
	//解析$符号的表达式
	private static void parse$(Object param) throws Exception {
		log.info("解析$号.........");
		String str = "$";// $?$形式的解析
		int start = hql.indexOf(str,0);// 第一次$号出现的起始位置
		int end = hql.indexOf(str,start+1);// 第一次$号出现的结束位置
		while(start !=-1 && end != -1){// 可能有多个$号
			String property = hql.substring(start+1, end);
			//propertyValue[0]这种情况
			int start_ = property.indexOf("[");
			Object value = null;
			if(start_!=-1){//数组的情况
				int index = Integer.parseInt(property.substring(start_+1, start_+2));//获取下标
				Field field = getField(param, property);
				field.setAccessible(true);
				value = field.get(param);
				value = ((Object[])value)[index];
				
			} else if(isPrimitive(param)){
				value = param;
			}
			else{// 普通属性
				Field field = getField(param, property);
				field.setAccessible(true);
				value = field.get(param);
			}
			
			hql.replace(start, end + 1, value.toString());// 把语句中的$?$符号替换成?号
			start = hql.indexOf(str, start);// 获取下一次$号出现的起始位置
			end = hql.indexOf(str, start + 1);// 获取下一次$号出现的结束位置
		}//end while
	}

	//解析#符号的表达式
	public static void parseJH(Object param) throws Exception{
		log.info("解析#号.........");
		String str = "#";// #?#形式的解析
		int start = hql.indexOf(str,0);// 第一次#号出现的起始位置
		int end = hql.indexOf(str,start+1);// 第一次#号出现的结束位置
		while(start !=-1 && end != -1){// 可能有多个#号
			String property = hql.substring(start+1, end);
			//propertyValue[0]这种情况
			int start_ = property.indexOf("[");
			Object value = null;
			if(start_!=-1){//数组的情况
				int index = Integer.parseInt(property.substring(start_+1, start_+2));//获取下标
				Field field = getField(param, property.replaceFirst("\\["+index+"\\]", ""));
				field.setAccessible(true);
				value = field.get(param);
				param_list.add(((Object[])value)[index]);
				
			} else if(isPrimitive(param)){
				param_list.add(param);
			}
			else{// 普通属性
				Field field = getField(param, property);
				field.setAccessible(true);
				value = field.get(param);
				param_list.add(value);
			}
			
			hql.replace(start, end + 1, "?");// 把语句中的#?#符号替换成?号
			start = hql.indexOf(str, start);// 获取下一次#号出现的起始位置
			end = hql.indexOf(str, start + 1);// 获取下一次#号出现的结束位置
		}//end while
		
		
		
	}
	
	//根据xpath获取单节点元素
	public static Element getSingleNode(String xpathExpression){
		return (Element)doc.selectSingleNode(xpathExpression);
	}

}

 

 涵盖了对单对象的所有情况的一个操作。当然这种通用写法肯定会降低效率的哈.

以上依赖的jar包:dom4j-1.6.1.jar,jaxen-1.1.1.jar,pagination.jar,commons-logging.jar

log4j.properties:

##LOGGERS##
log4j.rootLogger=INFO,console
##APPENDERS##
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=d\:\\log.txt
log4j.appender.file.MaxFileSize=1024KB
##LAYOUTS##
log4j.appender.console.layout=org.apache.log4j.SimpleLayout
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm} %t %p- %m%n

 

0
2
分享到:
评论

相关推荐

    student.rar

    2. **pom.xml** - 这是Maven项目的配置文件,它定义了项目依赖,包括Spring Boot的starter父 pom,以及其他如Spring Security、Spring Data JPA等必要的库。通过分析这个文件,我们可以了解项目的完整技术栈和版本...

    springdatajpa.rar

    在Spring Boot项目中,只需要在`pom.xml`添加Spring Data JPA和相应的数据库驱动依赖,然后在`application.properties`或`application.yml`中配置数据库连接信息,例如: ```properties spring.datasource.url=...

    利用springboot-jpa实现对数据库的增删改查操作

    public interface StudentRepository extends JpaRepository&lt;Student, Long&gt; { } ``` `JpaRepository`接口提供了基本的CRUD操作,如`save()`, `findAll()`, `findById()`, `deleteById()`等。 现在,我们可以在...

    Hibernate JPA

    databaseName=student"/&gt; &lt;property name="hibernate.max_fetch_depth" value="1"/&gt; &lt;property name="hibernate.hbm2ddl.auto" value="update"/&gt; &lt;property name="hibernate.jdbc.fetch_size" value="18"/&gt; ...

    Java spring boot链接mql数据库 JDBC

    public interface StudentRepository extends JpaRepository&lt;Student, Long&gt; { } ``` 现在,我们可以在Controller中注入Repository,并实现简单的数据库操作,如查询所有学生: ```java import org.spring...

    配置hibernate

    创建一个Student.hbm.xml映射文件,用于映射Student实体类与数据库表的关系。 ```xml &lt;?xml version="1.0"?&gt; &lt;!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" ...

    hibernate many to one

    例如,在`Student.hbm.xml`和`Class.hbm.xml`中: - 在`Student.hbm.xml`: ```xml &lt;many-to-one name="class" column="class_id" class="com.example.Class" cascade="all" /&gt; ``` 这表示`Student`实体有一个名为`...

    JPA 配置文件

    ### JPA 配置文件与持久化概念解析 #### JPA 持久化:ORM技术的核心 在软件开发中,尤其是涉及数据库交互的应用场景,持久化层的设计至关重要。JPA(Java Persistence API)作为Java平台上的标准持久化规范,为...

    Spring JPA 项目简单实现

    1. **添加依赖**:在项目的`pom.xml`或`build.gradle`文件中,引入Spring Boot的`spring-boot-starter-data-jpa`依赖,它包含了Spring JPA和所需的数据库驱动。 2. **配置数据源**:在`application.properties`或`...

    Java EE 6企业级应用开发教程:第10章 JPA.ppt

    - **ORM映射元数据**:JPA支持XML和JDK 5.0注解两种元数据形式,描述对象和数据库表之间的映射。 - **JPA API**:提供了一套操作实体对象的接口,用于执行创建(Create)、读取(Read)、更新(Update)和删除...

    学生管理系统jpa+jsp+servlet

    在学生管理系统中,JPA可以用来定义实体类(如Student实体),映射到数据库中的表,进行增删查改操作。 JavaServer Pages(JSP)是一种动态网页技术,它允许开发者将HTML、CSS、JavaScript与Java代码混合在一起,以...

    5分钟利用Myeclipse快速搭建ssh(JPA)环境,自动生成dao,model

    ### 使用MyEclipse快速搭建SSH(JPA)环境并自动生成DAO与Model #### 概述 本篇文章将详细介绍如何使用MyEclipse集成开发环境在五分钟内快速搭建SSH(Spring、Struts2、Hibernate)结合JPA技术的应用环境,并自动...

    Stu_ssh.rar

    2. **实体类(Entity)**:如Student.java,这些类代表数据库表的结构,通常会有一些getter和setter方法,以及JPA或Hibernate注解。 3. **持久化层(DAO,Data Access Object)**:例如StudentDAO.java,这些类包含...

    hibernate映射和查询

    List&lt;Student&gt; students = session.createQuery("from Student").list(); ``` 2. **QBC**:基于 Java 接口的查询,提供了一种类型安全的方式。例如,获取所有学生: ```java Criteria criteria = session....

    Student-Course_JPA_Assessment

    《Student-Course JPA Assessment: 探索Java持久层框架的魅力》 在现代软件开发中,数据管理和持久化是至关重要的部分。Java平台提供了一系列工具和技术来处理这些问题,其中之一便是Java Persistence API(JPA)。...

    Hibernate annotation JPA 一对多,多对多

    在实际应用中,除了实体类的注解外,我们还需要在`persistence.xml`文件中配置持久化单元,指定使用的数据库连接信息、实体类等。这样,Hibernate才能根据这些配置进行数据库操作。 5. **懒加载与立即加载**: ...

    hibernate实现多对一得单项关联

    例如,如果有一个`Student`类和一个`Teacher`类,`Student`可以有多位老师,而`Teacher`只对应一个班级,那么在`Student.hbm.xml`文件中,我们这样配置: ```xml &lt;class name="com.example.Student"&gt; &lt;!-- ... --&gt;...

    spring boot 集成十几种demo

    通过在`pom.xml`中引入JPA和数据库驱动的依赖,设置`application.properties`中的数据源属性,以及定义实体类和Repository接口,我们就能使用Spring Data JPA提供的便捷方法进行CRUD操作。 邮件服务的集成通常是...

Global site tag (gtag.js) - Google Analytics