作为一款优秀封装dao层的框架,被众多同仁使用,这篇文章再为学习hibernate的朋友提供一个理解原理的参考。
下面是我模拟hibernate的运行原理写的一个程序,希望对大家有用!
首先跟大家分享框架结构图
第一步,创建Execute对象
第二步,创建ConfigManager对象
第三步,创建configFile对象,configFile包含数据库连接部分和实体类映射文件
第四步,读取数据库连接映射文件盒实体类配置文件
第五步,调用Execute对象的get方法
第六步,根据实体映射类构造SQL语句
第七步,设置对象属性,返回实体对象
看完结构图,由我带大家浏览一下设计流程:
1、首先创建一个Web Project
2、然后需要导入一个解析XML文件的jar包dom4j-1.6.1.jar和java访问oracle数据库的jar包classes12.jar
3、需要在src下写一个名叫Config.dtd文件和Mapping.dtd,这个文件用于规范配置文件
a、Config.dtd
<!ELEMENT hibernate (session-factory)>
<!ELEMENT session-factory (property*,mapping*)>
<!ELEMENT property (#PCDATA)>
<!ATTLIST property
name CDATA #REQUIRED>
<!ELEMENT mapping EMPTY>
<!ATTLIST mapping
resource CDATA #REQUIRED>
b、Mapping.dtd
<!ELEMENT hibernate-mapping (class)>
<!ELEMENT class (id,property*)>
<!ATTLIST class
name CDATA #REQUIRED
table CDATA #REQUIRED>
<!ELEMENT id EMPTY>
<!ATTLIST id
name CDATA #REQUIRED
type CDATA "java.lang.String"
column CDATA #REQUIRED>
<!ELEMENT property EMPTY>
<!ATTLIST property
name CDATA #REQUIRED
type CDATA "java.lang.String"
column CDATA #REQUIRED>
4、下面就开始写各个类
a、实体映射文件MappingFile类和映射属性Attribute类
package com.huan.frame;
import java.util.*;
public class MappingFile {
private String name;
private String className;
private String tableName;
private String primary;
private List<Attribute> attlist = new ArrayList<Attribute>();
public void addAttribute(Attribute att){
attlist.add(att);
}
public List<Attribute> getAttlist() {
return attlist;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public String getPrimary() {
return primary;
}
public void setPrimary(String primary) {
this.primary = primary;
}
}
package com.huan.frame;
public class Attribute {
private String name;
private String type;
private String column;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getColumn() {
return column;
}
public void setColumn(String column) {
this.column = column;
}
}
b、实例化MappingManager类
package com.huan.frame;
public class MappingManager {
public static Object createInstance(MappingFile file){
try {
return Class.forName(file.getName()).newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
c、配置文件ConfigFile类
package com.huan.frame;
import java.util.*;
public class ConfigFile {
private String connectionDriver;
private String connectionURL;
private String connectionUser;
private String connectionPassword;
private Map<String,MappingFile> mappings = new HashMap<String,MappingFile>();
public void addMapping(MappingFile mf){
mappings.put(mf.getName(), mf);
}
public MappingFile getMapping(String name){
return mappings.get(name);
}
public String getConnectionDriver() {
return connectionDriver;
}
public void setConnectionDriver(String connectionDriver) {
this.connectionDriver = connectionDriver;
}
public String getConnectionURL() {
return connectionURL;
}
public void setConnectionURL(String connectionURL) {
this.connectionURL = connectionURL;
}
public String getConnectionUser() {
return connectionUser;
}
public void setConnectionUser(String connectionUser) {
this.connectionUser = connectionUser;
}
public String getConnectionPassword() {
return connectionPassword;
}
public void setConnectionPassword(String connectionPassword) {
this.connectionPassword = connectionPassword;
}
}
d、配置管理ConfigManager类
package com.huan.frame;
import java.io.InputStream;
import java.sql.*;
import java.util.*;
import org.dom4j.*;
import org.dom4j.io.SAXReader;
public class ConfigManager {
private ConfigFile config;
public ConfigManager(){
config = new ConfigFile();
readConfig();
}
public void readConfig(){
try {
InputStream is = getClass().getResourceAsStream("/Config.xml");
if(is == null) throw new Exception("hibernate:配置文件未找到!");
Document doc = new SAXReader().read(is);
Element root = doc.getRootElement();
Iterator<Element> sessionNode = root.elementIterator("session-factory");
Element child = sessionNode.next();
Iterator<Element> propertys = child.elementIterator("property");
Element node = null;
while(propertys.hasNext()){
node = propertys.next();
if(node.attributeValue("name").trim().equals("connection.driver"))
config.setConnectionDriver(node.getTextTrim());
if(node.attributeValue("name").trim().equals("connection.uri"))
config.setConnectionURL(node.getTextTrim());
if(node.attributeValue("name").trim().equals("connection.user"))
config.setConnectionUser(node.getTextTrim());
if(node.attributeValue("name").trim().equals("connection.password"))
config.setConnectionPassword(node.getTextTrim());
}
Iterator<Element> mappings = child.elementIterator("mapping");
while(mappings.hasNext()){
node = mappings.next();
MappingFile mf = readMapping(node.attributeValue("resource"));
config.addMapping(mf);
}
System.out.println("hibernate:配置文件加载完毕!");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public MappingFile readMapping(String path){
MappingFile mapping = new MappingFile();
try {
if(path == null) throw new Exception("hibernate:映射文件未找到!");
mapping.setName(path.substring(5,path.lastIndexOf(".")).replaceAll("/", "."));
System.out.println("hibernate:映射文件名:" + mapping.getName());
path = path.substring(4);
System.out.println("hibernate:映射路径名:" + path);
Properties properties = new Properties();
InputStream is = getClass().getResourceAsStream(path);
if(is == null) throw new Exception("hibernate:映射文件加载失败!");
Document doc = new SAXReader().read(is);
Element root = doc.getRootElement();
Iterator<Element> sessionNode = root.elementIterator("class");
Element child = sessionNode.next();
mapping.setClassName(child.attributeValue("name"));
mapping.setTableName(child.attributeValue("table"));
Iterator<Element> ids = child.elementIterator("id");
Element id = ids.next();
mapping.setPrimary(id.attributeValue("name"));
Attribute attId = new Attribute();
attId.setName(id.attributeValue("name"));
attId.setType(id.attributeValue("type"));
attId.setColumn(id.attributeValue("column"));
mapping.addAttribute(attId);
Iterator<Element> propertys = child.elementIterator("property");
Element property = null;
Attribute att = null;
System.out.println("hibernate:进入属性加载循环!");
while(propertys.hasNext()){
property = propertys.next();
att = new Attribute();
att.setName(property.attributeValue("name"));
att.setType(property.attributeValue("type"));
att.setColumn(property.attributeValue("column"));
mapping.addAttribute(att);
}
System.out.println("hibernate:映射文件加载完毕!");
return mapping;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public MappingFile getMapping(String name){
return config.getMapping(name);
}
public Connection openConnection(){
Connection conn = null;
try {
Class.forName(config.getConnectionDriver());
conn = DriverManager.getConnection(config.getConnectionURL()
,config.getConnectionUser(),config.getConnectionPassword());
return conn;
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public void closeAll(Connection conn,PreparedStatement pstmt,ResultSet rs){
try {
if(rs != null) rs.close();
if(pstmt != null) pstmt.close();
if(conn != null) conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
e、执行Execute类
package com.huan.frame;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.List;
public class Execute {
private ConfigManager manager = new ConfigManager();
public Object get(Class c,int id){
String[] str = c.toString().split(" ");
MappingFile mf = manager.getMapping(str[1]);
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
Class clazz = Class.forName(mf.getName());
Object obj = MappingManager.createInstance(mf);
if(obj == null) throw new Exception("hibernate:反射生成对象实例化失败!");
conn = manager.openConnection();
if(conn == null) throw new Exception("hibernate:连接数据库失败!");
String sql = buildSql(mf);
System.out.println("hibernate:" + sql);
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, id);
rs = pstmt.executeQuery();
int size = mf.getAttlist().size();
String methodName = null;
String type = null;
Method[] methods = clazz.getDeclaredMethods();
while(rs.next()){
System.out.println("hibernate:读取数据...");
for(int i = 0; i < size; i++){
methodName = buildMethodName(mf.getAttlist().get(i).getName());
System.out.println("hibernate:方法名:" + methodName);
for (Method method : methods) {
System.out.println("hibernate:遍历方法名..." + method.getName());
if(methodName.equals(method.getName())){
type = mf.getAttlist().get(i).getType();
System.out.println("hibernate:参数类型:" + type);
if(type.equals("java.lang.Integer")){
System.out.println("hibernate:" + method.getName() + "赋值");
method.invoke(obj, rs.getInt(i + 1));
break;
}
if(type.equals("java.lang.String")){
System.out.println("hibernate:" + method.getName() + "赋值");
method.invoke(obj, rs.getString(i + 1));
break;
}
}
}
}
}
return obj;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
manager.closeAll(conn, pstmt, rs);
}
return null;
}
public String buildSql(MappingFile file){
try {
if(file == null) throw new Exception("创建SQL语句的MF文件为空!");
String sql = "SELECT ";
List<Attribute> attList = file.getAttlist();
for(int i = 0; i < attList.size(); i++){
if(i == 0) sql += attList.get(i).getColumn();
else sql += "," + attList.get(i).getColumn();
}
return sql += " FROM " + file.getTableName() + " WHERE " + file.getPrimary() + " = ?";
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public String buildMethodName(String attName){
try {
if(attName == null || attName.isEmpty()) throw new Exception("创建方法的属性名为空!");
return "set" + attName.substring(0,1).toUpperCase() + attName.substring(1);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
5、写完各个类之后就是打包,右键点击项目export,保存为JAR file文件即可!
浏览完设计流程,就让我们测试一下我们的hibernate框架吧,let's go!
1、创建一个Web Project项目,导入咱们刚刚写好的包,还要导入dom4j-1.6.1.jar和classes12.jar,别忘了!
2、创建配置文件和实体类和实体映射文件,注意实体类和实体映射文件必须在一个包下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ActionConfig[
<!ELEMENT hibernate (session-factory)>
<!ELEMENT session-factory (property*,mapping*)>
<!ELEMENT property (#PCDATA)>
<!ATTLIST property
name CDATA #REQUIRED>
<!ELEMENT mapping EMPTY>
<!ATTLIST mapping
resource CDATA #REQUIRED>
]>
<hibernate>
<session-factory>
<property name="connection.driver">oracle.jdbc.driver.OracleDriver</property>
<property name="connection.uri">jdbc:oracle:thin:@localhost:1521:orcl</property>
<property name="connection.user">huan</property>
<property name="connection.password">orcl</property>
<mapping resource="/src/com/huan/entity/User.xml"/>
</session-factory>
</hibernate>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ActionConfig[
<!ELEMENT hibernate-mapping (class)>
<!ELEMENT class (id,property*)>
<!ATTLIST class
name CDATA #REQUIRED
table CDATA #REQUIRED>
<!ELEMENT id EMPTY>
<!ATTLIST id
name CDATA #REQUIRED
type CDATA "java.lang.String"
column CDATA #REQUIRED>
<!ELEMENT property EMPTY>
<!ATTLIST property
name CDATA #REQUIRED
type CDATA "java.lang.String"
column CDATA #REQUIRED>
]>
<hibernate-mapping>
<class name="com.huan.entity.User" table="users">
<id name="id" type="java.lang.Integer" column="id"/>
<property name="name" column="name"/>
<property name="pwd" column="password"/>
</class>
</hibernate-mapping>
3、创建执行类Execute对象,调用get方法。之前我写了一个struts模拟用的是虚拟数据库,这次我将我的模拟hibernate替换掉虚拟数据库
package com.huan.test;
import java.util.*;
import com.huan.entity.User;
import com.huan.frame.Execute;
public class UserDaoImp {
private Execute execute = null;
public User getUserById(int id){
execute = HibnateUtil.getExecute();
return (User)execute.get(User.class, id);
}
}
还是老规则,输入数据库里有的用户资料进入index.jsp就算成功了!
今天的hibernate运行原理就跟大家探讨到这里,想交流的朋友请留言或私信。