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;
}