手写ORM持久层框架

根据尚学堂录的教程做的。:

配置文件 db.properties

driver=com.mysql.jdbc.Driver
url=jdbc\:mysql\://127.0.0.1\:3306/sorm
user=root
password=123
usingDB=mysql
srcPath=/home/frank/MyEclipseWorkSpace/S_ORM/src
poPackage=com.frank.po
queryClass=com.frank.sorm.core.imp.MySqlQuery
poolMinSize=10
poolMaxSize=100

只支持mysql数据库.poPackage为框架根据数据库表自动生成的domain类的包名

com.frank.sorm.bean

  ColumnInfo.java

  

 1 package com.frank.sorm.bean;
 2
 3 /**
 4  * 封装表中一个字段的信息
 5  * @author frank
 6  *
 7  */
 8 public class ColumnInfo {
 9
10
11     public static final int NORMAL_KEY=0;
12     public  static final int PRIMARY_KEY=1;
13     public  static final int FOREIGN_KEY=2;
14
15     /**
16      *  字段名称
17      */
18     private String colName;
19
20     /**
21      * 字段类型
22      */
23     private String dataType;
24
25     /**
26      * 字段的键类型
27      * 0:普通键 1:主键 2:外键
28      */
29     private int keyType;
30
31     public String getColName() {
32         return colName;
33     }
34
35     public void setColName(String colName) {
36         this.colName = colName;
37     }
38
39     public String getDataType() {
40         return dataType;
41     }
42
43     public void setDataType(String dataType) {
44         this.dataType = dataType;
45     }
46
47     public int getKeyType() {
48         return keyType;
49     }
50
51     public void setKeyType(int keyType) {
52         this.keyType = keyType;
53     }
54
55     public ColumnInfo(String colName, String dataType, int keyType) {
56         super();
57         this.colName = colName;
58         this.dataType = dataType;
59         this.keyType = keyType;
60     }
61     public ColumnInfo() {
62     }
63
64 }

  Configuration.java

  1 package com.frank.sorm.bean;
  2
  3 /**
  4  * 管理配置信息
  5  * @author frank
  6  *
  7  */
  8 public class Configuration {
  9     /**
 10      * 驱动类
 11      */
 12     private String driver;
 13     /**
 14      * jdbc-url
 15      */
 16     private String url;
 17     /**
 18      * 数据库用户名
 19      */
 20     private String user;
 21     /**
 22      * 数据库密码
 23      */
 24     private String password;
 25     /**
 26      * 使用的数据库
 27      */
 28     private String usingDB;
 29     /**
 30      * 项目的源码路径
 31      */
 32     private String srcPath;
 33     /**
 34      * 扫描生成java类的包
 35      * persistence object
 36      */
 37     private String poPackage;
 38
 39     /**
 40      * 连接池中最小的连接数
 41      */
 42     private int poolMinSize;
 43     /**
 44      * 连接池中最大的连接数
 45      */
 46     private int poolMaxSize;
 47
 48
 49     /**
 50      * 项目使用的查询类
 51      */
 52     private String queryClass;
 53     public String getQueryClass() {
 54         return queryClass;
 55     }
 56     public void setQueryClass(String queryClass) {
 57         this.queryClass = queryClass;
 58     }
 59     public Configuration(String driver, String url, String user,
 60             String password, String usingDB,
 61             String srcPath, String poPackage) {
 62         super();
 63         this.driver = driver;
 64         this.url = url;
 65         this.user = user;
 66         this.password = password;
 67         this.usingDB = usingDB;
 68         this.srcPath = srcPath;
 69         this.poPackage = poPackage;
 70     }
 71
 72     public int getPoolMinSize() {
 73         return poolMinSize;
 74     }
 75     public void setPoolMinSize(int poolMinSize) {
 76         this.poolMinSize = poolMinSize;
 77     }
 78     public int getPoolMaxSize() {
 79         return poolMaxSize;
 80     }
 81     public void setPoolMaxSize(int poolMaxSize) {
 82         this.poolMaxSize = poolMaxSize;
 83     }
 84     public Configuration() {
 85         super();
 86     }
 87     public String getDriver() {
 88         return driver;
 89     }
 90     public void setDriver(String driver) {
 91         this.driver = driver;
 92     }
 93     public String getUrl() {
 94         return url;
 95     }
 96     public void setUrl(String url) {
 97         this.url = url;
 98     }
 99     public String getUser() {
100         return user;
101     }
102     public void setUser(String user) {
103         this.user = user;
104     }
105     public String getPassword() {
106         return password;
107     }
108     public void setPassword(String password) {
109         this.password = password;
110     }
111     public String getUsingDB() {
112         return usingDB;
113     }
114     public void setUsingDB(String usingDB) {
115         this.usingDB = usingDB;
116     }
117     public String getSrcPath() {
118         return srcPath;
119     }
120     public void setSrcPath(String srcPath) {
121         this.srcPath = srcPath;
122     }
123     public String getPoPackage() {
124         return poPackage;
125     }
126     public void setPoPackage(String poPackage) {
127         this.poPackage = poPackage;
128     }
129
130
131
132
133
134
135 }

  JavaFieldGetSet.java

 1 package com.frank.sorm.bean;
 2
 3 /**
 4  * 封装了java属性和set/get源码信息
 5  *
 6  * @author frank
 7  *
 8  */
 9 public class JavaFieldGetSet {
10     /**
11      * 属性的源码信息
12      */
13     private String fieldInfo;
14     /**
15      * get的源码信息
16      */
17     private String getInfo;
18     /**
19      * set的源码信息
20      */
21     private String setInfo;
22
23     public String getFieldInfo() {
24         return fieldInfo;
25     }
26
27     public void setFieldInfo(String fieldInfo) {
28         this.fieldInfo = fieldInfo;
29     }
30
31     public String getGetInfo() {
32         return getInfo;
33     }
34
35     public void setGetInfo(String getInfo) {
36         this.getInfo = getInfo;
37     }
38
39     public String getSetInfo() {
40         return setInfo;
41     }
42
43     public void setSetInfo(String setInfo) {
44         this.setInfo = setInfo;
45     }
46
47     public JavaFieldGetSet(String fieldInfo, String getInfo,
48             String setInfo) {
49         super();
50         this.fieldInfo = fieldInfo;
51         this.getInfo = getInfo;
52         this.setInfo = setInfo;
53     }
54
55     public JavaFieldGetSet() {
56         super();
57     }
58
59     @Override
60     public String toString() {
61         System.out.println(fieldInfo);
62         System.out.println(getInfo);
63         System.out.println(setInfo);
64         return super.toString();
65     }
66
67 }

  TableInfo.java

 1 package com.frank.sorm.bean;
 2
 3 import java.util.List;
 4 import java.util.Map;
 5
 6 /**
 7  * 封装表结构信息
 8  * @author frank
 9  *
10  */
11 public class TableInfo {
12
13     /**
14      * 表名
15      */
16     private String tabName;
17
18     /**
19      * 所以字段信息
20      */
21     private Map<String,ColumnInfo> columns;
22
23     /**
24      * 主键
25      */
26     private ColumnInfo priKey;
27
28     /**
29      *联合主键
30      *
31      */
32     private List<ColumnInfo> priKeys;
33
34
35     public List<ColumnInfo> getPriKeys() {
36         return priKeys;
37     }
38
39     public void setPriKeys(List<ColumnInfo> priKeys) {
40         this.priKeys = priKeys;
41     }
42
43     public String getTabName() {
44         return tabName;
45     }
46
47     public void setTabName(String tabName) {
48         this.tabName = tabName;
49     }
50
51     public Map<String, ColumnInfo> getColumns() {
52         return columns;
53     }
54
55     public void setColumns(Map<String, ColumnInfo> columns) {
56         this.columns = columns;
57     }
58
59     public ColumnInfo getPriKey() {
60         return priKey;
61     }
62
63     public void setPriKey(ColumnInfo priKey) {
64         this.priKey = priKey;
65     }
66
67     public TableInfo(String tabName, Map<String, ColumnInfo> columns,
68             ColumnInfo priKey) {
69         super();
70         this.tabName = tabName;
71         this.columns = columns;
72         this.priKey = priKey;
73     }
74
75     public TableInfo(String tabName, Map<String, ColumnInfo> columns,
76             List<ColumnInfo> priKeys) {
77         super();
78         this.tabName = tabName;
79         this.columns = columns;
80         this.priKeys = priKeys;
81     }
82
83     public TableInfo() {
84         super();
85     }
86
87
88
89 }

