JDBC增删改查封装(mysql)

5 篇文章 0 订阅
5 篇文章 0 订阅

基于mysql的JDBC的增删改查的封装

忧伤…昨晚写的代码简直不能看啊,你们看完了竟然不告诉我~哼!
趁着我现在有空,把这篇博客再优化一下,就叫我女神吧!
首先,这是一篇有节操的博客,主要介绍JDBC对数据库(这里以mysql为例)的操作:添加数据,修改数据,删除数据,查询数据(用反射+内省来实现)
若您的火眼金睛发现我有小错误的话,咱们评论中交流哇~

1 数据库(mysql)操作:

在数据库中创建一张表,这里以用户表为例,如下图:table_name:user,您的table,怎么舒服怎么建:
还有jdbc驱动的jar包的引入我就略了,不要忘记导入这个jar包噢~
user

2 创建类(User.java):

先封装一个用户类(User),当然你可以封装其他的类,在封装类的时候注意以下两点:

1. 类中的属性名要和数据库对应表的列名一致(一模一样拿过来就对了):是为了方便后面通过内省获取指定方法,名字不一样的话,找到地老天荒也找不到┗|`O′|┛ 嗷~~
2. 属性(成员)的数据类型最好是包装类型:通过内省获取的方法传参时用的是从数据库中拿出来的数据(放到结果集中了),你可以测试一下,这些数据是包装类型欧
也可以不实现Serializable接口,这个是实现数据库连接池时使用的,懒得删了~

package com.myproject.beans;
import java.io.Serializable;
/**
 * Administrator
 * 2019/4/15 0015
 * 用户类
 */
public class User implements Serializable {
    private static final long serialVersionUID = 373910607014836778L;
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private String gendar;

    public User() {
    }

    public User(Integer id, String username, String password, Integer age, String gendar) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.age = age;
        this.gendar = gendar;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getGendar() {
        return gendar;
    }

    public void setGendar(String gendar) {
        this.gendar = gendar;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                ", gendar='" + gendar + '\'' +
                '}';
    }
}
3 创建配置文件(db.properties)

主要是将连接数据库的几个变量封装一下,更换数据库信息的时候,我们只需要修改这个配置文件中的内容即可,对,一切为了方便,emm~懒创造了高效的代码:

#驱动名称
driverClass=com.mysql.jdbc.Driver
#数据库url
url=jdbc:mysql:///mydatebase
#当然上面的这句话就等价于:url=jdbc:mysql://localhost:3306/mydatabase
#数据库用户名
user=root
#数据库密码
password=root
4 创建封装类(DB_Tools.java)

本篇博客所有的精华都在这里了,来让我们一起来感受一下:

4.1 注册JDBC驱动

将注册驱动的实现代码置于静态代码块中,类被调用时首先被加载:
通过加载配置文件,完成JDBC的驱动注册,(悄咪咪的问一下,看到这里的你应该知道不同的数据库有不同的JDBC驱动不~

public class DB_Tools{
    private static String driverClass;
    private static String url;
    private static String user;
    private static String password;
    /**
     *1.注册JDBC驱动
     */
    static {
        try {
            //获取配置文件
            InputStream inputStream = DB_Tools.class.getClassLoader().getResourceAsStream("db.properties");
            Properties properties = new Properties();
            properties.load(inputStream);
            //从配置文件中获取数据信息
            driverClass = properties.getProperty("driverClass");
            url = properties.getProperty("url");
            user = properties.getProperty("user");
            password = properties.getProperty("password");
            try {
                //注册驱动
                Class.forName(driverClass);
                System.out.println("注册驱动成功");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("注册驱动失败");
        }
    }
}
4.2 获取数据库连接

这个感觉没有什么好说的,就是常规操作嘛~

public class DB_Tools{
    /**
     * 2.获取连接
     * @return Connection null连接失败 !null连接成功
     */
    public static Connection getDBConnection() {
        try {
            return DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
}
4.3 断开连接释放资源

emmm,这个也是常规操作~
注意以下关闭的顺序就好了,这里我们用PreparedStatement的父类Statement(虽然我不是很喜欢这个接口),使代码更加灵活.

public class DB_Tools{
    /**
     * 3.释放资源close()
     * @param connection        连接
     * @param preparedStatement 执行命令
     * @param resultSet         结果集
     */
    public static void allClose(Connection connection, Statement statement, ResultSet resultSet) {
        try {
        	if (resultSet != null) {
                resultSet.close();
            }
            if (statement!= null) {
                statement.close();
            }
            if (connection != null) {
                connection.close();
            }
            System.out.println("执行结束");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
4.4 执行增删改查

代码中都有注释,我是仙女本仙没错了~看看下面的代码,增删改的操作返回的结果是一个int类型的数字:
操作成功 结果>0 返回受影响的行数,
操作失败 结果<0 返回的是一个负数,
还有一个点:这里用PreparedStatement,本仙不喜欢Statement,Statement会发生sql注入,嫌弃.PreparedStatement相对来说会做预处理,执行效率高还比较安全,可以举一个生动形象的例子:Statement是我眼里的渣男,而PreparedStatement就是那完美的男神!
代码如下:

public class DB_Tools{
     /**
     * 4.执行增删改
     * @param sql     sql操作语句
     * @param objects sql语句中的参数,可以为null
     * @return int >0操作(增删改)成功 <0操作失败
     */
    public static int excumentDBUpdate(String sql, Object[] objects) {
        int updateResult = 0;
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            //1.获取连接
            connection = getDBConnection();
            //2.获取增删改查的执行命令
            preparedStatement = connection.prepareStatement(sql);
            //3.向sql语句中?填充数据
            if (objects != null) {
                for (int i = 0; i < objects.length; i++) {
                    preparedStatement.setObject(i + 1, objects[i]);
                }
            }
            //4.执行增删改查
            updateResult = preparedStatement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //5.关闭连接,释放资源
            allClose(connection, preparedStatement, null);
        }
        return updateResult;
    }
}
4.5 (重点)查询数据

你也能看出来,前面的都太简单了,嗯哼不用写出来,谁都会的么那重点就来了:
下面的炫点有三个:

1.泛型的使用
2.反射的使用
> 3.内省的使用
上面使代码复用性更高

4.5.1 查询单条数据

思路:如代码中注释所示(我是有个仙女没错了,写代码还加注释~)

public class DB_Tools{
    //这个我先放在前面,后面就不再赘述了
 	/**
     * 通过反射+内省将结果集中数据拿出来
     * @param resultSet 结果集啊
     * @param tClass 传递过来的操作类
     * @param <T> 泛型
     * @return 返回一个泛型对象Object
     * @throws Exception
     */
    public static <T> T getObject(ResultSet resultSet, Class<T> tClass) throws Exception {
        T object = tClass.newInstance();
        ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
        for (int i = 0; i < resultSetMetaData.getColumnCount(); i++) {
            //获取列名
            String colName = resultSetMetaData.getColumnName(i + 1);
            //通过内省获取包含列名指定方法(一般是get和set)
            PropertyDescriptor propertyDescriptor = new PropertyDescriptor(colName, tClass);
            if (propertyDescriptor != null) {
                //获取到方法后我们再获取set方法来对private修饰的相关属性进行赋值
                Method method = propertyDescriptor.getWriteMethod();
                //然后我们执行这个方法并将属性添加到object对象中
                method.invoke(object, resultSet.getObject(colName));
            }
        }
        return object;
    }

	 /**
     * 5.查询单条数据(反射加内省实现)
     *
     * @param sql     sql操作语句
     * @param objects sql语句中的参数,可以为null
     * @param tClass
     * @param <T>     泛型
     * @return 返回单个实体对象
     */
    public static <T> T getSingleResult(String sql, Object[] objects, Class<T> tClass) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        T object = null;

        try {
            //1.获取连接
            connection = getDBConnection();
            //2.创建命令对象
            preparedStatement = connection.prepareStatement(sql);
            //3.向sql语句中添加数据(objects),如果objects不为空的话
            if (objects != null) {
                for (int i = 0; i < objects.length; i++) {
                    preparedStatement.setObject(i + 1, objects[i]);
                }
            }
            //4.执行查询语句
            resultSet = preparedStatement.executeQuery();
            //5.通过反射创建tClass类的对象
            //6.从结果集中获取数据
            if (resultSet.next()) {
                object = getObject(resultSet, tClass);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //7.关闭连接释放资源
            allClose(connection, preparedStatement, resultSet);
        }
        //8.返回object对象
        return object;
    }
}
4.5.2 查询多条数据

实现和前面的思路如出一辙,我们这里有个人的脚超级臭(我发现好像是我胖胖的同桌的jio…),伴着阵阵吹向我的方向的微风,我快给熏牺牲了,怀疑人生…快速沾完这个代码撤!狗命重要!

public class DB_Tools{
	 /**
     * 5.2查询多条数据(反射+内省实现)
     *
     * @param sql     sql操作语句
     * @param objects sql语句中的参数,可以为null
     * @param tClass
     * @param <T>     泛型
     * @return 返回多个对象的集合
     */
    public static <T> List<T> getComplexResult(String sql, Object[] objects, Class<T> tClass) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        List<T> tList = new ArrayList<T>();

        try {
            //1.获取连接
            connection = getDBConnection();
            //2.创建命令对象
            preparedStatement = connection.prepareStatement(sql);
            //3.向sql语句中添加数据(objects),如果objects不为空的话
            if (objects != null) {
                for (int i = 0; i < objects.length; i++) {
                    preparedStatement.setObject(i + 1, objects[i]);
                }
            }
            //4.执行查询语句
            resultSet = preparedStatement.executeQuery();
            //5.从结果集中获取数据
            while (resultSet.next()) {
                T object = getObject(resultSet, tClass);
                tList.add(object);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //7.关闭连接释放资源
            allClose(connection, preparedStatement, resultSet);
        }
        //8.返回tList集合
        return tList;
    }
}

本篇博客只是模拟了对JDBC增删改查超简易封装,和Apache提供的对JDBC进行简单封装的开源工具类库DBUtils还相差甚远,后面有时间我会写一篇关于DBUtils这个轻量级工具类的介绍,敬请期待.

感谢你看到了这里啊,
如果你有收获的话记得点赞呦
有问题可以留言,本仙看见了就会回复的
再见,祝您学习快乐,生活愉快~

  • 25
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 22
    评论
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值