该工具类是在JavaWeb中连接mysql所用到的通用工具类
该类用于Java+Servlet的编程中,方便数据库的操作,连接,获取其列表值。下面是这个数据库操作类的通用方法,基本上能够用于类里面只含有简单数据的类,例如类是Date,int,double,String等数据库里面包含的类型。
这个并不是一个模板,而是一个工具类,也就是说,符合只有简单数据的类可以直接调用以下提供的功能就能操作数据库,返回类的List的值。
之前在进行编程的时候发现在操作数据库的过程中特别麻烦,每次重新写一个新类要存储到数据库的话,总是要在service写新的方法才能适应相应的操作,但是我觉得这些方法大都大同小异,似乎没有必要每次都为一个类写一个方法适应一个新的类。所以写这个通用数据库操作的类的想法就产生了。
首先,该工具主要是对数据库进行操作,所以首先要对数据库进行连接,下面是实现对数据库连接的一个DBUtil.java文件,实现了对数据库的连接
package com.hjf.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; /** * 数据库连接工具 * @author HDQ * */ public class DBUtil { public static String db_url = "jdbc:mysql://localhost:3306/数据库名"; public static String db_user = "数据库用户名"; public static String db_pass = "数据库密码"; public static Connection getConn () { Connection conn = null; try { Class.forName("com.mysql.jdbc.Driver");//加载驱动 conn = DriverManager.getConnection(db_url, db_user, db_pass); } catch (Exception e) { e.printStackTrace(); } return conn; } /** * 关闭连接 * @param state * @param conn */ public static void close (Statement state, Connection conn) { if (state != null) { try { state.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } public static void close (ResultSet rs, Statement state, Connection conn) { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (state != null) { try { state.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } public static void main(String[] args) throws SQLException { Connection conn = getConn(); PreparedStatement pstmt = null; ResultSet rs = null; String sql ="select * from course"; pstmt = conn.prepareStatement(sql); rs = pstmt.executeQuery(); if(rs.next()){ System.out.println("空"); }else{ System.out.println("不空"); } } }
然后在对数据库连接完成之后,接着就是对数据库进行操作的一个类了,这个类位于dao层
这个ClassDao.java类可以根据传递进来的参数返回相应类型的类的List,其实现的原理是利用Field 反射其值到对应的类里面,所以在使用的时候带有返回List的功能的时候,其数据库里面的数据项名称和类里面定义的变量的名称需要保持一致,才能保证其值被正确反射到类里面,反射机制所以返回的类的List都已经被赋予相应的值,可以直接被使用
相应的操作方法用法会在本文的最后给出,ClassDao.java是一个通用操作类,实现了对数据库操作
package com.hjf.dao; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List; import com.hjf.util.DBUtil; /** * 通用类Dao * Dao层操作数据 * @author HDQ * */ public class ClassDao { /** * 添加 * @return */ public <T> boolean add(String table,String []strList,String []strList1) { if(strList.length==0) return false; String sql = "insert into "+table+"("; for(int i=0;i<strList.length;i++) { if(i!=strList.length-1) sql+=strList[i]+","; else sql+=strList[i]+")"; } sql+=" values('"; for(int i=0;i<strList1.length;i++) { if(i!=strList1.length-1) sql+=strList1[i]+"','"; else sql+=strList1[i]+"')"; } //创建数据库链接 Connection conn = DBUtil.getConn(); Statement state = null; boolean f = false; int a = 0; try { state = conn.createStatement(); a=state.executeUpdate(sql); } catch (Exception e) { e.printStackTrace(); } finally { //关闭连接 DBUtil.close(state, conn); } if (a > 0) { f = true; } return f; } /** * 删除 * * @return */ public boolean delete (String table,String zhixing,String biaoshi) { boolean f = false; String sql = "delete from "+table+" where "+zhixing+"='" + biaoshi + "'"; Connection conn = DBUtil.getConn(); Statement state = null; int a = 0; try { state = conn.createStatement(); a = state.executeUpdate(sql); } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(state, conn); } if (a > 0) { f = true; } return f; } /** * 修改*/ public boolean update(String table,String []strlist,String []strlist1,String qian,String hou) { String sql = "update "+table+" set "; for(int i=0;i<strlist.length;i++) { if(i!=strlist.length-1) sql+=strlist[i]+"='" + strlist1[i] + "',"; else sql+=strlist[i]+"='" + strlist1[i] + "' where "+qian+"='" + hou + "'"; } Connection conn = DBUtil.getConn(); Statement state = null; boolean f = false; int a = 0; try { state = conn.createStatement(); a = state.executeUpdate(sql); } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(state, conn); } if (a > 0) { f = true; } return f; } /** * 验证通用类名称是否唯一 * true --- 不唯一 * @return */ public boolean name(String table,String zhi,String weiyi) { boolean flag = false; String sql = "select "+zhi+" from "+table+" where "+zhi+" = '" + weiyi + "'"; Connection conn = DBUtil.getConn(); Statement state = null; ResultSet rs = null; try { state = conn.createStatement(); rs = state.executeQuery(sql); while (rs.next()) { flag = true; } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(rs, state, conn); } return flag; } /** * 查找 * @return * @throws IllegalAccessException * @throws InstantiationException */ @SuppressWarnings("deprecation") public <T> List<T> search(String table,String []strList,String []strList1,Class<T> clazz) throws InstantiationException, IllegalAccessException { String sql = "select * from "+table; int i=0,k=0; for(String it:strList1) { if(it!=null&&!it.equals("")) { if(k==0) sql +=" where "+ strList[i]+" like '%" + it + "%'"; else sql +=" and "+ strList[i]+" like '%" + it + "%'"; ++k; } ++i; } List<T> list = new ArrayList<>(); Connection conn = DBUtil.getConn(); Statement state = null; ResultSet rs = null; try { state = conn.createStatement(); rs = state.executeQuery(sql); T bean = null; while (rs.next()) { bean=clazz.newInstance(); for(String it:strList) { Field fs=getDeclaredField(bean, it); if(fs==null){ throw new IllegalArgumentException("Could not find field["+ it+"] on target ["+bean+"]"); } makeAccessiable(fs); try{ fs.set(bean, rs.getObject(it)); } catch(IllegalAccessException e){ System.out.println("不可能抛出的异常"); } } list.add(bean); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(rs, state, conn); } return list; } /** * 由时间和条件查找 * @return * @throws IllegalAccessException * @throws InstantiationException */ @SuppressWarnings("deprecation") public <T> List<T> searchByTime(String table,String []strList,String []strList1,String biaoshi,String qian,String hou,Class<T> clazz) throws InstantiationException, IllegalAccessException { String sql = "select * from "+table+" where "; int i=0,k=0; for(String it:strList1) { if(it!=null&&!it.equals("")) { sql += strList[i]+" like '%" + it + "%'"; ++k; } ++i; } if(qian!=null&&!qian.equals("")) { if(k>0) sql+=" and "+biaoshi+" Between '"+qian+"' AND '"+hou+"'"; else sql+=biaoshi+" Between '"+qian+"' AND '"+hou+"'"; } //and shijian Between '"+request.getParameter("shijian1")+"' AND '"+request.getParameter("shijian2")+"'" //查询的时间格式例如:2015-10-27 24:00:0(假如为DateTime的话,Date只需要年-月-日) List<T> list = new ArrayList<>(); Connection conn = DBUtil.getConn(); Statement state = null; ResultSet rs = null; try { state = conn.createStatement(); rs = state.executeQuery(sql); T bean = null; while (rs.next()) { bean=clazz.newInstance(); for(String it:strList) { Field fs=getDeclaredField(bean, it); if(fs==null){ throw new IllegalArgumentException("Could not find field["+ it+"] on target ["+bean+"]"); } makeAccessiable(fs); try{ fs.set(bean, rs.getObject(it)); } catch(IllegalAccessException e){ System.out.println("不可能抛出的异常"); } } list.add(bean); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(rs, state, conn); } return list; } /** * 创建数据库 * @return * @throws ClassNotFoundException * @throws IllegalAccessException * @throws InstantiationException */ public boolean createTable(String table,String []info,String []type,int []size) { String sql = "CREATE TABLE "+table+"("; String lei[]=new String[] {"char","varchar"}; int i=0; for(String it:info) { if(!it.equals("")) { boolean g_trit=false; for(String sit:lei) { if(type[i].toLowerCase().contains(sit.toLowerCase())) { g_trit=true; } } if(g_trit) sql += it+" "+type[i]+"("+size[i]+")"; else sql += it+" "+type[i]; } if(i!=info.length-1) sql+=","; ++i; } sql+=")"; //and shijian Between '"+request.getParameter("shijian1")+"' AND '"+request.getParameter("shijian2")+"'" //查询的时间格式例如:2015-10-27 24:00:0 Connection conn = DBUtil.getConn(); Statement state = null; ResultSet rs = null; int a=0; boolean f=false; try { state = conn.createStatement(); a = state.executeUpdate(sql); } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(rs, state, conn); } if(a>0) f=true; return f; } /** * 全部数据 * @return * @throws ClassNotFoundException * @throws IllegalAccessException * @throws InstantiationException */ @SuppressWarnings("deprecation") public <T> List<T> list(String table,String []strList,Class<T> clazz) throws ClassNotFoundException, InstantiationException, IllegalAccessException { String sql = "select * from "+table; List<T> list = new ArrayList<>(); Connection conn = DBUtil.getConn(); Statement state = null; ResultSet rs = null; try { state = conn.createStatement(); rs = state.executeQuery(sql); T bean = null; while (rs.next()) { bean=clazz.newInstance(); for(String it:strList) { Field fs=getDeclaredField(bean, it); if(fs==null){ throw new IllegalArgumentException("Could not find field["+ it+"] on target ["+bean+"]"); } makeAccessiable(fs); try{ fs.set(bean, rs.getObject(it)); } catch(IllegalAccessException e){ System.out.println("不可能抛出的异常"); } } list.add(bean); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(rs, state, conn); } return list; } //获取field属性,属性有可能在父类中继承 public static Field getDeclaredField(Object obj,String fieldName){ for (Class<?> clazz=obj.getClass(); clazz!=Object.class; clazz=clazz.getSuperclass()){ try{ return clazz.getDeclaredField(fieldName); } catch(Exception e){ } } return null; } //判断field的修饰符是否是public,并据此改变field的访问权限 public static void makeAccessiable(Field field){ if(!Modifier.isPublic(field.getModifiers())){ field.setAccessible(true); } } }
在dao层里面的方法应该是为了安全性考虑吧,还要有一个sevice类来调用dao层里面的方法,就相当一个中介一样吧,也就是一个提供dao层里面接口的一个类,以下是位于service层的service.java,实现dao层方法的接口
package com.hjf.service; import java.util.List; import com.hjf.dao.ClassDao; /** * CourseService * 服务层 * @author HDQ * */ public class ClassService { ClassDao cDao = new ClassDao(); /** * 添加 * @param course * @return */ public boolean add(String table,String strList[],String strList1[]) { boolean f = cDao.add(table,strList,strList1); return f; } /** * 删除 */ public boolean del(String table,String qian,String hou) { return cDao.delete(table,qian,hou); } /** * 修改 * @return */ public boolean update(String table,String []strlist,String []strlist1,String qian,String hou) { return cDao.update(table,strlist,strlist1,qian,hou); } /** * 查找 * @return * @throws IllegalAccessException * @throws InstantiationException */ public <T> List<T> search(String table, String []strList, String []strList1,Class<T> clazz) throws InstantiationException, IllegalAccessException { return cDao.search(table,strList,strList1,clazz); } /** * 由时间查找 * @return * @throws IllegalAccessException * @throws InstantiationException */ public <T> List<T> searchByTime(String table, String []strList, String []strList1,String biaoshi,String qian,String hou,Class<T> clazz) throws InstantiationException, IllegalAccessException { return cDao.searchByTime(table, strList, strList1, biaoshi, qian, hou, clazz); } /** * 全部数据 * @return * @throws IllegalAccessException * @throws InstantiationException * @throws ClassNotFoundException */ public <T> List<T> list(String table,String []strList,Class<T> clazz) throws ClassNotFoundException, InstantiationException, IllegalAccessException { return cDao.list(table,strList,clazz); } /** * 创建数据库表单 * @return * @throws IllegalAccessException * @throws InstantiationException */ public boolean createTable(String table,String []info,String []type,int []size) { return cDao.createTable(table, info, type, size); } }
其3个类组成的工具类就如上面所示。
就以一个查找功能为例子,我现在Entity层中有3个类用到了这个通用类,假如现在想再定义一个新类调用这个通用数据库的函数,实现对数据库对这个类的数据的增删改查功能,以下就以一个具体的例子来展示如何调用这个通用类的函数
然后下面介绍这个通用类的用法:
首先假如现在有一个类,位于entity层,假如是一个老师类,Teacher
然后在entity层中定义一个Teacher类,其中含有int类型的编号id,String类型的名字name,还有Date类型的出生日期birth,(定义的类的多少不受限制),并定义getter和setter的方法
定义完这个类之后,数据库里面对应的项的名称要和类的名称一致,这样才能被正确反射
所以在数据库里面新建一个teacherlist的表,对应的项的名称设置为int类型的id,char或者text类型的name,Date类型的birth
名字分别都与Teacher类里面的名称相对应
虽然该工具类里面有提供表创建的函数,但是为了方便读者理解,这里用数据库管理软件的创建过程来展示
创建完成之后,要实现往这个数据库的teacherlist里面添加数据的功能的话,我们查看一下service层提供的接口
这个是ClassServlet里面的前缀,ClassService就是数据库通用工具的接口类,可以通过调用这个service里面的函数实现数据的操作
//--------------添加数据功能--------------
提供的方法是add(table,strList[],strList1[]),返回的类型是boolean类型,表示成功与否
第一个参数是table表名,第二个参数strList是需要添加的项的名称字符串组,第三个参数strList1是对应要需要添加项的内容
例如执行
String []strList=new String[] {"id","name","birth"};
String []strList1=new String[] {"11","王老师",“2001-09-22”};
service.add("teacherlist",strList,strList1);
就会将数据库中teacherlist表里面对应的id,name,birth项添加上11,王老师,2001-09-22的信息
值得注意的是,strLis[]里面的字符串要对应和类中的变量名称相等,而且数据库中的名称也是,这样才能正确的反射,当然,添加的过程并没有用到反射,但是规范化而言,用到list等功能的时候就可以直接使用了。
当出现数据添加失败的时候,add函数会返回一个false,执行成功时则是true
//--------------获取列表信息功能--------------
首先上述是teacherlist数据库表的信息,现在如果我们想把所有信息获取到一个List<Teacher>里面,可以调用service提供的
获取全部数据的方法
list(table,strlist[],Class);
其中参数table是要获取数据的表格名称,strList[]填写的是要获取数据库中的哪个项的名称所对应的信息,Class是需要返回的List<>数组的类型,不过这个返回的类型一般还得强制转换一下
以获取上述的数据到一个List<Teacher>里面为例子,调用的函数如下所示:
String []strList=new String[]{"id","name","birth"};
@SuppressWarnings("unchecked")
List<Teacher> teachers= (List<Teacher>) service.list("teacherlist",strList,new Teacher().getClass());
此时teachers变量里面就储存了你想要的数据了。然后,如果想要获取的数据项没有birth这个的话,在strList中填写对应想要获取的数据项就可以了,String []strList=new String[]{"id","name"};再执行获取的函数,这个时候获取的teachers里面的birth就没有储存数据了
然后这里拓展一点小知识,获取的list可以存储到attribute里面后直接在网页上输出,当然要利用到jstl.jar和standard.jar这两个包
这里调用tlist这个函数的时候,将会跳转到teacherlist这个网页
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <% Object message = request.getAttribute("message"); if(message!=null && !"".equals(message)){ %> <script type="text/javascript"> alert("<%=request.getAttribute("message")%>"); </script> <%} %> <div align="center"> <h1 style="color: black;">老师信息列表</h1> <a href="index.jsp">返回主页</a> <table class="tb"> <tr> <td>编号id</td> <td>名字</td> <td>出生日期</td> </tr> <c:forEach items="${teachers}" var="item"> <tr> <td>${item.id}</td> <td>${item.name}</td> <td>${item.birth}</td> </tr> </c:forEach> </table> </div> </body> </html>
然后调用tlist这个函数之后的界面如下所示。
//--------------删除信息项功能--------------
下面举一个简单的删除其中一条信息的功能
service中提供了del这个删除数据项的函数,返回的是boolean类型表示删除成功与否
用法也很简单,参数table表示的是需要删除信息的数据库表,参数qian表示的是需要删除的数据项的名称(主键),参数hou表示的数据项对应的数据
实现的功能就是将数据库的table表将其中一个叫qian等于hou的这行数据删除了,例如执行
service.del("teacherlist", "id","11");
这样就删除了编号id为11的老师的信息了
//--------------模糊搜索功能--------------
service中提供了search这个搜索数据项的函数,返回的依旧是List<>的值
参数table表示的是数据库名,参数strList[]表示的是需要模糊匹配的及获取数据名字符串组,strList1[]表示的是对于strList[]模糊匹配的值,strList1的值个数可以少于strList,最后参数clazz表示的是要返回数据的list的类型,同样需要强制转换一下,因为是泛型
例如要获取老师中名字中含有老师,并且编号中含有1的所有老师的编号 姓名 出生日月可以这么写
String []strList=new String[]{"id","name","birth"};
String []strList1=new String[]{"1","老师"};
@SuppressWarnings("unchecked")
List<Teacher> teachers= (List<Teacher>) service.search("teacherlist",strList,strList1,new Teacher().getClass());
这样变量teachers中就获取了模糊搜索后的所有信息了
//--------------根据时间搜索及其关键字的高级模糊搜索功能--------------
service中提供了searchByTime这个根据时间搜索及其关键字的模糊搜索数据项的函数,算是比较高级的搜索功能,但是用法相对模糊搜索来说比较复杂
前面3个参数的用法和----模糊搜索功能----的用法一致,然后主要的区别就是后面的,biaoshi,qian,hou这3个参数
首先biaoshi是数据库中存储时间的项和类中存储时间的变量的名称,这个变量的类型可以是Date或者DateTime的,不过Date和DateTime的查格式有区别,具体可以看网上。
参数qian表示的是要搜索的开始时间,参数hou表示的是搜索的结束时间
以要获取出生日期为2000-10-22到2002-10-01的名字中含有老师的老师的名字name,编号id为例子
所要执行的函数如下:
String []strList=new String[]{"name","id"}; //获取的数据有name,id这两个,birth不做获取
String []strList1=new String[]{"老师"}; //这样的话name就模糊匹配了老师了,id因为没有参数对应,所以id不做匹配
@SuppressWarnings("unchecked")
List<Teacher> teachers= (List<Teacher>) service.searchByTime("teacherlist",strList,strList1,"birth","2000-10-22","2002-10-01",new Teacher().getClass());
这样teachers中就存储了所要的匹配的所有信息了。
//--------------修改(更新)数据功能--------------
service中提供了update更新数据的功能,其中返回的值是boolean值,表示成功与否
参数table表示要修改数据的数据表的名称,参数strlist[]表示分别要修改那些数据,strlist1[]表示这些数据分别修改成什么,qian表示的是关键字项(主键),hou表示的是qian对应的信息是什么的时候修改
例如要将存储在teacherlist表中编号为11的王老师的生日修改成2000-10-23日的话,那么所要执行的语句如下:
String strlist[]=new String[] {"birth"}; //需要修改的项的名称
String strlist1[]=new String[] {"2000-10-23"}; //对应的项的信息要修改成什么
service.update("teacherlist",strlist,strlist1,"id","11");
这样就实现了我们想要的功能了
//-------------------------------------------------------------
该数据库操作类中还提供了一些创建数据库的函数,这里就不再说明了,因为创建数据库的操作一般在实际的过程中都较少用到
该工具类的介绍大概就是这样,我想这个数据库操作的java工具应该可以在平时的操作中,方便我们对mysql数据库的管理。