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文件,篇幅有限就寫到這裏