0
点赞
收藏
分享

微信扫一扫

jdbc篇第8课:进一步封装jdbc

最不爱吃鱼 2022-03-12 阅读 96


  这节课我们来进一步封装jdbc


  首先来分析下,jdbc的使用:

jdbc使用:

     1. 建立好表对应的类(我们称为bean),要求每一列对应一个属性,且数据类型对应上

     2. 建立连接,获取Connection对象

     3. 使用Connection对象获取Statement或PreparedStatement对象

     4. 写好sql

     5. 使用Statement或PreparedStatement执行查询语句,如果是select语句,获取ResultSet对象,并执行6和7

     6. 建一个或多个bean对象

     7. 获取ResultSet里存储的值,并封装到bean对象中

     8. 关闭连接


第1步的封装以后讲,这个可以算是另一个小项目了

第2、3步我们已经封装好了,就是dbc


接下来就是封装4、5、6、7


代码:

package com.tool;



import com.bean.Employee;

import com.util.ClassUtil;

import com.util.ObjectUtil;

import com.util.StringUtil;



import java.io.IOException;

import java.lang.reflect.Field;

import java.lang.reflect.InvocationTargetException;

import java.sql.*;

import java.util.ArrayList;

import java.util.List;

import java.util.Map;



/**

*

* @param <E> bean的类型

* 一个bean对应一个表,且bean的类名用驼峰式命名,表的命名用下划线全小写命名

* 这个类是一个抽象类,必须有子类继承并且给定E的类型

*/

