模拟hibernate读配置文件生成sql
今天温习了下尚学堂马士兵老师的hibernate视频,其中讲解模拟hibernate读取配置文件并生成sql部分内容。以前自己不用框架的时候也去模拟过持久层的处理,但最终效果总是不理想。而且现在想想,一些细节部分并没有能够很好的处理。其实这个模拟用的关键知识点不多,就两个:
- 读取并解析xml配置文件
- 使用反射机制根据属性名得到获取属性getProperty()的方法,根据方法的返回值类型设置PreparedStatement参数类型setXXX
简单模拟,学生类以及配置文件如下,模拟目标是要完成学生入库持久化这样的操作。
<?xml version="1.0"?> <hibernate-mapping package="com.hibernate.model"> <class name="Student" table="_Student"> <id column="_id" name="id" /> <property column="_name" name="name" /> <property column="_age" name="age" /> </class> </hibernate-mapping>
public class Student { private int id; private String name; private int age; // getXXX( ) // setXXX(..) }
下面是模拟关键类,其中解决了以下难点:
- 插入的数据顺序不知道
- 插入数据读取的方法不知道,调用的getXXX不知道
- 插入数据的类型不知道,ps.setXXX不知道
package com.hibernate.simulation; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.input.SAXBuilder; import com.google.gson.Gson; import com.hibernate.model.Student; public class Session { String tableName ; Map<String,String> config = new HashMap<String,String>(); private Session() throws Exception{ SAXBuilder sb = new SAXBuilder(); Document doc = sb.build("bin/com/hibernate/model/Student.hbm.xml"); Element clazz = doc.getRootElement().getChild("class"); tableName = clazz.getAttributeValue("table"); List<Element> list = (List<Element>)clazz.getChildren(); for(int i=0; i<list.size(); i++){ Element e = list.get(i); config.put(e.getAttributeValue("column"), e.getAttributeValue("name")); } } public static void main(String[] args) throws Exception{ Session session = new Session(); String sql = session.createSql(); System.out.println(sql); Student s = new Student(); s.setId(2); s.setAge(2); s.setName("2"); session.save(s); } private void save(Student student) throws Exception { String sql = createSql(); Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/hibernate","root","1"); PreparedStatement ps = conn.prepareStatement(sql); // String[] methodName = new String[config.size()]; int i=0; Iterator<String> itr = config.keySet().iterator(); while(itr.hasNext()){ String propertyName = config.get(itr.next()); methodName[i] = "get" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1); i++; } System.out.println(new Gson().toJson(methodName).toString()); for(int j=0; j<methodName.length; j++){ Method method = student.getClass().getMethod(methodName[j]); Class clazz = method.getReturnType(); if(clazz.getName().equals("int")){ Integer propertyValue = (Integer)method.invoke(student); ps.setInt(j+1, propertyValue); } if(clazz.getName().equals("java.lang.String")){ ps.setString(j+1, (String)method.invoke(student)); } } ps.executeUpdate(); ps.close(); conn.close(); } private String createSql(){ StringBuffer sql = new StringBuffer(); String str1=""; for(String column : config.keySet()){ str1 += column + ","; } str1 = str1.substring(0, str1.length() - 1); String str2 =""; for(int i=0; i<config.size(); i++){ str2 += "?,"; } str2 = str2.substring(0, str2.length() - 1); sql.append("insert into ").append(tableName) .append("(").append(str1).append(")") .append(" values (").append(str2).append(")"); return sql.toString(); } }
以上代码是草草而就,缺陷不少,空了再改,但关键核心思路值得参考学习,备忘!