结合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文件,篇幅有限就写到这里

相关文章
相关标签/搜索