public abstract class Mapper<E> {



private Connection connection;



public Mapper(Connection connection)

{

this.connection = connection;

}



public Mapper(String dbcPropertiesPath) throws SQLException, IOException, ClassNotFoundException {

this.connection = Dbc.getConnection(dbcPropertiesPath);

}



/**

* 将value转换成合适的类型插入到合适的位置

*/

private void castToSuitType(PreparedStatement preparedStatement,int index, Object value) throws SQLException {

Class<?> valueClass = value.getClass();



if (valueClass == String.class)

{

preparedStatement.setString(index, String.valueOf(value));

}

else if(valueClass == Integer.class || valueClass == int.class)

{

preparedStatement.setInt(index,(Integer)value);

}

else if (valueClass == Float.class || valueClass == float.class)

{

preparedStatement.setFloat(index,(Float) value);

}

else if (valueClass == Double.class || valueClass == double.class)

{

preparedStatement.setDouble(index,(Double) value);

}

else if (valueClass == Short.class || valueClass == short.class)

{

preparedStatement.setShort(index,(Short)value);

}

else

{

preparedStatement.setString(index, String.valueOf(value));

}

}



private <T> T castToSuitType(ResultSet resultSet,int index, Class<T> fieldClass) throws SQLException

{

Object value;

if (fieldClass == String.class)

{

value = resultSet.getString(index);

}

else if(fieldClass == Integer.class || fieldClass == int.class)

{

value = resultSet.getInt(index);

}

else if (fieldClass == Float.class || fieldClass == float.class)

{

value = resultSet.getFloat(index);

}

else if (fieldClass == Double.class || fieldClass == double.class)

{

value = resultSet.getDouble(index);

}

else if (fieldClass == Short.class || fieldClass == short.class)

{

value = resultSet.getShort(index);

}

else

{

value = resultSet.getString(index);

}

return (T)value;

}



/**

* 首先,我们要获取所有的类列

* 每一列对应bean的类的一个属性

* 列名用全小写下划线式

* 属性名用首字母小写的驼峰式

*

* 接下来我们需要几个一个工具类来处理字符串

* 当然,要用的工具类我都提前写好了

*/



/**

* 获取泛型E的Class对象,即bean的类型的Class对象

* @return

*/

public Class<E> getBeanClass()

{

return ClassUtil.getSuperClassGenricType(this.getClass());

}



/**

* 获取表名

* @param

*/

public String getTableName()

{

Class<E> beanClass = getBeanClass();

String className = beanClass.getName();

className = className.substring(className.lastIndexOf(".") +1);

String tableName = StringUtil.castCamelCaseToUnderline(className);



//保险起见首字母转下小写

tableName = StringUtil.firstLetterToLowerCase(tableName);

return tableName;

}



/**

* 获取列名

* @return

*/

public List<String> getColumnNames()

{

Class<E> beanClass = getBeanClass();

Field[] fields = beanClass.getDeclaredFields();

List<String> columnNames = new ArrayList<String>(fields.length);

for (Field field : fields) {

String columnName = StringUtil.castCamelCaseToUnderline(field.getName());

//保险起见首字母转下小写

columnName = StringUtil.firstLetterToLowerCase(columnName);

columnNames.add(columnName);

}

return columnNames;

}





//接下来封装增删改查操作

public void insert(E e) throws SQLException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {

//String sql = "insert into tbl_employee (id,last_name,email,gender,d_id) values (?,?,?,?,?)";

String sql = "insert into ";

sql += getTableName() + " (";

List<String> columnNames = getColumnNames();

for (String columnName : columnNames) {

sql += columnName + ",";

}



//删除最后一个逗号

sql = StringUtil.deleteLastChildString(sql,1);

sql += ") values (";



//说了含金量高的,索性写复杂点

List<Object> valueList = ObjectUtil.getAllFieldValue(e);

for (Object value : valueList) {

//用?当占位符

sql += "?,";

}

//删除最后一个逗号

sql = StringUtil.deleteLastChildString(sql,1);

sql += ");";





PreparedStatement preparedStatement = connection.prepareStatement(sql);

for (int i = 0; i < valueList.size(); i++) {

//这个也是从1开始

castToSuitType(preparedStatement,i + 1,valueList.get(i));

}

preparedStatement.executeUpdate();

//总算把insert写完了,后面的都差不多,我快点写,就不写注释了

}



public void delete(int id) throws SQLException {

//String sql = "delete from tbl_employee where id = ?";

String sql = "delete from ";

sql += getTableName() + " ";

sql += "where ";

Class<E> beanClass = getBeanClass();



//注意,在写bean类的时候必须将主键写在最前面,否则,这个代码要写的更加复杂,因为涉及到注解

String primaryKeyName = beanClass.getDeclaredFields()[0].getName();

sql += primaryKeyName + "= ?;";



PreparedStatement preparedStatement = connection.prepareStatement(sql);

preparedStatement.setInt(1,id);

preparedStatement.executeUpdate();

}



public void update(E e) throws SQLException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {

//String sql = "update tbl_employee set last_name = ?,email = ?,gender = ?, d_id = ? where id = ?";

String sql = "update " + getTableName() + " set ";

List<String> columnNames = getColumnNames();

String primaryKeyName = columnNames.remove(0);

for (String columnName : columnNames) {

sql += columnName + "=?,";

}

sql = StringUtil.deleteLastChildString(sql,1);



sql += " where " + primaryKeyName + "=?";



PreparedStatement preparedStatement = connection.prepareStatement(sql);

List<Object> valueList = ObjectUtil.getAllFieldValue(e);

Object primaryKeyValue = valueList.remove(0);

//主键被挪到了最后,在where那里

valueList.add(primaryKeyValue);

for (int i = 0; i < valueList.size(); i++) {

castToSuitType(preparedStatement,i + 1,valueList.get(i));

}

preparedStatement.executeUpdate();

}



public E selectByPrimaryKey(Object primaryKey) throws SQLException, IllegalAccessException, InstantiationException, NoSuchMethodException, NoSuchFieldException, InvocationTargetException {

Class<E> beanClass = getBeanClass();

//以前说过,java bean必须有空构造函数,其实就是为了方便通过反射构造对象

E e = null;



//String sql = "select * from tbl_employee where id = ?";

String sql = "select ";

List<String> columnNames = getColumnNames();

for (String columnName : columnNames) {

sql += columnName + ",";

}

sql = StringUtil.deleteLastChildString(sql,1);

sql += " from " + getTableName() + " where ";



//获取主键名称

String primaryKeyName = beanClass.getDeclaredFields()[0].getName();

sql += primaryKeyName + "= ?;";



PreparedStatement preparedStatement = connection.prepareStatement(sql);

castToSuitType(preparedStatement,1,primaryKey);

ResultSet resultSet = preparedStatement.executeQuery();

if (resultSet.next())

{

//查得到数据才new,否则返回null

e = getBeanFromResultSet(resultSet, beanClass);

}



return e;

}



/**

*

* @param conditionMap 键是列名,值是要匹配的值

* @return

*/

public List<E> selectByExample(Map<String,Object> conditionMap) throws SQLException, IllegalAccessException, InstantiationException, NoSuchMethodException, NoSuchFieldException, InvocationTargetException {

List<E> resultList = new ArrayList<E>();

int size = conditionMap.keySet().size();

String[] keyArr = new String[size];

Object[] valueArr = conditionMap.values().toArray();

conditionMap.keySet().toArray(keyArr);



//String sql = "select * from tbl_employee where ";

String sql = "select ";

List<String> columnNames = getColumnNames();

for (String columnName : columnNames) {

sql += columnName + ",";

}

sql = StringUtil.deleteLastChildString(sql,1);

sql += " from " + getTableName() + " where ";



for (int i = 0; i < size; i++) {

sql += keyArr[i] + "=? and "; //and前后要加空格

}

//末尾多了一个and,去掉

sql = sql.substring(0,sql.lastIndexOf("and") - 1);



PreparedStatement preparedStatement = connection.prepareStatement(sql);

for (int i = 0; i < valueArr.length; i++) {

castToSuitType(preparedStatement,i + 1,valueArr[i]);

}

ResultSet resultSet = preparedStatement.executeQuery();



Class<E> beanClass = getBeanClass();

while (resultSet.next())

{

E e = getBeanFromResultSet(resultSet, beanClass);

resultList.add(e);

}

return resultList;

}



//提取点公共代码



public E getBeanFromResultSet(ResultSet resultSet,Class<E> beanClass) throws IllegalAccessException, InstantiationException, SQLException, NoSuchMethodException, NoSuchFieldException, InvocationTargetException {

E e = beanClass.newInstance();

Field[] fields = beanClass.getDeclaredFields();

for (int i = 0; i < fields.length; i++) {

//列数从1开始

Object value = castToSuitType(resultSet, i + 1, fields[i].getType());

ObjectUtil.setFieldValue(e,fields[i],value);

}

return e;

}

}