com.frank.sorm.connPool

  DBconnPool.java

 1 package com.frank.sorm.connPool;
 2
 3 import java.sql.Connection;
 4 import java.sql.SQLException;
 5 import java.util.ArrayList;
 6 import java.util.List;
 7
 8 import com.frank.sorm.core.DBManager;
 9
10 /**
11  * 连接池
12  * @author frank
13  *
14  */
15 public class DBconnPool {
16     /**
17      * 连接池对象
18      */
19     private  List<Connection> pool;
20     /**
21      * 最大连接数
22      */
23     private static final int POOL_MAX_SIZE=DBManager.getConf().getPoolMaxSize();
24     /**
25      * 最小连接数
26      */
27     private static final int POOL_MIN_SIZE=DBManager.getConf().getPoolMinSize();
28
29
30     /**
31      * 初始化连接池
32      */
33     public void initPool(){
34         if(pool==null){
35             pool=new ArrayList<Connection>();
36         }
37         while(pool.size()<POOL_MIN_SIZE){
38             pool.add(DBManager.createConnection());
39         }
40     }
41
42     /**
43      * 从连接池中取出一个连接
44      * @return 连接
45      */
46     public synchronized Connection getConnection(){
47         int last_index=pool.size()-1;
48         Connection conn = pool.get(last_index);
49         pool.remove(last_index);
50         return conn;
51     }
52
53     /**
54      * 将连接放回池中
55      * @param conn 连接
56      */
57     public synchronized void close(Connection conn){
58         if(pool.size()>=POOL_MAX_SIZE)
59             try {
60                 if(conn!=null)
61                     conn.close();
62             } catch (SQLException e) {
63                 // TODO Auto-generated catch block
64                 e.printStackTrace();
65             }
66         else
67             pool.add(conn);
68
69     }
70
71
72
73
74
75     public DBconnPool(){
76         initPool();
77     }
78
79 }

com.frank.sorm.core

  CallBack.java

