結合hibernate與mybatis各自優勢自定義web應用擴展(一)

Hibernate:這是一個很是強大的dao層框架,進行合理的O/R映射設計,會讓讓開發人員關注數據庫表結構的時間大大下降,可是缺點也是很明顯的,就是sql語句不夠靈活,其獨有的hql是基於實體映射類的sql,無疑會使靈活度大大下降。java

Mybatis:MyBatis在Session方面和Hibernate的Session生命週期是同樣的,一樣須要合理的Session管理機制。MyBatis一樣具備二級緩存機制。不一樣於hibernate,mybatis能夠進行詳細的SQL優化設計。可是缺點也是明顯的,須要數據交互的時候就要寫sql。node

想法:在量級較小的狀況下,易用性比性能更加劇要,而mybatis相較於hibernate更容易上手與操做,當選用mybatis時,會出現大量寫sql語句的狀況。那麼能不能在保持mybatis結構的基礎,參考hibernate的表映射,在mybatis封裝一層,達到mybatis的表映射?下面開始嘗試web

mybatis結構(spring+mybatis):加入spring+mybatis的包而且配置好以後,使用mybatis的結構目錄以下圖spring

藍色爲對應接口,紅色爲對應方法,黃色爲實體bean。使用時 接口名.方法 就能獲取到sql執行後獲得數據sql

會發現如下幾點:數據庫

1,一個接口對應一個xml(先不談在接口裏註解寫sql)。緩存

2,執行的每一個sql都要手寫mybatis

3,xml和接口的格式大同小異框架

代碼一:解決問題-建表dom

咱們知道數據表有基本表,虛表,基本表存着數據,虛表是對基本表進行一些操做而獲得的數據集。

以此來看,咱們也能夠將實體bean分爲固定的基本bean與靈活的變化bean。

舉個例子,數據庫如今有個user表,有4個字段id,name,pass,nickname。

咱們創建一個與表字段徹底映射的實體bean。那麼之後咱們只須要關注這個bean就好,而不須要去打開數據庫

可是咱們有的時候並不須要全部的字段,這個時候咱們創建一個靈活的bean和進行和虛表同樣的操做

回到問題,如今的需求就是隻創建一個基本bean就能自動或者半自動創建一個基本表

步驟一:創建數據表須要字段名和字段類型和值,那麼在bean裏就要有相應的設置。就要引入另外一個知識點,自定義註解

創建一個自定義註解

ggze.java

package plug.gg;

import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Target({java.lang.annotation.ElementType.FIELD})
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface ggze
{
  /*字段長度*/
  int leng() default 100;
  /*字段類型*/
  String type();
}

利用自定義的註解創建一個基本bean,user.java

package login.bean;

import plug.gg.ggze;

public class user {
    @ggze(leng = 20,type="varchar")
    private String name;
    @ggze(leng = 20,type="varchar")
    private String pass;
    @ggze(leng = 20,type="varchar")
    private String nickName;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPass() {
        return pass;
    }

    public void setPass(String pass) {
        this.pass = pass;
    }

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }
}

創建配置xml gg.xml

<?xml version="1.0" encoding="UTF-8"?>
<gg>
  <!-- bean所在目錄 -->
  <bean>login/bean</bean>
  <!-- bean包名-->
  <page>login.bean</page>
</gg>

讀取xml工具類 readxml.java

package plug.gg;

import java.io.File;
import java.io.ObjectInputStream.GetField;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class readXml {

	private  Map maps=new LinkedHashMap();
	public  Map readXmls(String url) throws DocumentException{
		
		SAXReader sax=new SAXReader();
		File fp=new File(url);
		Document doc=sax.read(fp);
		Element root=doc.getRootElement();
		this.getNode(root);
		return maps;
	}
	private void getNode(Element node){
		maps.put(node.getName(), node.getTextTrim());
		List<Attribute> listAttr=node.attributes();
		for(Attribute attr:listAttr){
	        String name=attr.getName();
	        String value=attr.getValue();
	        maps.put(name, value);  
	    }  
		List<Element> listElement=node.elements();
	    for(Element e:listElement){  
	        this.getNode(e);
	    }  
	}
}

配置xml讀取 ggScan.java

package plug.gg;

import java.util.Map;

import javax.servlet.ServletContextEvent;
import javax.servlet.http.HttpServletRequest;

import org.dom4j.DocumentException;

public class ggScan {
	public ggScan(){}
	public Map getXml(ServletContextEvent arg0) throws DocumentException{
		String urlString=arg0.getServletContext().getRealPath("WEB-INF/classes/gg.xml");
		Map nodeMap=new readXml().readXmls(urlString);
		return nodeMap;
	}

}

所需共享數據存儲類ggTherdInter.java

package plug.gg;

import java.util.LinkedList;
import java.util.List;

import javax.servlet.ServletContextEvent;

