首页 > 代码库 > 利用反射搭建项目的dao层,从此可以告别被人的dao层框架了(spring+反射)

利用反射搭建项目的dao层,从此可以告别被人的dao层框架了(spring+反射)

作为一名刚入手的小白程序猿,不但"TA"不懂我们,就连自己都不懂自己,苦逼的程序猿,只能每天都是在给自己充电了。让"TA"和自己更了解。今天笔者又来吹吹水了,各位客官请买好零食咯,好了废话不多说了。
在以前做项目的时候,一般想到搭项目都是用别人的框架来做,但是别人的框架都是别人封装好的很多东西,对不太熟源码的码农来说就是苦逼呀,所以像笔者这种小白又不甘心,所以笔者就用反射来自己封装一个操作dao层的框架(不算一个框架,就是这么称呼吧),说起反射可能是很多像笔者这样的小白都不了解吧(不过好在笔者有点小聪明,自己学习一下)。其实大家在做项目时用的框架都是用反射来搭起来的,所以反射我们并不陌生,先不说太多了,怎么搭建自己dao层,笔者今天的实例子是用(spring+反射)搭建的Webapp,怎么入手呢 ,如下:
①:首先我们搭建springmvc的配置吧(笔者喜欢这样的方式呢),先创建一个springmvc.xml的文件吧:配置文件如下:

 <?xml version="1.0" encoding="UTF-8"?>    <beans xmlns="http://www.springframework.org/schema/beans"	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"	xmlns:context="http://www.springframework.org/schema/context"	xmlns:mvc="http://www.springframework.org/schema/mvc"	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">		<!--自动注解,扫描如下包 -->        <mvc:annotation-driven/>        <context:component-scan base-package="com.yw.Contrlloer"/>        <bean class="org.springframework.web.servlet.mvc.support.ControllerBeanNameHandlerMapping"></bean></beans>

  没错springmvc的配置文件就是这样简单就行了。

② 配好springmvc 接下来就是配置spring了 ,配spring的配置之前我们创建数据库的配置文件先 jdbc.properties。jdbc.properties的配置如下:

validationQuery=SELECT 1	jdbc_URL=jdbc:mysql://127.0.0.1:3306/testredis?useUnicode=true&characterEncoding=UTF-8	jdbc_username=root	jdbc_password=123456	initialSize=0	maxActive=20	maxIdle=20	minIdle=0	maxWait=6000	timeBetweenEvictionRunsMillis=60000	minEvictableIdleTimeMillis=25200000	removeAbandonedTimeout=1800

  然后就是spring的配置的文件了,对了笔者这里用的是阿里的连接池哦,为什么用阿里的,因为是阿里的(哈哈,是因为它强大呢) 配置如下:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"	xmlns:context="http://www.springframework.org/schema/context"	xmlns:tx="http://www.springframework.org/schema/tx"	xmlns:aop="http://www.springframework.org/schema/aop"	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">     <context:annotation-config/>  <context:component-scan base-package="com.yw.dao"/>   <context:component-scan base-package="com.yw.service"/>  <!-- 引入属性文件 -->    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">      <property name="locations" value="http://www.mamicode.com/classpath:com/yw/conf/config.properties"></property>    </bean>        <!-- 配置数据源 -->    <bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">		<property name="url" value="http://www.mamicode.com/${jdbc_URL}" />		<property name="username" value="http://www.mamicode.com/${jdbc_username}" />		<property name="password" value="http://www.mamicode.com/${jdbc_password}" />		<!-- 初始化连接大小 -->		<property name="initialSize" value="http://www.mamicode.com/${initialSize}" />		<!-- 连接池最大使用连接数量 -->		<property name="maxActive" value="http://www.mamicode.com/${maxActive}" />		<!-- 连接池最大空闲 -->		<property name="maxIdle" value="http://www.mamicode.com/${maxIdle}" />		<!-- 连接池最小空闲 -->		<property name="minIdle" value="http://www.mamicode.com/${minIdle}" />		<!-- 获取连接最大等待时间 -->		<property name="maxWait" value="http://www.mamicode.com/${maxWait}" />		<!-- <property name="poolPreparedStatements" value="http://www.mamicode.com/true" /> <property name="maxPoolPreparedStatementPerConnectionSize" value="http://www.mamicode.com/33" /> -->		<property name="validationQuery" value="http://www.mamicode.com/${validationQuery}" />		<property name="testOnBorrow" value="http://www.mamicode.com/false" />		<property name="testOnReturn" value="http://www.mamicode.com/false" />		<property name="testWhileIdle" value="http://www.mamicode.com/true" />		<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->		<property name="timeBetweenEvictionRunsMillis" value="http://www.mamicode.com/${timeBetweenEvictionRunsMillis}" />		<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->		<property name="minEvictableIdleTimeMillis" value="http://www.mamicode.com/${minEvictableIdleTimeMillis}" />		<!-- 打开removeAbandoned功能 -->		<property name="removeAbandoned" value="http://www.mamicode.com/true" />		<!-- 1800秒,也就是30分钟 -->		<property name="removeAbandonedTimeout" value="http://www.mamicode.com/${removeAbandonedTimeout}" />		<!-- 关闭abanded连接时输出错误日志 -->		<property name="logAbandoned" value="http://www.mamicode.com/true" />		<!-- 监控数据库 -->		<!-- <property name="filters" value="http://www.mamicode.com/stat" /> -->		<property name="filters" value="http://www.mamicode.com/mergeStat" />    </bean>   <!-- 配置Jdbc模板  -->   <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" >    <constructor-arg ref="dataSource"></constructor-arg>  </bean>     <bean id="baseDao" class="com.yw.dao.BaseDao" abstract="true">    	 <property name="jdbcTemplate" ref="jdbcTemplate"/>      </bean>    <bean id="userDAo" class="com.yw.dao.UserDao" parent="baseDao"/>          <!-- 配置事务管理器 -->	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">		<property name="dataSource" ref="dataSource" />	</bean>	<tx:advice id="transactionAdvice" transaction-manager="transactionManager">		<tx:attributes>			<tx:method name="add*" propagation="REQUIRED" />			<tx:method name="append*" propagation="REQUIRED" />			<tx:method name="insert*" propagation="REQUIRED" />			<tx:method name="save*" propagation="REQUIRED" />			<tx:method name="update*" propagation="REQUIRED" />			<tx:method name="modify*" propagation="REQUIRED" />			<tx:method name="edit*" propagation="REQUIRED" />			<tx:method name="delete*" propagation="REQUIRED" />			<tx:method name="remove*" propagation="REQUIRED" />			<tx:method name="repair" propagation="REQUIRED" />			<tx:method name="delAndRepair" propagation="REQUIRED" />			<tx:method name="get*" propagation="SUPPORTS" />			<tx:method name="find*" propagation="SUPPORTS" />			<tx:method name="load*" propagation="SUPPORTS" />			<tx:method name="search*" propagation="SUPPORTS" />			<tx:method name="datagrid*" propagation="SUPPORTS"  />			<tx:method name="*" propagation="SUPPORTS" />		</tx:attributes>	</tx:advice>	<aop:config>		<aop:pointcut id="transactionPointcut" expression="execution(* com.yw.service..*(..))" />		<aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" />	</aop:config></beans>

  

好了配置文件就这样可以了。
③ 接来下就是配置web.xml 的文件了:

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">  <display-name>WebApp</display-name>  <welcome-file-list>    <welcome-file>index.html</welcome-file>    <welcome-file>index.htm</welcome-file>    <welcome-file>index.jsp</welcome-file>    <welcome-file>default.html</welcome-file>    <welcome-file>default.htm</welcome-file>    <welcome-file>default.jsp</welcome-file>  </welcome-file-list>   <!-- spring的配置 开始 -->  <context-param>  	<param-name>contextConfigLocation</param-name>  	<param-value>classpath*:com/yw/conf/spring.xml</param-value>  </context-param>  <listener>  	 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  </listener>     <!-- spring的配置 结束 -->     <!-- springmvc的配置 开始  -->  <servlet>    <servlet-name>SpringMvc</servlet-name>  	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>    <init-param>    	<param-name>contextConfigLocation</param-name>    	<param-value>classpath*:com/yw/conf/springmvc.xml</param-value>    </init-param>    <load-on-startup>1</load-on-startup>  </servlet>  <servlet-mapping>  	<servlet-name>SpringMvc</servlet-name>  	<url-pattern>*.do</url-pattern>  </servlet-mapping>  <!-- springmvc的配置  结束 -->    <!-- 字符的过滤器 -->  <filter>    <filter-name>encodingFilter</filter-name>    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>    <init-param>      <param-name>encoding</param-name>      <param-value>UTF-8</param-value>    </init-param>    <init-param>      <param-name>forceEncoding</param-name>      <param-value>true</param-value>    </init-param>  </filter>  <filter-mapping>    <filter-name>encodingFilter</filter-name>    <url-pattern>/*</url-pattern>  </filter-mapping></web-app>

  