1 package com.frank.sorm.core;
2
3 import java.sql.Connection;
4 import java.sql.PreparedStatement;
5 import java.sql.ResultSet;
6
7 public interface CallBack {
8     public Object doExecute(Connection conn, PreparedStatement ps,ResultSet rs);
9 }

  DBManager.java

  1 package com.frank.sorm.core;
  2
  3 import java.io.IOException;
  4 import java.sql.Connection;
  5 import java.sql.DriverManager;
  6 import java.sql.ResultSet;
  7 import java.sql.SQLException;
  8 import java.sql.Statement;
  9 import java.util.Properties;
 10
 11 import com.frank.sorm.bean.Configuration;
 12 import com.frank.sorm.connPool.DBconnPool;
 13
 14 /**
 15  *  根据配置信息,维持连接对象的管理 
 16  * @author frank
 17  *
 18  */
 19 public class DBManager {
 20
 21     /**
 22      * 配置信息
 23      */
 24     private static Configuration conf;
 25     /**
 26      * 连接池对象
 27      */
 28     private static DBconnPool pool ;
 29     public static Configuration getConf() {
 30         return conf;
 31     }
 32     static{
 33         Properties pros=new Properties();
 34
 35         try {
 36             pros.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));
 37         } catch (IOException e) {
 38             // TODO Auto-generated catch block
 39             e.printStackTrace();
 40         }
 41         conf = new Configuration();
 42         conf.setDriver(pros.getProperty("driver"));
 43         conf.setPoPackage(pros.getProperty("poPackage"));
 44         conf.setPassword(pros.getProperty("password"));
 45         conf.setUrl(pros.getProperty("url"));
 46         conf.setUser(pros.getProperty("user"));
 47         conf.setSrcPath(pros.getProperty("srcPath"));
 48         conf.setUsingDB(pros.getProperty("usingDB"));
 49         conf.setQueryClass(pros.getProperty("queryClass"));
 50         conf.setPoolMaxSize(Integer.parseInt(pros.getProperty("poolMaxSize")));
 51         conf.setPoolMinSize(Integer.parseInt(pros.getProperty("poolMinSize")));
 52
 53
 54
 55     }
 56     /**
 57      * 获得数据库连接
 58      * @return 连接
 59      */
 60     public static Connection createConnection(){
 61         try {
 62             Class.forName(conf.getDriver());
 63             return DriverManager.getConnection(conf.getUrl(), conf.getUser(), conf.getPassword());
 64         } catch (Exception e) {
 65             // TODO Auto-generated catch block
 66             e.printStackTrace();
 67             return null;
 68         }
 69     }
 70     /**
 71      * 从连接池中获得数据库连接
 72      * @return 连接
 73      */
 74     public static Connection getConnection(){
 75 //        try {
 76 //            Class.forName(conf.getDriver());
 77 //            return DriverManager.getConnection(conf.getUrl(), conf.getUser(), conf.getPassword());
 78 //        } catch (Exception e) {
 79 //            // TODO Auto-generated catch block
 80 //            e.printStackTrace();
 81 //            return null;
 82         if(pool==null)
 83             pool = new DBconnPool();
 84         return pool.getConnection();
 85
 86     }
 87     /**
 88      * 关闭资源
 89      * @param rs
 90      * @param ps
 91      * @param conn
 92      */
 93     public static void close(ResultSet rs,Statement ps,Connection conn){
 94         try {
 95             if(rs!=null){
 96                 rs.close();
 97             }
 98         } catch (SQLException e) {
 99             e.printStackTrace();
100         }
101         try {
102             if(ps!=null){
103                 ps.close();
104             }
105         } catch (SQLException e) {
106             e.printStackTrace();
107         }
108         pool.close(conn);
109     }
110 }

  Query.java

  1 package com.frank.sorm.core;
  2
  3 import java.lang.reflect.Field;
  4 import java.sql.Connection;
  5 import java.sql.PreparedStatement;
  6 import java.sql.ResultSet;
  7 import java.sql.ResultSetMetaData;
  8 import java.sql.SQLException;
  9 import java.util.ArrayList;
 10 import java.util.List;
 11
 12 import com.frank.sorm.bean.ColumnInfo;
 13 import com.frank.sorm.bean.TableInfo;
 14 import com.frank.sorm.util.JDBCUtil;
 15 import com.frank.sorm.util.ReflectUtil;
 16
 17 /**
 18  *    负责查询 对外提供服务的核心类
 19  * @author frank
 20  */
 21 public abstract class Query implements Cloneable{
 22
 23     /**
 24      * 采用模板方法模式将JDBC操作封装成模板
 25      * @param sql sql语句
 26      * @param params sql参数 
 27      * @param clazz 记录要封装到的java类
 28      * @param back CallBack的实现类 回调
 29      * @return
 30      */
 31     public Object executeQueryTemplate(String sql,Object[] params, Class clazz,CallBack back){
 32         Connection conn=DBManager.getConnection();
 33         PreparedStatement ps=null;
 34         ResultSet rs=null;
 35
 36         try {
 37             ps=conn.prepareStatement(sql);
 38             JDBCUtil.handleParams(ps, params);
 39             rs=ps.executeQuery();
 40             return back.doExecute(conn, ps, rs);
 41         } catch (Exception e) {
 42             // TODO Auto-generated catch block
 43             e.printStackTrace();
 44             return null;
 45         }finally{
 46             DBManager.close(null, ps, conn);
 47         }
 48     }
 49
 50     /**
 51      *    执行一条DML语句
 52      * @param sql 要执行的sql语句
 53      * @param params sql语句参数
 54      * @return 影响的记录行数
 55      */
 56     public int executeDML(String sql, Object[] params) {
 57         // TODO Auto-generated method stub
 58         Connection conn=DBManager.getConnection();
 59         int count=0;
 60
 61         PreparedStatement ps=null;
 62
 63         try {
 64             ps=conn.prepareStatement(sql);
 65             JDBCUtil.handleParams(ps, params);
 66             count=ps.executeUpdate();
 67         } catch (SQLException e) {
 68             // TODO Auto-generated catch block
 69             e.printStackTrace();
 70         }finally{
 71             DBManager.close(null, ps, conn);
 72         }
 73         return count;
 74     }
 75
 76     /**
 77      *      将一个对象储存到数据库中
 78      * @param obj 要储存的对象
 79      */
 80     public void save(Object obj) {
 81         // TODO Auto-generated method stub
 82         Class c=obj.getClass();
 83         List<Object> params =new ArrayList<Object>();
 84         TableInfo tableInfo = TableContext.poClassTableMap.get(c);
 85         StringBuilder sql=new StringBuilder("insert into "+tableInfo.getTabName()+" (");
 86         Field[] fs=c.getDeclaredFields();
 87         int fieldNotNullCount=0;
 88
 89         for(Field field:fs){
 90             String fieldName=field.getName();
 91             Object fieldValue = ReflectUtil.invokeGet(fieldName, obj);
 92
 93             if(fieldValue!=null){
 94                 fieldNotNullCount++;
 95                 sql.append(fieldName+",");
 96                 params.add(fieldValue);
 97             }
 98         }
 99         sql.setCharAt(sql.length()-1, ‘)‘);
100         sql.append(" values (");
101         for(int i=0;i<fieldNotNullCount;i++){
102             sql.append("?,");
103         }
104         sql.setCharAt(sql.length()-1, ‘)‘);
105
106         this.executeDML(sql.toString(), params.toArray());
107     }
108
109     /**
110      *    删除数据库中的记录
111      * @param clazz 对象类型
112      * @param id 主键id
113      * @return 影响的记录行数
114      */
115     @SuppressWarnings("rawtypes")
116     public int delete(Class clazz, Object id) {
117         // TODO Auto-generated method stub
118         //通过class找TableInfo
119         TableInfo tableInfo=TableContext.poClassTableMap.get(clazz);
120         //主键
121         ColumnInfo onlyPriKey=tableInfo.getPriKey();
122
123         String sql="delete from "+tableInfo.getTabName()+" where  "+onlyPriKey.getColName()+"=?";
124
125         return executeDML(sql, new Object[]{id});
126
127     }
128
129     /**
130      *    删除对应数据库中的记录
131      * @param obj 要删除的对象
132      * @return 影响的记录行数
133      */
134
135     public int delete(Object obj) {
136         // TODO Auto-generated method stub
137         Class c = obj.getClass();
138         TableInfo tableInfo = TableContext.poClassTableMap.get(c);
139         ColumnInfo onlyPrikey  = tableInfo.getPriKey();
140
141         //反射
142         Object priKeyValue=ReflectUtil.invokeGet(onlyPrikey.getColName(), obj);
143         return delete(c, priKeyValue);
144
145
146     }
147
148     /**
149      *     更新对象对应的记录
150      * @param obj 对象
151      * @return 影响的记录行数
152      */
153     public int update(Object obj ,String[] fieldNames) {
154         // TODO Auto-generated method stub
155         Class c=obj.getClass();
156         List<Object> params =new ArrayList<Object>();
157         TableInfo tableInfo = TableContext.poClassTableMap.get(c);
158         ColumnInfo priKey = tableInfo.getPriKey();
159         StringBuilder sql=new StringBuilder("update  "+tableInfo.getTabName()+" set ");
160
161         for(String fieldName: fieldNames){
162             Object fvalue = ReflectUtil.invokeGet(fieldName, obj);
163             params.add(fvalue);
164             sql.append(fieldName+"=?,");
165         }
166         params.add(ReflectUtil.invokeGet( priKey.getColName(),obj));
167
168         sql.setCharAt(sql.length()-1,‘ ‘);
169         sql.append(" where ");
170         sql.append(priKey.getColName()+"=? ");
171         System.out.println(sql.toString());
172         return this.executeDML(sql.toString(), params.toArray());
173     }
174
175     /**
176      *    查询数据库返回多条记录
177      * @param sql  sql语句
178      * @param clazz 封装javabean类的Class对象
179      * @param params sql语句参数
180      * @return 查询得到的结果集
181      */
182     @SuppressWarnings("rawtypes")
183     public List queryRows(String sql, final Class clazz, Object[] params) {
184         // TODO Auto-generated method stub
185         return (List) executeQueryTemplate(sql, params, clazz, new CallBack() {
186
187             @Override
188             public Object doExecute(Connection conn, PreparedStatement ps,
189                     ResultSet rs) {
190                 ResultSetMetaData metaDate;
191                 List list=null;
192                 try {
193                     metaDate = rs.getMetaData();
194                     while(rs.next()){
195                         if(list==null)
196                             list=new ArrayList<>();
197                         Object rowObj=clazz.newInstance();
198                         for(int i=0;i<metaDate.getColumnCount();i++){
199                             String columnName = metaDate.getColumnLabel(i+1);
200                             Object columnValue = rs.getObject(i+1);
201                             //通过反射调用rowObj的set方法
202                             ReflectUtil.invokeSet(rowObj, columnName, columnValue);
203
204                         }
205                     list.add(rowObj);
206                     }
207                 } catch (Exception e) {
208                     // TODO Auto-generated catch block
209                     e.printStackTrace();
210                 }
211                 return list;
212             }
213         });
214
215
216     }
217
218
219     /**
220      *    查询数据库返回一条记录
221      * @param sql  sql语句
222      * @param clazz 封装javabean类的Class对象
223      * @param params sql语句参数
224      * @return 查询得到的结果对象
225      */
226     @SuppressWarnings("rawtypes")
227     public Object queryUniqueRows(String sql, Class clazz,
228             Object[] params) {
229         // TODO Auto-generated method stub
230         List list=queryRows(sql, clazz, params);
231         return (list==null||list.size()==0)?null:list.get(0);
232     }
233
234
235     /**
236      *    查询数据库返回一个值( 一行一列)
237      * @param sql  sql语句
238      * @param params sql语句参数
239      * @return 查询得到的结果对象
240      */
241     public Object queryValue(String sql, Object[] params) {
242         // TODO Auto-generated method stub
243
244         return executeQueryTemplate(sql, params, null, new CallBack() {
245
246             @Override
247             public Object doExecute(Connection conn, PreparedStatement ps,
248                     ResultSet rs) {
249                 Object value = null;
250                 // TODO Auto-generated method stub
251                 try {
252                     while(rs.next()){
253                         value=rs.getObject(1);
254                     }
255                 } catch (SQLException e) {
256                     // TODO Auto-generated catch block
257                     e.printStackTrace();
258                 }
259                 return value ;
260             }
261         });
262     }
263
264     /**
265      *    查询数据库返回一个数字
266      * @param sql  sql语句
267      * @param params sql语句参数
268      * @return 查询得到的结果数字
269      */
270     public Number queryNumber(String sql, Object[] params) {
271         // TODO Auto-generated method stub
272         return (Number) queryValue(sql, params);
273     }
274
275     /**
276      * 分页查询 
277      * @param pageNum 当前页
278      * @param pageSize每页显示的记录条数
279      * @return
280      */
281     public abstract Object queryPagenate(int pageNum,int pageSize);
282
283     @Override
284     protected Object clone() throws CloneNotSupportedException {
285         // TODO Auto-generated method stub
286         return super.clone();
287     }
288
289
290 }

  QueryFactory.java

 1 package com.frank.sorm.core;
 2
 3 /**
 4  * 创建query工厂类
 5  * @author frank
 6  *
 7  */
 8 public class QueryFactory {
 9
10     private static QueryFactory factory=new QueryFactory();
11     private static Query prototypeObj;
12     static{
13         try {
14             Class c=Class.forName(DBManager.getConf().getQueryClass());
15             prototypeObj=(Query) c.newInstance();
16
17         } catch (Exception e) {
18             // TODO Auto-generated catch block
19             e.printStackTrace();
20         }
21
22     }
23     private QueryFactory(){
24     }
25
26     public static QueryFactory getInstance(){
27         return factory;
28     }
29
30
31     public Query creatyFactory(){
32         try {
33             return (Query) prototypeObj.clone();
34         } catch (CloneNotSupportedException e) {
35             // TODO Auto-generated catch block
36             e.printStackTrace();
37             return null;
38         }
39
40     }
41 }

  TableContext.java

  1 package com.frank.sorm.core;
  2
  3 import java.sql.Connection;
  4 import java.sql.DatabaseMetaData;
  5 import java.sql.ResultSet;
  6 import java.sql.SQLException;
  7 import java.util.ArrayList;
  8 import java.util.HashMap;
  9 import java.util.Map;
 10
 11 import javax.swing.text.TabExpander;
 12
 13 import com.frank.sorm.bean.ColumnInfo;
 14 import com.frank.sorm.bean.TableInfo;
 15 import com.frank.sorm.core.imp.MysqlTypeConvertor;
 16 import com.frank.sorm.util.JavaFileUtil;
 17 import com.frank.sorm.util.StringUtil;
 18
 19
 20
 21 /**
 22  * 负责获取管理数据库所有表结构和类结构的关系,并可以根据表结构生成类结构。
 23  * @author gaoqi www.sxt.cn
 24  *
 25  */
 26 public class TableContext {
 27
 28     /**
 29      * 表名为key,表信息对象为value
 30      */
 31     public static  Map<String,TableInfo>  tables = new HashMap<String,TableInfo>();
 32
 33     /**
 34      * 将po的class对象和表信息对象关联起来,便于重用!
 35      */
 36     public static  Map<Class,TableInfo>  poClassTableMap = new HashMap<Class,TableInfo>();
 37
 38     private TableContext(){}
 39
 40     static {
 41         try {
 42             //初始化获得表的信息
 43             Connection con = DBManager.getConnection();
 44             DatabaseMetaData dbmd = con.getMetaData();
 45
 46             ResultSet tableRet = dbmd.getTables(null, "%","%",new String[]{"TABLE"});
 47
 48             while(tableRet.next()){
 49                 String tableName = (String) tableRet.getObject("TABLE_NAME");
 50
 51                 TableInfo ti = new TableInfo(tableName,new HashMap<String, ColumnInfo>(), new ArrayList<ColumnInfo>() );
 52                 tables.put(tableName, ti);
 53
 54                 ResultSet set = dbmd.getColumns(null, "%", tableName, "%");  //查询表中的所有字段
 55                 while(set.next()){
 56                     ColumnInfo ci = new ColumnInfo(set.getString("COLUMN_NAME"),
 57                             set.getString("TYPE_NAME"), 0);
 58                     ti.getColumns().put(set.getString("COLUMN_NAME"), ci);
 59                 }
 60
 61                 ResultSet set2 = dbmd.getPrimaryKeys(null, "%", tableName);  //查询t_user表中的主键
 62                 while(set2.next()){
 63                     ColumnInfo ci2 = (ColumnInfo) ti.getColumns().get(set2.getObject("COLUMN_NAME"));
 64                     ci2.setKeyType(ColumnInfo.PRIMARY_KEY);  //设置为主键类型
 65                     ti.getPriKeys().add(ci2);
 66                 }
 67
 68                 if(ti.getPriKeys().size()>0){  //取唯一主键。。方便使用。如果是联合主键。则为空!
 69                     ti.setPriKey(ti.getPriKeys().get(0));
 70                 }
 71             }
 72         } catch (SQLException e) {
 73             e.printStackTrace();
 74         }
 75         //更新类结构
 76         updateJavaPOFile();
 77
 78         //加载po包下的所有的类
 79         loadPOTables();
 80
 81
 82     }
 83     /**
 84      * 根据表结构,更新配置po包下的java类
 85      */
 86     public static void updateJavaPOFile(){
 87         Map<String,TableInfo> map=tables;
 88         for(TableInfo t:map.values()){
 89             JavaFileUtil.createJavaPOFile(t, new MysqlTypeConvertor());
 90         }
 91     }
 92     /**
 93      * 加载po包下的类
 94      */
 95     public static void loadPOTables(){
 96         for(TableInfo tableInfo:tables.values()){
 97             try {
 98                 Class c = Class.forName(DBManager.getConf().getPoPackage()+
 99                         "."+StringUtil.firstChar2UpperCase(tableInfo.getTabName()));
100                 poClassTableMap.put(c, tableInfo);
101             } catch (ClassNotFoundException e) {
102                 // TODO Auto-generated catch block
103                 e.printStackTrace();
104             }
105         }
106
107     }
108
109
110
111 //    public static void main(String[] args) {
112 //         Map<String,TableInfo>  tables = TableContext.tables;
113 //         for(String v: tables.keySet())
114 //         {
115 //            System.out.println(v);
116 //         }
117 //         for(TableInfo f:tables.values()){
118 //            System.out.println(f.getPriKey().getColName());
119 //         }
120 //         System.out.println(tables);
121 //    }
122
123 }

  TypeConvertor.java

 1 package com.frank.sorm.core;
 2
 3 /**
 4  *    负责java类型和数据库类型的相互转换 
 5  * @author frank
 6  */
 7
 8 public interface TypeConvertor {
 9
10     /**
11      * 将数据库类型转换为java类型
12      * @param columnType 数据库字段类型
13      * @return java类型
14      */
15     public String databaseType2JavaType(String columnType);
16
17     /**
18      * 将java类型转换为数据库类型
19      * @param javaType java类型
20      * @return 数据库类型
21      */
22     public String javaType2DatabaseType(String  javaType);
23
24 }