public class ggThreadInter{
	private static ggThreadInter gg=new ggThreadInter();
	public static ggThreadInter getVa(){
		return gg;
	}
	public List<String> getBeanTableName() {
		return beanTableName;
	}
	public void setBeanTableName(List<String> beanTableName) {
		this.beanTableName = beanTableName;
	}
	public List<List<String>> getSqlTable() {
		return sqlTable;
	}
	public void setSqlTable(List<List<String>> sqlTable) {
		this.sqlTable = sqlTable;
	}
/*bean的名字,也是未來的表名*/
	public  List<String> beanTableName;
/*bean裏的變量,也是未來表的字段*/
	public  List<List<String>> sqlTable=new LinkedList<List<String>>();
	public ServletContextEvent contextEvent;

	public ServletContextEvent getContextEvent() {
		return contextEvent;
	}

	public void setContextEvent(ServletContextEvent contextEvent) {
		this.contextEvent = contextEvent;
	}
}

根據掃描結果裝載bean ggTherdBean.java

package plug.gg;

import org.dom4j.DocumentException;

import java.io.File;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContextEvent;

public class ggThreadBean extends ggThreadInter implements Runnable{
	/*掃描後bean的名字也是即將建立sql的表名*/
	public static List<String> tableName=new LinkedList<String>();
	/*掃描bean後裝載實體對象*/
	public static List<List<String>> sqlTable=new LinkedList<List<String>>();
	private ServletContextEvent contextEvent;
	public ggThreadBean(){
		
	}
	@Override
	protected Object clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		return super.clone();
	}
	public static List<List<String>> init(ServletContextEvent arg0){
		Map node = null;
		try {
			node=new ggScan().getXml(arg0);
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		/*得到bean目錄*/
		String a=arg0.getServletContext().getRealPath("WEB-INF/classes/"+node.get("bean")+"");
		File files = new File(a);
		File[] filesList = files.listFiles();
        try {
            for (File file : filesList) {
            	String[] fileStrings=file.getName().split("\\.");
            	
            	tableName.add(fileStrings[0]);
            }
        }catch(Exception e){
        	e.printStackTrace();
        }
        
        
        
        
        
        /*
         * 
         * 反射得到bean的變量和變量類型
         * 
         * */
        
        for(int i = 0;i<tableName.size();i++){
        	List<String> tables=new LinkedList<String>();
        	tables.add(tableName.get(i));
			try {
				Class c = Class.forName(node.get("page")+"."+tableName.get(i));
				Field[] declaredFields = c.getDeclaredFields();
				for( Field field : declaredFields ){
					
					int age=10;
					String age1="varchar";
		            boolean fieldHasAnno = field.isAnnotationPresent(ggze.class);
		            if(fieldHasAnno){  
		                ggze fieldAnno = field.getAnnotation(ggze.class);  
		   
		                age = fieldAnno.leng();
		                age1 =fieldAnno.type();
		                tables.add(field.getName()+"."+age+"."+age1);
		            }  
		            
				}
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SecurityException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			sqlTable.add(tables);
        }
       
        return sqlTable;
	}
	public void run(ServletContextEvent contextEvent) {
		ggThreadBean.init(contextEvent);
		ggThreadInter.getVa().setSqlTable(sqlTable);
		ggThreadInter.getVa().setBeanTableName(tableName);
	}
	public void start(ServletContextEvent arg0){
		this.contextEvent=arg0;
		Thread s=new Thread(this);
		s.start();
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		
	}
}

拼裝建立表的sql語句 ggCreateTableSql.java

package plug.gg;

import java.util.LinkedList;
import java.util.List;

public class ggCreateTableSql{
	public ggCreateTableSql(){
		
	}
	private static ggCreateTableSql gg=new ggCreateTableSql();
	public static ggCreateTableSql getObj(){
		return gg;
	}
	public void init(List<List<String>> sqlTable){
		if(sqlTable==null){
			return;
		}
		 /*
         * 生成建立sql語句
         * 
         * 
         * 
         * */
        List<String> createSql=new LinkedList<String>();
        
        for(List<String> sqlList:sqlTable){
        	
        	String sql="";
        	for(int j=1;j<sqlList.size();j++){
        		String[] valeAndType=sqlList.get(j).split("\\.");
        		
        		sql=sql+","+valeAndType[0]+" "+valeAndType[2]+"("+valeAndType[1]+")";	
        	}
        	sql="create table "+sqlList.get(0)+"(uuid int(100) unsigned primary key"+sql+");";
        	System.out.println(sql);
        	createSql.add(sql);
        }
	}
}

web啓動時偵聽類 ggLoaderLinter.java

package plug.gg;

import org.dom4j.DocumentException;
import plug.gg.commons.ggCommonsXml;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class ggLoaderListener extends ggThreadInter implements ServletContextListener{
	
	
	public ggLoaderListener() {
		
	}
	@Override
	public void contextDestroyed(ServletContextEvent arg0) {

	}
	@Override
	public void contextInitialized(ServletContextEvent arg0) {	
		new ggThreadBean().run(arg0);
		ggCreateTableSql.getObj().init(ggThreadInter.getVa().getSqlTable());
	}
}

在web.xml配置

<listener>
        <listener-class>plug.gg.ggLoaderListener</listener-class>
    </listener>

目錄結構

運行結果

複製這個去數據庫執行就行了。或者再寫一個方法將這些sql生成sql文件,篇幅有限就寫到這裏

相關文章
相關標籤/搜索