使用:

public class EmployeeMapper extends Mapper<Employee> {





public EmployeeMapper(Connection connection) {

super(connection);

}



public EmployeeMapper(String dbcPropertiesPath) throws SQLException, IOException, ClassNotFoundException {

super(dbcPropertiesPath);

}

}


测试:

public static void main(String[] args) throws Exception {



//测一下,我也不确定我能不能一次写对

EmployeeMapper mapper = new EmployeeMapper("src/com/resource/dbc.properties");



//通过

Employee employee = mapper.selectByPrimaryKey(3);

System.out.println(employee);



//通过

mapper.delete(100);



//通过

employee = new Employee(13,"mahuateng","mahuateng@qq.com","1",1004);

mapper.update(employee);



//通过

employee = new Employee(100,"xiaowang","xiaowang@163.com","0",1002);

mapper.insert(employee);



//通过

Map<String,Object > map = new HashMap<String, Object>();

map.put("gender","1");

map.put("d_id",1002);

List<Employee> employees = mapper.selectByExample(map);



for (Employee employee1 : employees) {

System.out.println(employee1);

}

}


工具类:

package com.util;



//字符串工具类

//这个工具类里的所有方法要求看懂并且可以自己写出来

//这个里的所有方法全是我自己手写出来的,要求你们也要可以手写出来

public class StringUtil {



/**

* 将字符串首字母转换成大写

*

* @param str 要转换的字符串

* @return 返回str首字母大写后的字符串

*/

public static String firstLetterToUpperCase(String str)

{

//这里只替换第一个

return str.replaceFirst(String.valueOf(str.charAt(0)),String.valueOf(str.charAt(0)).toUpperCase());

}



/**

* 将字符串首字母转换成小写

*

* @param str 要转换的字符串

* @return 返回str首字母瞎写写后的字符串

*/

public static String firstLetterToLowerCase(String str)

{

//这里只替换第一个

return str.replaceFirst(String.valueOf(str.charAt(0)),String.valueOf(str.charAt(0)).toLowerCase());

}



/**

* 驼峰转下划线

* 解释下什么叫驼峰式,就是每个单词的首字母大写,其余字母都小写

* java推荐所有变量、方法、类都使用驼峰式命名

* 类名一般第一个单词的首字母也要大写

* 变量、方法第一个单词的首字母小写

* 下划线式是指全字母小写或全字母大写,单词之间用下划线分割,如cast_camel_case_to_underline

* 常量采用全字母大写加下划线式

*/





/**

* 将驼峰式字符串转换成下划线式

*

* @param str 驼峰式字符串

* @return 下划线式字符串

*/

public static String castCamelCaseToUnderline(String str)

{

char[] chars = str.toCharArray();

String result = "";

for (char i : chars)

{

if (i >= 'A' && i <= 'Z')

{

result += "_" + String.valueOf(i).toLowerCase();

}

else

{

result += i;

}

}

if (result.startsWith("_"))

{

result = result.substring(1);

}

return result;

}



/**

* 将下划线字符串转换成驼峰式

*

* @param str 下划线式字符串

* @return 驼峰式字符串

*/

public static String castUnderlineToCamelCase(String str)

{

String[] split = str.split("_");

String result = "";

for (String s : split)

{

result += firstLetterToUpperCase(s);

}

return firstLetterToLowerCase(result);

}



/**

* 删除下划线最后length位字符

*

* @param str 要处理的字符串

* @param length 要删除字符串最后多少位字符

* @return 删除str字符串最后length位字符后的新字符串

*/

public static String deleteLastChildString(String str,int length)

{

return str.substring(0,str.length() - length);

}

}