com.frank.sorm.core.imp

  MySqlQuery.java

 1 package com.frank.sorm.core.imp;
 2
 3 import java.lang.reflect.Field;
 4 import java.sql.Connection;
 5 import java.sql.PreparedStatement;
 6 import java.sql.ResultSet;
 7 import java.sql.ResultSetMetaData;
 8 import java.sql.SQLException;
 9 import java.util.ArrayList;
10 import java.util.List;
11
12 import com.frank.sorm.bean.ColumnInfo;
13 import com.frank.sorm.bean.TableInfo;
14 import com.frank.sorm.core.DBManager;
15 import com.frank.sorm.core.Query;
16 import com.frank.sorm.core.TableContext;
17 import com.frank.sorm.util.JDBCUtil;
18 import com.frank.sorm.util.ReflectUtil;
19
20 /**
21  * 负责mysql数据库的操作
22  * @author frank
23  *
24  */
25 public class MySqlQuery extends Query {
26
27     @Override
28     public Object queryPagenate(int pageNum, int pageSize) {
29         // TODO Auto-generated method stub
30         return null;
31     }
32
33
34
35
36
37
38
39
40 }

  MysqlTypeConvertor.java

 1 package com.frank.sorm.core.imp;
 2
 3 import com.frank.sorm.core.TypeConvertor;
 4
 5 /**
 6  * mysql数据库类型和java类型的转换
 7  *
 8  * @author frank
 9  *
10  */
11 public class MysqlTypeConvertor implements TypeConvertor {
12
13     @Override
14     public String databaseType2JavaType(String columnType) {
15         // TODO Auto-generated method stub
16         // varchar-->String
17         if ("varchar".equalsIgnoreCase(columnType)
18                 || "char".equalsIgnoreCase(columnType)) {
19             return "String";
20         } else if ("int".equalsIgnoreCase(columnType)
21                 || "tinyint".equalsIgnoreCase(columnType)
22                 || "smallint".equalsIgnoreCase(columnType)
23                 || "integer".equalsIgnoreCase(columnType)) {
24             return "Integer";
25         } else if ("bigint".equalsIgnoreCase(columnType)) {
26             return "Long";
27         } else if ("double".equalsIgnoreCase(columnType)
28                 || "float".equalsIgnoreCase(columnType)) {
29             return "Double";
30         } else if ("clob".equalsIgnoreCase(columnType)) {
31             return "java.sql.CLob";
32         } else if ("blob".equalsIgnoreCase(columnType)) {
33             return "java.sql.BLob";
34         } else if ("date".equalsIgnoreCase(columnType)) {
35             return "java.sql.Date";
36         } else if ("time".equalsIgnoreCase(columnType)) {
37             return "java.sql.Time";
38         } else if ("timestamp".equalsIgnoreCase(columnType)) {
39             return "java.sql.Timestamp";
40         }
41
42         return null;
43     }
44
45     @Override
46     public String javaType2DatabaseType(String javaType) {
47         // TODO Auto-generated method stub
48         return null;
49     }
50
51 }

