util工具类
package com.ishangu.util; import java.lang.reflect.Field; import java.security.spec.ECField; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; /** * 数据库基本工具类 * */ public class DBUtil { /** * 将基本数据库信息封装成常量 */ private static final String URL="jdbc:mysql:///"; private static final String DB_NAME="aaa"; private static final String USERNAME="root"; private static final String PASSWORD="123456"; /** * JDBC常用对象 */ private static Connection con; private static PreparedStatement ps; private static ResultSet rs; /** * 私有化工具类的构造方法,不让别人new对象 */ private DBUtil(){ } /** * 1.获取数据库连接 */ private static Connection getConnection(){ try{ con=DriverManager.getConnection(URL+DB_NAME, USERNAME, PASSWORD); }catch(Exception e){ e.printStackTrace(); } return con; } /** * 2.获取预编译对象 */ public static PreparedStatement getPS(String sql){ getConnection(); try { ps=con.prepareStatement(sql); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return ps; } /** * 3.编写关闭连接的方法 */ public static void close(Connection con){ if(con!=null){ try { con.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * 4.关闭预编译对象 */ public static void close(Connection con,PreparedStatement ps){ if(ps!=null){ try { ps.close(); close(con); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * 5.编写关闭结果集对象的方法 */ public static void close(Connection con,PreparedStatement ps,ResultSet rs){ if(rs!=null){ try { rs.close(); close(con,ps); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * 6.通用的DML 参数1.需要执行的sql语句 * 参数2.是sql中占位符需要的值 * */ public static void dml(String sql,Object...objects){ getPS(sql);//预编译对象已经有了。 try { //通过for循环,将所有参数放入到sql的占位符之内 for(int i=0;i<objects.length;i++){ ps.setObject(i+1, objects[i]); } ps.execute();//执行sql语句 } catch (Exception e) { e.printStackTrace(); }finally { close(con,ps); } } /** * 7.通用的DQL:最大难题:查询不同的表,需要返回不同的model类对象,此时我门可以在形参中传入查询的model类型,没然后根据反射创建对象,完成结果集的封装 */ public static <E> E dqlOne(String sql,Class<E> c,Object...objects){ getPS(sql); E e=null; try { for (int i = 0; i < objects.length; i++) { ps.setObject(i+1, objects[i]); } rs=ps.executeQuery(); //首先获取结果集中所有列的集合 ResultSetMetaData data = rs.getMetaData(); //然后获取列的数量 int count = data.getColumnCount(); //根据列的数量创建一个字符串数组 String[] str =new String[count]; //将所有列明后才能存入到字符串数组之中 for (int i = 0; i < str.length; i++) { str[i]=data.getColumnLabel(i+1); } String[] fields=method(str); //开始遍历结果集 if(c.getName().equals("Integer")||c.getName().equals("int")){ //需要返回的是一个单纯的整数,也证明sql是求总数的sql。 rs.next(); return (E) new Integer(rs.getInt(1)); } while (rs.next()) { //获取当前列数 if(rs.getRow()>1){ throw new Exception("查出多条数据"); } //通过反射将e实例化为实力对象 e=c.newInstance(); //通过循环给e对象的属性赋值 for(int i=0;i<str.length;i++){ //使用列名称通过反射对象,获取对象的属性 Field field = c.getDeclaredField(fields[i]); //公开访问权限 field.setAccessible(true); //给属性设置值 field.set(e, rs.getObject(str[i])); } } } catch (Exception ex) { ex.printStackTrace(); }finally { close(con,ps,rs); } return e; } /** * 将数据库列名称转化为Java的属性名,并返回对应的数组 */ public static String[] method(String[] str){ //创建一个数组用来保存model中的属性名长度与数据库列的数组长度一致 String[] fields =new String [str.length]; for (int i = 0; i < fields.length; i++) { if(str[i].indexOf("_")!=-1){//进入if代表列名中包含有下划线 //由于列名中可能不止一个下划线,所以做了如下处理 String[] split=str[i].split("_"); StringBuffer sb=new StringBuffer(); //遍历根据_分割出来的数组 for (int j = 0; j < split.length; j++) { if(j==0){ sb.append(split[j]); }else{ char[] charArray = split[j].toCharArray();//将字符串转换成char数组 charArray[0]-=32;//数组中的第一个元素进行大写转换。 sb.append(charArray); } } //将StringBuffer转换成字符串,然后存入到字符串数组中 fields[i]=sb.toString(); }else{ fields[i]=str[i]; } } return fields; } /** * 8.通用的DQL:最大难题:查询不同的表,需要返回不同的model类对象,此时我门可以在形参中传入查询的model类型,没然后根据反射创建对象,完成结果集的封装 * 查询多个 */ public static <E> List<E> dqlList(String sql,Class<E> c,Object...objects){ getPS(sql); List<E> list=new ArrayList<>(); try { for (int i = 0; i < objects.length; i++) { ps.setObject(i+1, objects[i]); } rs=ps.executeQuery(); //首先获取结果集中所有列的集合 ResultSetMetaData data = rs.getMetaData(); //然后获取列的数量 int count = data.getColumnCount(); //根据列的数量创建一个字符串数组 String[] str =new String[count]; //将所有列明后才能存入到字符串数组之中 for (int i = 0; i < str.length; i++) { str[i]=data.getColumnLabel(i+1); } String[] fields=method(str); //开始遍历结果集 while (rs.next()) { //通过反射将e实例化为实力对象 E e=c.newInstance(); //通过循环给e对象的属性赋值 for(int i=0;i<str.length;i++){ //使用列名称通过反射对象,获取对象的属性 Field field = c.getDeclaredField(fields[i]); //公开访问权限 field.setAccessible(true); //给属性设置值 field.set(e, rs.getObject(str[i])); } list.add(e); } } catch (Exception ex) { ex.printStackTrace(); }finally { close(con,ps,rs); } return list; } public static <E> void dml(String sql,E e){ getPS(sql); Class<? extends Object> class1 = e.getClass(); if(class1.getName().equals("int")||class1.getName().equals("Integer")||class1.getSimpleName().equals("String")){ try { ps.setObject(1, e); ps.execute(); } catch (SQLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); }finally { close(con,ps); } }else{ try { Field[] fields = class1.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { fields[i].setAccessible(true); ps.setObject(i+1, fields[i].get(e)); } ps.execute(); }catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); }finally { close(con,ps); } } } /** * 1.通用的增加,要求有多少个占位符,传入的model中需要有多少个属性有值 * 2.model属性的书写规范顺序要与数据库列名的顺序一致,书写sql要规范 * 由于传入的model是任何类型,所以要用到泛型 */ public static <E> void saveModel(String sql,E e){ getPS(sql); try { Class<? extends Object> class1 = e.getClass(); Field[] fields = class1.getDeclaredFields(); int j=1; for (int i = 0; i < fields.length; i++) { fields[i].setAccessible(true); if(fields[i].get(e)!=null){ ps.setObject(j++, fields[i].get(e)); } } ps.execute(); } catch (Exception e2) { e2.printStackTrace(); }finally { close(con,ps); } } public static <E> void updateModel(String sql,E e){ getPS(sql); try { Class<? extends Object> class1 = e.getClass(); Field[] fields = class1.getDeclaredFields(); int j=1; for (int i = 1; i < fields.length; i++) { fields[i].setAccessible(true); if(fields[i].get(e)!=null){ ps.setObject(j++, fields[i].get(e)); } } fields[0].setAccessible(true); ps.setObject(j,fields[0].get(e)); ps.execute(); } catch (Exception e2) { e2.printStackTrace(); }finally { close(con,ps); } } /** * 通用分页查询,使用这个方法,会返回分页的数据 */ public static <E> PageInfo<E> dqlListLimit(String sql,Class<E> e,Object...objects){ //1.将传入的sql语句转化为求总数的sql StringBuffer sb=new StringBuffer("select count(*)"); sb.append(sql.substring(sql.indexOf("from"))); //2.去除limit之后的sql sb.replace(sb.indexOf("limit"), sb.length(), ""); //3.去除参数中的分页参数 Object[] of = Arrays.copyOf(objects, objects.length-2); Integer count = dqlOne(sb.toString(), int.class,of); //4.修改参数执行原来的sql int pageSize=(int) objects[objects.length-1]; int pageNumber= (int) objects[objects.length-2]; objects[objects.length-2]=(pageNumber-1)*pageSize; List<E> data = dqlList(sql, e, objects); PageInfo<E> pageInfo=new PageInfo<>(data,count,pageSize,pageNumber); return pageInfo; } package com.ishangu.util; import java.util.List; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.ToString; import lombok.Value;
分页查询
package com.ishangu.util; import java.util.List; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.ToString; import lombok.Value; /** * 主要记录跟分页有关的数据 * 1.数据 * 2.记录总条数 * 3.每页显示多少条数据 * 4.当前页码 * 5.首页 * 6.尾页 * 7.上一页 * 8.下一页 */ //@Setter //@Getter //@ToString //@EqualsAndHashCode @Data //以上所有 @NoArgsConstructor //无参构造 @AllArgsConstructor //有参构造 //@RequiredArgsConstructor //指定构造 //@Value //类被static final修饰 public class PageInfo<E> { /** * 存放数据 */ //@NonNull //指定生成在构造器中 private List<E> data; public PageInfo(List<E> data, int count, int pageSize, int pageNumber) { super(); this.data = data; //数据 this.count = count; //总数 this.pageSize = pageSize; //每页显示多少数据 this.pageNumber = pageNumber; //当前页码 this.countPage=count%pageSize==0 ? count/pageSize : (count/pageSize)+1;//求总共有几页 this.startPage=1; this.endPage=countPage; this.upPage=pageNumber==1?false:true; //第一也没有上一页 this.nextPage=pageNumber==countPage?false:true; //pageNumber==countPage 表示已经是最后一页了,所以没有下一页了 } /** * 记录总条数 */ private int count;//总记录数 /** * 每页显示多少条数据 */ private int pageSize; /** * 当前页码 */ private int pageNumber; /** * 总共有多少页 */ private int countPage; /** * 首页 */ private int startPage; /** * 尾页 */ private int endPage; /** * 上一页 */ private boolean upPage; /** * 下一页 */ private boolean nextPage; }