④ 创建包的结构了:

⑤创建一个base类dao了, 代码如下:

package com.yw.dao;import java.io.Serializable;import java.lang.reflect.Field;import java.lang.reflect.ParameterizedType;import java.sql.Types;import java.util.List;import org.springframework.jdbc.core.BeanPropertyRowMapper;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.jdbc.core.RowMapper;import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;/** * 有一个规则哦 ,所有model 的字段属性 id这个属性必须放在第一位, * 因为了后来数组拷贝用的 * @author yw * * @param <T> * @param <Tb> */public class BaseDao<T,Tb> {		public static final String SQL_INSERT="insert";	public static final String SQL_UPDATE="update";	public static final String SQL_DELETE="delete";	    private Class<T> entityClass;	private Class<Tb> pClass;	protected NamedParameterJdbcTemplate namedParameterJdbcTemplate;	protected JdbcTemplate jdbcTemplate;	public JdbcTemplate getJdbcTemplate() {		return jdbcTemplate;	}	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {		this.jdbcTemplate = jdbcTemplate;	}	 	public BaseDao(){		ParameterizedType type=(ParameterizedType) getClass().getGenericSuperclass();		entityClass=(Class<T>) type.getActualTypeArguments()[0];	    ParameterizedType  typep=(ParameterizedType) getClass().getGenericSuperclass();	    pClass=(Class<Tb>) typep.getActualTypeArguments()[0];	}	//封装一下简单的组装sql语句,就是常用的哦    public String SQl(String sqlFla){		StringBuffer sb=new StringBuffer();		//获取改bean所有的字段		Field[] field=entityClass.getDeclaredFields();		if(SQL_INSERT.equals(sqlFla)){			sb.append("INSERT INTO ").append(entityClass.getSimpleName())			.append(" (");			for(int i=0;i<field.length;i++){				field[i].setAccessible(true);//暴露反射				sb.append(field[i].getName()).append(",");			}			sb.deleteCharAt(sb.length()-1);			sb.append(" ) ").append("VALUES (");			for(int i=0;i<field.length;i++){				sb.append("?,");			}			sb.deleteCharAt(sb.length()-1);			sb.append(" ) ");		}		else if(SQL_UPDATE.equals(sqlFla)){			sb.append("UPDATE ").append(entityClass.getSimpleName()+" SET ");			for(int i=0;i<field.length;i++){				field[i].setAccessible(true);				if(field[i].getName().equalsIgnoreCase("id")){					continue;				}				sb.append(field[i].getName()).append(" = ").append("?,");			}			sb.deleteCharAt(sb.length()-1);			sb.append(" WHERE id=?");		}		else if(SQL_DELETE.equals(sqlFla)){			sb.append("DELETE FROM ").append(entityClass.getSimpleName());			sb.append(" WHERE id=?");		}    	return sb.toString();    }    //设置值    private Object[] setArgs(T entity,String sqlFla){ 		Field[] fields=entityClass.getDeclaredFields(); 		if(SQL_INSERT.equals(sqlFla)){ 			Object []obj=new Object[fields.length]; 			for (int i = 0; i < obj.length; i++) { 				fields[i].setAccessible(true); 				try {					obj[i]=fields[i].get(entity);				} catch (IllegalArgumentException e) {					e.printStackTrace();				} catch (IllegalAccessException e) {					e.printStackTrace();				}			} 			return obj; 		} 		else if(SQL_UPDATE.equals(sqlFla)){ 			Object []obj=new Object[fields.length]; 			int id=0; 			for (int i = 0; i < obj.length; i++) { 				fields[i].setAccessible(true); 				try {					obj[i]=fields[i].get(entity);				} catch (IllegalArgumentException | IllegalAccessException e) {					e.printStackTrace();				}			} 			Object []objArr=new Object[fields.length]; 		    System.arraycopy(obj, 1, objArr, 0, fields.length-1); 		    objArr[obj.length - 1]=obj[0]; 		    return objArr; 		}else if(SQL_DELETE.equals("delete")){ 			Object[] obj=new  Object[1]; 			fields[0].setAccessible(true); 			try {				obj[0]=fields[0].get(entity);			} catch (IllegalArgumentException e) {				e.printStackTrace();			} catch (IllegalAccessException e) {				e.printStackTrace();			} 			return obj; 		} 		return null; 	}    //设置值对应的类型 	private  int [] setArgsTypes(T entity,String sqlFlag){ 		 Field[] fields = entityClass.getDeclaredFields();           if (sqlFlag.equals(SQL_INSERT)) {               int[] argTypes = new int[fields.length];               try {                   for (int i = 0; argTypes != null && i < argTypes.length; i++) {                       fields[i].setAccessible(true); // 暴力反射                       if (fields[i].get(entity).getClass().getName().equals("java.lang.String")) {                           argTypes[i] = Types.VARCHAR;                       } else if (fields[i].get(entity).getClass().getName().equals("java.lang.Double")) {                           argTypes[i] = Types.DECIMAL;                       } else if (fields[i].get(entity).getClass().getName().equals("java.lang.Integer")) {                           argTypes[i] = Types.INTEGER;                       } else if (fields[i].get(entity).getClass().getName().equals("java.util.Date")) {                           argTypes[i] = Types.DATE;                       }  else if (fields[i].get(entity).getClass().getName().equals("java.sql.Timestamp")) {                           argTypes[i] = Types.TIMESTAMP;                     } else if (fields[i].get(entity).getClass().getName().equals("java.math.BigDecimal")) {                           argTypes[i] = Types.DECIMAL;                     }                 }               } catch (Exception e) {                   e.printStackTrace();               }               return argTypes;           } else if (sqlFlag.equals(SQL_UPDATE)) {               int[] tempArgTypes = new int[fields.length];               int[] argTypes = new int[fields.length];               try {                   for (int i = 0; tempArgTypes != null && i < tempArgTypes.length; i++) {                       fields[i].setAccessible(true); // 暴力反射                       if (fields[i].get(entity).getClass().getName().equals("java.lang.String")) {                           tempArgTypes[i] = Types.VARCHAR;                       } else if (fields[i].get(entity).getClass().getName().equals("java.lang.Double")) {                           tempArgTypes[i] = Types.DECIMAL;                       } else if (fields[i].get(entity).getClass().getName().equals("java.lang.Integer")) {                           tempArgTypes[i] = Types.INTEGER;                       } else if (fields[i].get(entity).getClass().getName().equals("java.util.Date")) {                           tempArgTypes[i] = Types.DATE;                       } else if (fields[i].get(entity).getClass().getName().equals("java.sql.Timestamp")) {                       	tempArgTypes[i] = Types.TIMESTAMP;                     } else if (fields[i].get(entity).getClass().getName().equals("java.math.BigDecimal")) {                       	tempArgTypes[i] = Types.DECIMAL;                     }                 }                   System.arraycopy(tempArgTypes, 1, argTypes, 0, tempArgTypes.length - 1); // 数组拷贝                   argTypes[argTypes.length - 1] = tempArgTypes[0];                  } catch (Exception e) {                   e.printStackTrace();               }               return argTypes;              } else if (sqlFlag.equals(SQL_DELETE)) {               int[] argTypes = new int[1]; // 长度是1               try {                   fields[0].setAccessible(true); // 暴力反射                   if (fields[0].get(entity).getClass().getName().equals("java.lang.String")) {                       argTypes[0] = Types.VARCHAR;                   } else if (fields[0].get(entity).getClass().getName().equals("java.lang.Integer")) {                       argTypes[0] = Types.INTEGER;                   }                  } catch (Exception e) {                   e.printStackTrace();               }               return argTypes;           }           return null;   	}	    public void save(T entity){    	String sql=this.SQl(SQL_INSERT);    	Object [] obj=this.setArgs(entity, SQL_INSERT);    	System.out.println(sql);    	for (int i = 0; i < obj.length; i++) {    		System.out.println("--------------------");			System.out.println(obj[i]);			System.out.println("--------------------");		}    	int [] objTypes=this.setArgsTypes(entity, SQL_INSERT);        jdbcTemplate.update(sql, obj,objTypes);    }	    public void upate(T entity){    	String sql=this.SQl(SQL_UPDATE);    	Object [] obj=this.setArgs(entity, SQL_UPDATE);    	int [] objTypes=this.setArgsTypes(entity, SQL_UPDATE);        jdbcTemplate.update(sql, obj, objTypes);    }      public void delete(T entity){    	String sql=this.SQl(SQL_DELETE);    	Object [] obj=this.setArgs(entity, SQL_DELETE);    	int [] objTypes=this.setArgsTypes(entity, SQL_DELETE);        jdbcTemplate.update(sql, obj, objTypes);    }        public List<T> findAll(){    	String sql="SELECT * FROM "+entityClass.getSimpleName();    	RowMapper<T> rowMapper=BeanPropertyRowMapper.newInstance(entityClass);     	return jdbcTemplate.query(sql, rowMapper);    }     public T findById(Serializable id){    	String sql="SELECt * FROM  "+entityClass.getSimpleName()+"  where id=?";    	RowMapper<T> rowMapper=BeanPropertyRowMapper.newInstance(entityClass);    	if(jdbcTemplate.query(sql, rowMapper, id).size()>0)    		return jdbcTemplate.query(sql, rowMapper, id).get(0);		return null;    }  }

  ⑥ 写一个Uerdao集成baseDao,代码如下

package com.yw.dao;import com.yw.Dto.UserDto;import com.yw.model.User;public class UserDao extends BaseDao<User, UserDto> {	}

  就是这样就行了,想增加一个sql语句就这样慢慢一个添加就的了

⑦ model和dto如下:

package com.yw.model;public class User {	@Override	public String toString() {		return "User [id=" + id + ", name=" + name + ", pass=" + pass + "]";	}	private Integer id;		public Integer getId() {		return id;	}	public void setId(Integer id) {		this.id = id;	}	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;	}	private String name;	private String pass;}/---------------------/package com.yw.Dto;public class UserDto {private int id;		public int getId() {		return id;	}	public void setId(int id) {		this.id = id;	}	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;	}	private String name;		private String pass;}

  ⑧ service层创建 一个Userservice,代码如下:

package com.yw.service;import java.util.List;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.yw.dao.UserDao;import com.yw.model.User;@Service("userService")public class UserService {    @Autowired	private UserDao  userDao;        public void  save(User user){    	userDao.save(user);	    }        public void delete(User user){    	userDao.delete(user);    }       public void update(User user){    	userDao.upate(user);    }    public User findById(int id){    	return userDao.findById(id);    }    public void findAll(){    	    	List<User> user=userDao.findAll();    	System.out.println(user);    }} 

  ⑨ 就是Contrlloer层了 创建一个userController

package com.yw.Contrlloer;import java.io.IOException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import com.yw.model.User;import com.yw.service.UserService;@Controller@RequestMapping("/test/controller")public class UserController {	@Autowired	private UserService userService;	   @RequestMapping("/test.do")	public void test(HttpServletRequest reServletRequest,HttpServletResponse response) throws IOException{		 response.getWriter().println("23456789-");		 //查询所有的用户		 userService.findAll();		 //查询id为2的用户		 User user=userService.findById(2);		 //增加一个用户		 User user2=new User();		 user2.setId(0); //增加数据的是数据库的id为在自增的,所以在这里就写死了		 user2.setName("夏明");		 user2.setPass("12345678");		 userService.save(user2);		 //删除一个用户		 userService.delete(user);		 //更新一个用户,更新之前最好是查询一次在更新		 User user3=userService.findById(2);		 user3.setName("GaVien");		 userService.update(user3);		 	}}

  

好了到这里算是真正完成了,直接跑起来O了,项目就这样就结束。
笔者说说在遇到问题和注意事项以及心得吧:
(1)笔者老是在配置spring配置出错的,老是报bean创建失败,出现这个问题 第一个可能是 扫描包可能没有扫到
第二可能是bean的配置的class的包的路径不对
第三可能是你的jdk编译有问题,如是:自己百度一下,更换一下jdk吧
第四可能是你没有添加bean吧
(2)创建model的时候有id的必须在所有字段的属性前面,为后来的baseDao的数据拷贝方便呢
(3)经过笔者的测试 ,自己的写反射运行和数据库响应时间并没有比mybatis和hibernate慢甚至还快呢呢,而且自己写的反射所有sql语句都可以自己去控制,没有任何多余的数据呢,
(4)对于宇宙无敌的spring框架不熟,那你就只能自己去补了,反射也是咯 哈哈

最后项目下载路径 http://pan.baidu.com/s/1c2mMHiS

 

利用反射搭建项目的dao层,从此可以告别被人的dao层框架了(spring+反射)