com.frank.sorm.util

  JavaFileUtil.java

  1 package com.frank.sorm.util;
  2
  3 import java.io.BufferedWriter;
  4 import java.io.File;
  5 import java.io.FileWriter;
  6 import java.io.IOException;
  7 import java.util.ArrayList;
  8 import java.util.List;
  9 import java.util.Map;
 10
 11 import com.frank.sorm.bean.ColumnInfo;
 12 import com.frank.sorm.bean.JavaFieldGetSet;
 13 import com.frank.sorm.bean.TableInfo;
 14 import com.frank.sorm.core.DBManager;
 15 import com.frank.sorm.core.TypeConvertor;
 16
 17 /**
 18  * 封装生成java源文件的常用操作
 19  * @author frank
 20  *
 21  */
 22 public class JavaFileUtil {
 23
 24     /**
 25      *根据字段信息生成java属性信息
 26      * @param colum 字段信息
 27      * @param convertor 类型转换器
 28      * @return java属性的set/get方法
 29      */
 30     public static JavaFieldGetSet createFieldGetSetSRC(ColumnInfo colum,TypeConvertor convertor){
 31         JavaFieldGetSet fieldSet = new JavaFieldGetSet();
 32
 33         String javaFieldType= convertor.databaseType2JavaType(colum.getDataType());
 34
 35         fieldSet.setFieldInfo("\tprivate "+javaFieldType+" "+colum.getColName()+";\n");
 36
 37         StringBuffer getSrc=new StringBuffer();
 38         //public String getUser(){
 39         //生成get方法源码
 40         getSrc.append("\tpublic "+javaFieldType+" get"+StringUtil.firstChar2UpperCase(colum.getColName())+"(){\n"   );
 41         getSrc.append("\t\treturn "+colum.getColName()+";\n");
 42         getSrc.append("\t}\n");
 43         fieldSet.setGetInfo(getSrc.toString());
 44
 45         //生成set方法源码
 46         StringBuffer setSrc= new StringBuffer();
 47         setSrc.append("\tpublic void set"+StringUtil.firstChar2UpperCase(colum.getColName())+"("   );
 48         setSrc.append(javaFieldType+" "+colum.getColName()+"){\n");
 49         setSrc.append("\t\tthis."+colum.getColName()+"="+colum.getColName()+";\n");
 50         setSrc.append("\t}\n");
 51         fieldSet.setSetInfo(setSrc.toString());
 52         return fieldSet;
 53     }
 54
 55
 56     /**
 57      * 根据表信息生成java类源码
 58      * @param tableInfo 表信息
 59      * @param convertor 数据类型转换器
 60      * @return java类源码
 61      */
 62     public  static String createJavaSrc(TableInfo tableInfo, TypeConvertor convertor){
 63         StringBuffer src= new StringBuffer();
 64
 65         Map<String,ColumnInfo> columns=tableInfo.getColumns();
 66         List<JavaFieldGetSet> javaFields=new ArrayList<JavaFieldGetSet>();
 67         for(ColumnInfo c:columns.values()){
 68             javaFields.add(createFieldGetSetSRC(c,convertor));
 69         }
 70         //生成package语句
 71         src.append("package "+DBManager.getConf().getPoPackage()+";\n\n");
 72
 73         //生成import语句
 74         src.append("import java.sql.*;\n");
 75         src.append("import java.util.*;\n\n");
 76         //生成类声明语句
 77         src.append("public class "+StringUtil.firstChar2UpperCase(tableInfo.getTabName())+" {\n\n");
 78 //        System.out.println("public class "+StringUtil.firstChar2UpperCase(tableInfo.getTabName())+" {\n\n");
 79
 80
 81         //生成属性列表
 82         for(JavaFieldGetSet f:javaFields){
 83             src.append(f.getFieldInfo());
 84         }
 85         src.append("\n\n");
 86
 87         //生成get方法列表
 88         for(JavaFieldGetSet f:javaFields){
 89             src.append(f.getGetInfo());
 90         }
 91
 92         //生成set方法列表
 93         for(JavaFieldGetSet f:javaFields){
 94             src.append(f.getSetInfo());
 95         }
 96
 97         //生成类结束
 98         src.append("}\n");
 99 //        System.out.println(src);
100         return src.toString();
101
102     }
103     /**
104      *根据表信息生成java文件
105      * @param table 表信息
106      * @param convertor 类型转换器
107      */
108     public static void createJavaPOFile(TableInfo table,TypeConvertor convertor){
109         String src=createJavaSrc(table, convertor);
110
111         String srcPath=DBManager.getConf().getSrcPath()+"//";
112         String packagePath=DBManager.getConf().getPoPackage().replaceAll("\\.", "/");
113         File f=new File(srcPath+packagePath);
114
115         System.out.println(f.getAbsolutePath());
116
117         if(!f.exists()){
118             f.mkdirs();
119         }
120
121         BufferedWriter bw=null;
122         try {
123             bw=new BufferedWriter(new FileWriter(f.getAbsoluteFile()+"/"+StringUtil.firstChar2UpperCase(table.getTabName())+".java") );
124             bw.write(src);
125         } catch (IOException e) {
126             // TODO Auto-generated catch block
127             e.printStackTrace();
128         }finally{
129             if(bw!=null){
130                 try {
131                     bw.close();
132                 } catch (IOException e) {
133                     // TODO Auto-generated catch block
134                     e.printStackTrace();
135                 }
136             }
137         }
138     }
139 }

  JDBCUtil.java

 1 package com.frank.sorm.util;
 2
 3 import java.sql.PreparedStatement;
 4 import java.sql.SQLException;
 5
 6
 7 /**
 8  * 封装jdbc常用的操作
 9  * @author frank
10  *
11  */
12 public class JDBCUtil {
13
14     /**
15      *给preparedStatement传如参数 
16      * @param ps PreparedStatement
17      * @param params 参数
18      */
19     public static void handleParams( PreparedStatement ps,Object[] params){
20
21         if(params!=null){
22             for(int i=0;i<params.length;i++){
23                 try {
24                     ps.setObject(i+1,params[i]);
25                 } catch (SQLException e) {
26                     // TODO Auto-generated catch block
27                     e.printStackTrace();
28                 }
29             }
30         }
31     }
32
33 }

  ReflectUtil.java

 1 package com.frank.sorm.util;
 2
 3 import java.lang.reflect.Method;
 4
 5 /**
 6  * 封装反射的常用操作
 7  * @author frank
 8  *
 9  */
