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