- 浏览: 82038 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
yangfuchao418:
楼主你这个实在太simple了。你可以用htmlunit。
commons-httpclient 的使用(模拟浏览器) -
fengfeng925:
<div class="quote_title ...
用反射注解实现的ORM(一看就明白的那种) -
pclfs1983:
楼上说的很有道理
用反射注解实现的ORM(一看就明白的那种) -
linliangyi2007:
楼主的工作还是很值得实践一次的,尤其是学习研究阶段。写过和看过 ...
用反射注解实现的ORM(一看就明白的那种) -
linliangyi2007:
<div class="quote_title ...
用反射注解实现的ORM(一看就明白的那种)
之所以会写这个程序完全是因为偷懒^^,那时在公司实习要我们用jdbc来写练习,想想已经很久没用过纯的jdbc来写操作数据库了,用Hibernate多好啊,最少也可以用ibatis,想到那么SQL语句就烦,写来写去都是那几句。那时刚好学过反射和注解所以就决定自己写一个ORM框架,当然只是简单的那种,刚开始用到了apache下的开源项目dbutils,不过后来就慢慢的改进用反射来代替,虽然现在那用到这个包,关键部分还是用反射实现的.
核心类:
package com.permission.utils.db; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.ArrayList; import java.util.Enumeration; import java.util.Hashtable; import java.util.List; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanListHandler; import com.permission.utils.log.LogUtil; /** * @Title: OperateDB.java * @Package com.cai.order.db * @Description: TODO(ORM) * @author awfhome@163.com * @date 2010-3-6 下午01:46:05 * @version V1.2 */ public class OperateDB { private Connection conn = null; private String sql =""; private PreparedStatement pst; private Hashtable map = null; public void setConnection(Connection conn) { this.conn = conn; } /** * 创建sql语句 */ public void createQuery(String sql){ map = new Hashtable(); //初始化 this.sql = sql; } /**设置参数*/ @Deprecated public void setParameter(String name,String val){ map.put(name, val); } /**设置String类型参数*/ public void setParameterString(String name,String val){ map.put(name, val); } /**设置Integer类型参数*/ public void setParameterString(String name,Integer val){ map.put(name, Integer.toString(val)); } /**设置Double类型参数*/ public void setParameterString(String name,Double val){ map.put(name, Double.toString(val)); } /** * 处理sql语句(数据库标准的sql) */ private String doSql(){ if(sql!=null && !"".equals(sql)){ String tem = ""; Enumeration e = map.keys(); while(e.hasMoreElements()){ tem = (String)e.nextElement(); this.sql = sql.replace(":" + tem, "'" +(String) map.get(tem)+"'"); } }else { System.out.println("没有sql语句"); } LogUtil.info("这次调用的sql语名: " + sql); return sql; } /** * 返回类数组,这部分用的是dbutils */ public List list(Class type) throws SQLException{ doSql(); //调用处理sql成标准 List list = null; QueryRunner queryR = new QueryRunner(); list = (List)queryR.query(conn, sql, new BeanListHandler(type)); return list; } /** * 返回单个数据 */ public Object uniqueResult(Class type) throws SQLException{ doSql(); Object object = null; List list = null; QueryRunner queryR = new QueryRunner(); list = (List)queryR.query(conn, sql, new BeanListHandler(type)); if(list != null && list.size()!=0) object = (Object)list.get(0); return object; } /** * 返回影响行数 */ public int executeUpdate() throws SQLException{ doSql(); QueryRunner queryR = new QueryRunner(); int a = queryR.update(conn,sql); return a; } /** 添加数据 * @throws NoSuchMethodException * @throws SecurityException * @throws InvocationTargetException * @throws IllegalAccessException * @throws IllegalArgumentException * @throws SQLException */ public int save(Object object) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, SQLException { List<String> list = new ArrayList(); StringBuffer str = new StringBuffer(); String _tableName = ""; Class c = object.getClass(); //解析类获取表名 FieldAnnotation _file = (FieldAnnotation) c.getAnnotation(FieldAnnotation.class); if(_file!=null){ _tableName = _file.name();//得到表名,如果没有写,将用和类名一样的表名 if("_null".equals(_tableName)){ _tableName = c.getSimpleName(); LogUtil.info("警告:你这个使用的是同类名相同的表名,请在对应的类注解表名! " ); } }else {//没有在类上注解表名 _tableName = c.getSimpleName(); LogUtil.info("警告:你这个使用的是同类名相同的表名,请在对应的类注解表名! " ); } str.append("insert into " + _tableName +"("); //解析属性 Field[] fs = c.getDeclaredFields(); for(int i = 0; i < fs.length; i++){ Field f = fs[i]; PrimaryAnnotation pa = f.getAnnotation(PrimaryAnnotation.class); if(pa!=null){ LogUtil.debug("检测到主键标识,SQL语句忽略主键,对应的字段为:" + f.getName()); }else { //非主键,忽略主键字键来创建SQL语句 str.append(f.getName()); if(i!=fs.length-1) str.append(","); list.add(f.getName()); } } str.append(") values("); // System.out.println(str); //解析方法,调用方法get() for(int i = 0; i < list.size(); i++){ String s = list.get(i); String tem = s.substring(0, 1).toUpperCase(); String tem2 = s.substring(1); String tem3 = tem + tem2; Method m = c.getMethod("get"+ tem3); //System.out.println(m.toString()); Object result = m.invoke(object); if(result==null){ str.append("null"); }else{ str.append("'" +result.toString() + "'"); } if(i!=list.size()-1){ str.append(","); String ss = str.toString(); //System.out.println(ss); } } str.append(")"); sql = str.toString(); LogUtil.info("此次调用的SQL语名: " + sql); QueryRunner queryR = new QueryRunner(); int a = queryR.update(conn,sql); LogUtil.info("添加数据完成!"); return a; } /**根据对象主键修改数据 * @throws NoSuchMethodException * @throws SecurityException * @throws InvocationTargetException * @throws IllegalAccessException * @throws IllegalArgumentException * @throws SQLException */ public boolean update(Object object) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, SQLException{ List<String> list = new ArrayList(); StringBuffer str = new StringBuffer(); String _tableName = "";//表名 String pk_name = "主键名"; //主键 String pk_id = "主键值"; //主键 Class c = object.getClass(); //解析类获取表名 FieldAnnotation _file = (FieldAnnotation) c.getAnnotation(FieldAnnotation.class); if(_file!=null){ _tableName = _file.name();//得到表名,如果没有写,将用和类名一样的表名 if("_null".equals(_tableName)){ _tableName = c.getSimpleName(); LogUtil.info("警告:你这个使用的是同类名相同的表名,请在对应的类注解表名! " ); } }else {//没有在类上注解表名 _tableName = c.getSimpleName(); LogUtil.info("警告:你这个使用的是同类名相同的表名,请在对应的类注解表名! " ); } //update student set sex='xx',dsf='' where xh=001; str.append("update " + _tableName +" set "); //解析属性+方法 Field[] fs = c.getDeclaredFields(); for(int i = 0; i < fs.length; i++){ Field f = fs[i]; PrimaryAnnotation pa = f.getAnnotation(PrimaryAnnotation.class); if(pa!=null){ LogUtil.info("检测到主键标识,SQL语句主键,进行主键条件查询"); pk_name = f.getName(); String tem = pk_name.substring(0, 1).toUpperCase(); String tem2 = pk_name.substring(1); String tem3 = tem + tem2; Method m = c.getMethod("get"+ tem3); Object result = m.invoke(object); pk_id = result.toString(); //LogUtil.info("检测到主键标识,SQL语句主键进行条件查询 " + pk_id); }else { //非主键,忽略主键字键来创建SQL语句 String s = f.getName(); str.append(s); str.append("="); //调用对应的get方法 String tem = s.substring(0, 1).toUpperCase(); String tem2 = s.substring(1); String tem3 = tem + tem2; Method m = c.getMethod("get"+ tem3); //System.out.println(m.toString()); Object result = m.invoke(object); if(result==null){ str.append("null"); }else{ str.append("'" +result.toString() + "'"); } if(i!=fs.length-1) str.append(", "); } } str.append(" where " + pk_name + " = " + pk_id ); sql = str.toString(); LogUtil.info("此次调用的SQL语名: " + sql); QueryRunner queryR = new QueryRunner(); int a = queryR.update(conn,sql); LogUtil.info("添加数据完成!"); if(a!=0){ return true; } return false; } /**关闭连接*/ public void close(){ try{ if (conn != null) { conn.close(); } }catch(Exception e){ LogUtil.info("关闭数据库时出错了..."); e.printStackTrace(); } } }
改进了处理sql语句:
public class StringToHql { private String hql =""; private Hashtable map = null; //初始化1 public StringToHql(){ } //初始化2 public StringToHql(String hql){ map = new Hashtable(); //初始化 this.hql = hql; } /** * 创建hql语句 */ public StringToHql createQuery(String hql){ map = new Hashtable(); //初始化 this.hql = hql; return this; } /**设置String类型参数*/ public StringToHql setParameterString(String name,String val){ map.put(name, val); return this; } /**设置Integer类型参数*/ public StringToHql setParameterString(String name,Integer val){ map.put(name, val); return this; } /**设置Double类型参数*/ public StringToHql setParameterString(String name,Double val){ map.put(name,val); return this; } /** * 处理hql语句(数据库标准的hql) */ public String doHql(){ if(hql!=null && !"".equals(hql)){ String tem = ""; Enumeration e = map.keys(); while(e.hasMoreElements()){ tem = (String)e.nextElement(); //key ~ String if(map.get(tem) instanceof Integer) { this.hql = hql.replace(":" + tem, "" +(Integer) map.get(tem)+" "); }else if(map.get(tem) instanceof String){ this.hql = hql.replace(":" + tem, "'" +(String) map.get(tem)+"'"); }else if(map.get(tem) instanceof Double){ this.hql = hql.replace(":" + tem, "" +(Double) map.get(tem)+" "); } } }else { System.out.println("没有sql语句"); } LogUtil.info("这次调用的sql语名[StringToHql]: " + hql); return hql; } /** * 测试,使用方法 */ @Test public void test1(){ StringToHql st = new StringToHql(); st.createQuery("from Manager where anutoh=:anutoh"); st.setParameterString("anutoh", "小明"); String hql = st.doHql(); System.out.println(hql); } @Test public void test2(){ String hql = new StringToHql("from Manager where anutoh=:anutoh and mone=:mone") .setParameterString("anutoh", "小明2") .setParameterString("mone", 4500.5) .doHql(); System.out.println(hql); } }
注解:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @Title: PrimaryAnnotation.java * @Package com.cai.order.db * @Description: TODO(用于标识主键的注解) * @author awfhome@163.com * @date 2010-3-6 下午02:26:13 * @version V1.x */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface PrimaryAnnotation { }
import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * @Title: FieldAnnotation.java * @Package com.cai.order.db * @Description: TODO(用于注解数据库表名,字段;对应类的类,属性) * @author awfhome@163.com * @date 2010-3-6 下午03:13:51 * @version V1.x */ @Retention(RetentionPolicy.RUNTIME) public @interface FieldAnnotation { String name() default "_null"; }
model:
/**角色*/ @FieldAnnotation(name = "role") public class Role { @PrimaryAnnotation private int roleId; private String roleName; private String description; public int getRoleId() { return roleId; } public void setRoleId(int roleId) { this.roleId = roleId; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } }
还有很多没有实现的功能,例如只能标识一个主键和表名,但是数据库字段现在只能和model属性一样,不过实现过程和主键差不多,后来看到了设计模式之模板模式和策略模式如果能结合他们,那就程序就更灵活了,spring的hibernate模板就是用这两种模式来设计的.
评论
14 楼
fengfeng925
2010-05-27
linliangyi2007 写道
sunson468 写道
有那么多开源的成熟的架构,除非非常有必要,否则还是拿来主义比较好。
只是研究的话也不错~
顺便感概下,java的反射效率真的不咋地~
只是研究的话也不错~
顺便感概下,java的反射效率真的不咋地~
我不认为java的反射效率不咋地?楼上的真的试过了吗?没试过不要用自己的感觉来作为判断标准。5.0开始的java已经在类反射上优化了很多。
你可以测试一下用一堆if else和用类反射方式的语句哪个更快,在数量越大的情况下,你会发现,类反射更有效率
说的很对,从jdk1.5开始,虚拟机已经做了很多优化,1.6更比1.5优化了不少。
13 楼
pclfs1983
2010-05-26
楼上说的很有道理
12 楼
linliangyi2007
2010-05-26
楼主的工作还是很值得实践一次的,尤其是学习研究阶段。写过和看过代码根本就是两个层次。
11 楼
linliangyi2007
2010-05-26
sunson468 写道
有那么多开源的成熟的架构,除非非常有必要,否则还是拿来主义比较好。
只是研究的话也不错~
顺便感概下,java的反射效率真的不咋地~
只是研究的话也不错~
顺便感概下,java的反射效率真的不咋地~
我不认为java的反射效率不咋地?楼上的真的试过了吗?没试过不要用自己的感觉来作为判断标准。5.0开始的java已经在类反射上优化了很多。
你可以测试一下用一堆if else和用类反射方式的语句哪个更快,在数量越大的情况下,你会发现,类反射更有效率
10 楼
crazy.j
2010-05-26
bluedest 写道
不知道为什么,相当反感注解这种东西
我也一样,看着不规矩!
9 楼
ironsabre
2010-05-26
aws 写道
另外反射其实也可以把method缓存起来吧
这没用,每个实体对象的属性值还得通过反射来得到。
我这个http://www.iteye.com/topic/675119也用反射实现了一个ActiveRecord,不需要注解,纯约定。
里边有一个地方可以缓存的是数据库结构。只需取一次。
8 楼
aws
2010-05-26
另外反射其实也可以把method缓存起来吧
7 楼
psuqqvfp
2010-05-26
反射还可以,不是很占时间
6 楼
bluedest
2010-05-25
不知道为什么,相当反感注解这种东西
5 楼
tomorrow009
2010-05-25
J-catTeam 写道
性能的瓶颈不在反射上
仁兄说的对.
对于Java的持久层访问来说,真正瓶颈在于数据库连接的开销,反射虽然不快却并不是短板所在.
4 楼
J-catTeam
2010-05-25
性能的瓶颈不在反射上
3 楼
hrsvici412
2010-05-25
哈哈,不怎么的
2 楼
awfrun
2010-05-25
虽然反射效率不好,但目前我用过的几个开源ORM框架底层都是用反射来实现的.
1 楼
sunson468
2010-05-25
有那么多开源的成熟的架构,除非非常有必要,否则还是拿来主义比较好。
只是研究的话也不错~
顺便感概下,java的反射效率真的不咋地~
只是研究的话也不错~
顺便感概下,java的反射效率真的不咋地~
发表评论
-
jxl,poi笔记
2010-10-19 15:38 1478由于最近要用到Excel数据导入数据库,在网上查了一下,目前一 ... -
commons-httpclient 的使用(模拟浏览器)
2010-07-10 15:38 12711.由于最近要做一个功能模块,要用于实时发送技术,然后取出返回 ... -
Cookie 工具类
2010-07-04 11:01 0x -
(三)UML下的各种图
2010-05-25 12:17 0类图: 类图上使用包含三个部分的矩形来描述,最上面的部分显示 ... -
简单的spring对数据库CURD (hibernate)类
2010-05-18 14:00 1372import java.util.List; impor ... -
日志工具类
2010-05-18 13:55 804import org.apache.log4j.Logger; ... -
获取时间的类
2010-05-18 13:54 799import java.util.Calendar; p ... -
实现一个简单处理sql语句的类
2010-05-15 17:18 855import java.util.Enumeration; ...
相关推荐
Java反射机制是Java编程语言中的一个强大特性,它允许运行时的Java程序访问、操作类、接口、字段和方法的信息,甚至能够动态调用方法和创建对象。在深入理解Java反射机制之前,我们先要明白类加载的过程。当Java程序...
首先,我们要明白,Hibernate4.x的核心在于它提供了一种桥梁,将Java对象与数据库表之间建立了映射关系。通过XML或注解的方式定义实体类和数据库表之间的映射关系,这被称为Hibernate的元数据配置。 一、Hibernate4...
首先,我们要明白,Hibernate的核心在于它提供了一种桥梁,连接了Java对象与数据库表之间的鸿沟。它允许我们用面向对象的方式处理数据库操作,从而降低了数据库编程的复杂性。源代码jar包1包含了Hibernate的核心组件...
(再加一条,其实大家可以看官方的教程更好些:http://mybatis.github.io/mybatis-3/,而且如果英文不是很好的那就看中文的:http://mybatis.github.io/mybatis-3/zh/sqlmap-xml.html) 写在这个系列前面的话: 以前...
ta_lib-0.5.1-cp312-cp312-win32.whl
课程设计 在线实时的斗兽棋游戏,时间赶,粗暴的使用jQuery + websoket 实现实时H5对战游戏 + java.zip课程设计
ta_lib-0.5.1-cp310-cp310-win_amd64.whl
基于springboot+vue物流系统源码数据库文档.zip
GEE训练教程——Landsat5、8和Sentinel-2、DEM和各2哦想指数下载
知识图谱
333498005787635解决keil下载失败的文件.zip
【微信机器人原理与实现】 微信机器人是通过模拟微信客户端的行为,自动处理消息、发送消息的程序。在Python中实现微信机器人的主要库是WeChatBot,它提供了丰富的接口,允许开发者方便地进行微信消息的接收与发送。这个项目标题中的"基于python实现的微信机器人源码"指的是使用Python编程语言编写的微信机器人程序。 1. **Python基础**:Python是一种高级编程语言,以其简洁的语法和强大的功能深受开发者喜爱。在实现微信机器人时,你需要熟悉Python的基本语法、数据类型、函数、类以及异常处理等概念。 2. **微信API与WeChatBot库**:微信为开发者提供了微信公共平台和微信开放平台,可以获取到必要的API来实现机器人功能。WeChatBot库是Python中一个用于微信开发的第三方库,它封装了微信的API,简化了消息处理的流程。使用WeChatBot,开发者可以快速搭建起一个微信机器人。 3. **微信OAuth2.0授权**:为了能够接入微信,首先需要通过OAuth2.0协议获取用户的授权。用户授权后,机器人可以获取到微信用户的身份信息,从而进行
基于springboot实验室研究生信息管理系统源码数据库文档.zip
张力控制,色标跟踪,多轴同步,电子凸轮,横切等工艺控制案例。
在Python编程环境中,处理Microsoft Word文档是一项常见的任务。Python提供了几个库来实现这一目标,如`python-docx`,它可以让我们创建、修改和操作.docx文件。本教程将重点介绍如何利用Python进行Word文档的合并、格式转换以及转换为PDF。 1. **合并Word文档(merge4docx)** 合并多个Word文档是一项实用的功能,特别是在处理大量报告或文档集合时。在Python中,可以使用`python-docx`库实现。我们需要导入`docx`模块,然后读取每个文档并将其内容插入到主文档中。以下是一个基本示例: ```python from docx import Document def merge4docx(file_list, output_file): main_doc = Document() for file in file_list: doc = Document(file) for paragraph in doc.paragraphs: main_doc.add_paragraph(paragraph.text) m
基于springboot+Javaweb的二手图书交易系统源码数据库文档.zip
基于springboot餐品美食论坛源码数据库文档.zip
基于springboot亚运会志愿者管理系统源码数据库文档.zip
使用WPF的数据样式绑定,切换对象数据值来完成控件动态切换背景渐变动画效果。 使用动画样式渲染比线程修改性能消耗更低更稳定
基于SpringBoot的企业客源关系管理系统源码数据库文档.zip