10 public class ReflectUtil {
11
12     /**
13      * 调用obj对象对应属性的get方法
14      * @param c
15      * @param fieldName
16      * @param obj
17      * @return
18      */
19     public static Object invokeGet(String fieldName, Object obj){
20         //通过反射机制,调用属性的get方法
21                 try {
22                     Class c=obj.getClass();
23                     Method m=c.getDeclaredMethod("get"+StringUtil.firstChar2UpperCase(fieldName), null);
24                      return m.invoke(obj, null);
25                 } catch (Exception  e) {
26                     // TODO Auto-generated catch block
27                     e.printStackTrace();
28                     return null;
29                 }
30     }
31
32     /**
33      * 调用obj对象对应属性的set方法
34      * @param c
35      * @param fieldName
36      * @param obj
37      */
38     public static void  invokeSet( Object obj ,String fieldName,Object fieldValue){
39         //通过反射机制,调用属性的set方法
40                 try {
41                     Class c=obj.getClass();
42                     Method m=c.getDeclaredMethod("set"+StringUtil.firstChar2UpperCase(fieldName), fieldValue.getClass());
43                     m.invoke(obj, fieldValue);
44                 } catch (Exception  e) {
45                     // TODO Auto-generated catch block
46                     e.printStackTrace();
47                 }
48     }
49
50
51
52 }

  StringUtil.java

 1 package com.frank.sorm.util;
 2
 3 /**
 4  * 封装String 类型的常用操作
 5  * @author frank
 6  *
 7  */
 8 public class StringUtil {
 9
10     /**
11      * 将目标字符串首字母变为大写
12      * @param str 目标字符串
13      * @return 首字母大写的字符串
14      */
15     public static String firstChar2UpperCase(String str){
16
17         return str.toUpperCase().substring(0,1)+str.substring(1);
18
19     }
20
21 }