package com.util;



import java.io.File;

import java.lang.reflect.Field;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import java.util.ArrayList;

import java.util.List;



public class ObjectUtil {



/**

* 获取object的属性值

* @param object 要获取属性值的镀锡

* @param fieldName 属性名

* @return object的filedName对应的属性值

*/

public static Object getFieldValue(Object object,String fieldName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

String getterMethodName = "get" + StringUtil.firstLetterToUpperCase(fieldName);



//只要public的getter方法

Method getterMethod = object.getClass().getMethod(getterMethodName);

if (getterMethod != null)

{

Object value = getterMethod.invoke(object);

return value;

}

return null;

}



/**

* 获取object的属性值

* @param object 要获取属性值的镀锡

* @param field 属性

* @return object的filed对应的属性值

*/

public static Object getFieldValue(Object object,Field field) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {

return getFieldValue(object,field.getName());

}



/**

* 获取object的所有属性值

* @param object 要获取属性值的镀锡

* @return object的所有属性值组成的List集合

*/

public static List<Object> getAllFieldValue(Object object) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {

Field[] declaredFields = object.getClass().getDeclaredFields();

List<Object> valueList = new ArrayList<Object>(declaredFields.length);

for (Field field : declaredFields) {

valueList.add(getFieldValue(object,field));

}

return valueList;

}



/**

* 设置object的属性值

* @param object 要获取属性值的镀锡

* @param fieldName 属性名

* @param value 要设置的属性值

* @return object的filedName对应的属性值

*/

public static void setFieldValue(Object object,String fieldName,Object value) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {

String setterMethodName = "set" + StringUtil.firstLetterToUpperCase(fieldName);

Class<?> fieldClass = object.getClass().getDeclaredField(fieldName).getType();



//只要public的getter方法

Method setterMethod = object.getClass().getMethod(setterMethodName,fieldClass);

if (setterMethod != null)

{

setterMethod.invoke(object,value);

}

}



/**

* 设置object的属性值

* @param object 要获取属性值的镀锡

* @param field 属性

* @param value 要设置的属性值

* @return object的filedName对应的属性值

*/

public static void setFieldValue(Object object, Field field, Object value) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {

setFieldValue(object,field.getName(),value);

}

}


package com.util;



import java.lang.reflect.ParameterizedType;

import java.lang.reflect.Type;



//这个工具类的所有方法会用就行,以后需要就直接复制粘贴

//反正这个玩意我也是百度的

public class ClassUtil {



/**

* 获取父类的泛型的类型

* @param clazz 子类

* @return 父类的泛型的Class对象

*/

public static Class getSuperClassGenricType(Class clazz) {

return getSuperClassGenricType(clazz, 0);

}



/**

* 通过反射,获得定义Class时声明的父类的范型参数的类型. 如public BookManager extends GenricManager<Book>

*

* @param clazz clazz The class to introspect

* @param index the Index of the generic ddeclaration,start from 0.

*/

public static Class getSuperClassGenricType(Class clazz, int index)

throws IndexOutOfBoundsException {

Type genType = clazz.getGenericSuperclass();

if (!(genType instanceof ParameterizedType)) {

return Object.class;

}

Type[] params = ((ParameterizedType) genType).getActualTypeArguments();

if (index >= params.length || index < 0) {

return Object.class;

}

if (!(params[index] instanceof Class)) {

return Object.class;

}

return (Class) params[index];

}





}



举报

相关推荐

0 条评论