自己动手写泛型dao
在经过一系列的问题得到解决之后,泛型dao终于写出来了。泛型dao相比于以前写的dao最大的好处就是,大大提高了代码的复用性,以往我们要对数据库中表中的数据进行操作的时候,每张表都需要写一个dao来操作,当表非常多的时候,代码量就会很大,还有就是这些代码大部分都是重复的,获取数据库连接、sql预处理,返回结果集,最后关闭数据库连接,获取数据库连接和关闭资源可以放在一个数据库工具类中很简单,剩下的对数据进行操作的方法,由于我们事先不知道要对那张表进行操作,所以就需要利用一些特殊的手段来获取,动态的获取,利用反射这个特性,我们可以很容易的获得我们想要得到的信息。
在前面有一篇文章讲了反射获取类中信息的例子: 通过反射获取属性名和属性类型 这篇文章就是在这里遇到的问题
还有就是在存储获得到的数据时候,需要用到有序的键值对在:有序的Map集合--LinkedHashMap 中说明了
下面开始正题:
代码结构:
在例子中用到了c3p0和读取properties配置文件连接数据库,构建数据库连接池,在第一个方法中写了注释,剩下的方法都是类似的
注意:代码中有get和getset方法分别是拼接get方法和set方法的方法……还有获得属性信息的getField方法都在代码的最后面
package com_basedao; import java.util.List; /** * Created with IDEA * author:DuzhenTong * Date:2017/11/8 * Time:19:40 */ public interface BaseDao<T> { void update(T t, String password, int id); void insert(T t); void delete(T t, int id); List selectAll(T t); List selectOne(T t,int id); }
package com_daoImp; import com_basedao.BaseDao; import com_util.JdbcUtil; 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.ResultSet; import java.sql.SQLException; import java.util.*; /** * Created with IDEA * author:DuzhenTong * Date:2017/11/8 * Time:19:46 */ public class BaseDaoImp<T> implements BaseDao<T>{ private Connection connection; private PreparedStatement preparedStatement; private ResultSet resultSet; private String sql; private List<Object> list = null; //LinkedHashMap是一个有顺序的map集合 private static Map<String, String> map = new LinkedHashMap<String, String>(); /** * 查询表中所有数据 * @param t * @return */ @Override public List<Object> selectAll(T t) { //初始化字符串 StringBuffer stringBuffer = new StringBuffer("select * from "); //创建对象的容器list集合 list = new ArrayList<Object>(); //获取类的类 Class clazz =t.getClass(); //获取到类的名字处理拼接sql语句 sql = stringBuffer.append(clazz.getSimpleName()).toString().toLowerCase(); try { connection = JdbcUtil.getInstance().getConnection(); preparedStatement = connection.prepareStatement(sql); resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { //利用反射获得对象 Object object = clazz.newInstance(); getField(object); int i = 1; //遍历map集合 for (Map.Entry<String, String> entry : map.entrySet()) { if ("int".equals(entry.getValue())) { //利用发射获取实体类中的set方法 Method method = clazz.getMethod(getSet(entry.getKey()), int.class); //执行方法 method.invoke(object, resultSet.getInt(i)); //从结果集中想要获取列值需要一个计数器如果查到的是本列加一 i++; } if ("String".equals(entry.getValue())) { Method method = clazz.getMethod(getSet(entry.getKey()), String.class); method.invoke(object, resultSet.getString(i)); i++; } } list.add(object); } } catch (SQLException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); }finally { JdbcUtil.releaseResources(connection,preparedStatement,resultSet); } return list; } /** * 根据id查询 * @param t * @param id * @return */ @Override public List<Object> selectOne(T t,int id) { StringBuffer stringBuffer = new StringBuffer("select * from "); list = new ArrayList<Object>(); Class clazz = t.getClass(); sql = stringBuffer.append(clazz.getSimpleName()+" where id=?").toString().toLowerCase(); try { connection = JdbcUtil.getInstance().getConnection(); preparedStatement = connection.prepareStatement(sql); preparedStatement.setInt(1,id); resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { Object object = clazz.newInstance(); getField(t); int i = 1; for (Map.Entry<String, String> entry : map.entrySet()) { if ("int".equals(entry.getValue())) { Method method = clazz.getMethod(getSet(entry.getKey()), int.class); method.invoke(object, resultSet.getInt(i)); i++; } if ("String".equals(entry.getValue())) { Method method = clazz.getMethod(getSet(entry.getKey()), String.class); method.invoke(object, resultSet.getString(i)); i++; } } list.add(object); } } catch (SQLException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); }finally { JdbcUtil.releaseResources(connection,preparedStatement,resultSet); } return list; } /** * 根据id删除记录 * @param t * @param id */ @Override public void delete(T t, int id){ StringBuffer stringBuffer = new StringBuffer("delete from "); Class clazz = t.getClass(); String tableName = clazz.getSimpleName().toLowerCase(); sql = stringBuffer.append(tableName + " where id=?").toString(); try { connection = JdbcUtil.getInstance().getConnection(); preparedStatement = connection.prepareStatement(sql); preparedStatement.setInt(1, id); preparedStatement.execute(); } catch (SQLException e) { e.printStackTrace(); }finally { JdbcUtil.releaseResources(connection, preparedStatement, null); } } /** * 修改密码 * @param t * @param password * @param id */ @Override public void update(T t, String password, int id) { Class clazz = t.getClass(); String tableName = clazz.getSimpleName().toLowerCase(); StringBuffer stringBuffer = new StringBuffer("update " + tableName + " set password=? where id=?"); sql = stringBuffer.toString(); try { connection = JdbcUtil.getInstance().getConnection(); preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, password); preparedStatement.setInt(2, id); preparedStatement.execute(); } catch (SQLException e) { e.printStackTrace(); } finally { JdbcUtil.releaseResources(connection, preparedStatement, null); } } /** * 增加记录 * @param t */ @Override public void insert(T t) { StringBuffer stringBuffer = new StringBuffer("insert into "); Class clazz = t.getClass(); String table = clazz.getSimpleName().toLowerCase(); try { Object object = t; getField(object); stringBuffer.append(table + " values("); for (int i = 0; i < map.size(); i++) { if (i == map.size() - 1) { stringBuffer.append("?)"); }else { stringBuffer.append("?,"); } } sql = stringBuffer.toString(); connection = JdbcUtil.getInstance().getConnection(); preparedStatement = connection.prepareStatement(sql); System.out.println(sql); int i=1; for (Map.Entry<String, String> entry : map.entrySet()) { if ("int".equals(entry.getValue())) { Method method = clazz.getMethod(get(entry.getKey())); System.out.println(method.invoke(object,null)); preparedStatement.setInt(i,(int)method.invoke(object,null)); i++; } if ("String".equals(entry.getValue())) { Method method = clazz.getMethod(get(entry.getKey())); preparedStatement.setString(i,(String)method.invoke(object,null)); i++; } } preparedStatement.execute(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); }finally { JdbcUtil.releaseResources(connection,preparedStatement,null); } } /** * 根据属性名拼接set方法字符串 * @param str * @return */ public static String getSet(String str) { return "set" + str.substring(0, 1).toUpperCase() + str.substring(1); } /** * 拼接get方法 * @param str * @return */ public static String get(String str) { return "get" + str.substring(0, 1).toUpperCase() + str.substring(1); } public static void getField(Object object) { Class clazz = object.getClass(); // 获取实体类的所有属性,返回Field数组 Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { String type = field.getGenericType().toString(); /*如果是String听会带有class java.lang.String截取再放入map中,其他直接放入 * 把属性名作为键,属性类型作为值*/ if ("class java.lang.String".equals(type)) { int index = type.lastIndexOf("."); map.put(field.getName(), type.substring(index + 1)); } else { map.put(field.getName(), field.getGenericType().toString()); } } } }
数据库工具类:JdbcUtil 用到了单例模式
package com_util; import com.mchange.v2.c3p0.ComboPooledDataSource; import java.beans.PropertyVetoException; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Properties; public class JdbcUtil { private Properties properties = new Properties(); private static String dirverName; private static String url; private static String username; private static String password; private static ComboPooledDataSource dataSource; private static JdbcUtil jdbcUtil = new JdbcUtil(); private JdbcUtil() { try { InputStream inputStream = JdbcUtil.class.getClassLoader() .getResourceAsStream("datebase.properties"); // 从输入字节流读取属性列表(键和元素对) properties.load(inputStream); // 用此属性列表中指定的键搜索属性,获取驱动,url,username,password dirverName = properties.getProperty("driverName").trim(); url = properties.getProperty("url").trim(); username = properties.getProperty("username").trim(); password = properties.getProperty("password").trim(); dataSource = new ComboPooledDataSource(); dataSource.setUser(username); dataSource.setPassword(password); dataSource.setJdbcUrl(url); dataSource.setDriverClass(dirverName); dataSource.setInitialPoolSize(5); //初始化连接数 dataSource.setMinPoolSize(1);//最小连接数 dataSource.setMaxPoolSize(20);//最大连接数 dataSource.setMaxStatements(50);//最长等待时间 dataSource.setMaxIdleTime(60);//最大空闲时间,单位毫秒 } catch (PropertyVetoException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public static JdbcUtil getInstance(){ return jdbcUtil; } public synchronized Connection getConnection() { Connection conn = null; try { conn=dataSource.getConnection(); } catch (SQLException e) { e.printStackTrace(); } return conn; } //关闭连接工具方法 public static void releaseResources(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet) { if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if (connection != null) { try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } if (preparedStatement != null) { try { preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
实体类:用于测试
package com_domain; public class Users { private int id; private String name; private String password; private int aid; @Override public String toString() { return "Users{" + "id=" + id + ", name='" + name + '\'' + ", password='" + password + '\'' + ", aid=" + aid + '}'; } 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 getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getAid() { return aid; } public void setAid(int aid) { this.aid = aid; } }
datebase.properties数据库连接配置文件
driverName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/test username=root password=root
代码放在了github上,可以下载完整代码(Code_story仓库fanxing文件夹):https://github.com/Ai-yoo/Code_story.git