时间: 2024-10-14 05:41:39

手写ORM持久层框架的相关文章

持久层框架JPA与Mybatis该如何选型

一.现状描述 目前java 持久层ORM框架应用最广泛的就是JPA和Mybatis.JPA只是一个ORM框架的规范, 对该规范的实现比较完整就是Spring Data JPA(底层基于Hibernate实现),是基于Spring的数据持久层框架,也就是说它只能用在Spring环境内.Mybatis也是一个优秀的数据持久层框架,能比较好的支持ORM实体关系映射.动态SQL等. 笔者在学习这两个框架的过程中,看过不少的帖子,每当有帖子比较这两个框架的优缺点,就引来一场论战.从笔者的角度,为什么国内的

MyBatis持久层框架使用总结

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis . 2013年11月迁移到Github,MyBatis的Github地址:https://github.com/mybatis/mybatis-3. iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架.iBATIS提供的持久层框架包括SQL Maps和Dat

持久层框架hibernate相关概念

hibernate为全自动的持久层框架(framework): 1.作用:把内存中的活跃对象永远的保存在关系型数据库中. 2.O/R/M原理:O-->object 对象,R---> relational关系型数据库,M--->mapping映射 为了解决应用程序中的对象和关系型数据库中的表的不匹配而提出的一个解决方案. 3.新版本hibernate4中怎么得到session工厂从而创建连接对象 Configuration cfg = new Configuration().configu

Java数据持久层框架 MyBatis

MyBatis 详细介绍 MyBatis 的前身就是 iBatis .是一个数据持久层(ORM)框架. iBATIS一词来源于"internet"和"abatis"的组合,是一个基于Java的持久层框架.iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO),同时还提供一个利用这个框架开发的 JPetStore实例. 源码来源:minglisoft.cn/technology

Hibernate数据库持久层框架

Hibernate是一种Java语言下的对象关系映射解决方案. 它是使用GNU宽通用公共许可证发行的自由.开源的软件.它为面向对象的领域模型到传统的关系型数据库的映射,提供了一个使用方便的框架.Hibernate也是目前Java开发中最为流行的数据库持久层框架,现已归JBOSS所有. 它的设计目标是将软件开发人员从大量相同的数据持久层相关编程工作中解放出来.无论是从设计草案还是从一个遗留数据库开始,开发人员都可以采用Hibernate. Hibernate不仅负责从Java类到数据库表的映射(还

JPA规范及其它持久层框架

JPA规范及其它持久层框架 JPA是一种规范,而hibernate是JPA的一种实现 JPA全称为Java Persistence API ,Java持久化API是Sun公司在Java EE 5规范中提出的Java持久化接口.JPA吸取了目前Java持久化技术的优点,旨在规范.简化Java对象的持久化工作.使用JPA持久化对象,并不是依赖于某一个ORM框架. JPA是目前比较流行的一种ORM技术之一,所以他拥有ORM技术的各种特点,当然他还有自己的一些优势: 1 标准化 JPA 是 JCP 组织

MyBatis持久层框架使用总结 转载

MyBatis持久层框架使用总结 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis . 2013年11月迁移到Github,MyBatis的Github地址:https://github.com/mybatis/mybatis-3. iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架.iBATIS提供的持久

Hibernate: 数据持久层框架

Hibernate 是一种Java语言下的对象关系映射解决方案. 它是使用GNU宽通用公共许可证发行的自由.开源的软件.它为面向对象的领域模型到传统的关系型数据库的映射,提供了一个使用方便的框架.Hibernate也是目前Java开发中最为流行的数据库持久层框架,现已归JBOSS所有.基于LGPL V2.1协议发布. 它的设计目标是将软件开发人员从大量相同的数据持久层相关编程工作中解放出来.无论是从设计草案还是从一个遗留数据库开始,开发人员都可以采用Hibernate. Hibernate不仅负

优秀的持久层框架Mybatis,连接数据库快人一步

我们之前学习了JDBC和连接池之后,攻城狮们对编程的效率仍然不是很满意.于是乎!有了今天更加优秀的内容,那就是Mybatis框架.它的出现解决了jdbc中的一些问题,提升了代码的鲁棒性.我们一起来看一下吧~ Mybatis介绍 Mybatis是在2010年由阿帕奇下的开源项目ibatis迁移到谷歌codde后,更改为mybatis. 这是一个十分好用的持久层的框架,我们能过通过这种框架实现对jdbc操作的数据库进行封装,我们只需要关心我们数据库SQL本身就可以了,不用麻烦的去注册驱动,连接数据库