• 利用动态代理去实现JDBC增删改查


    什么叫做动态代理:就是不用我们手动去编写代理类了,系统会自动帮你生成,生成的类是在内存里,不占用硬盘空间,也不会像静态代理一样添加一个方法就需要改一遍代理类。动态代理就是一劳永逸。

    废话不多说直接看代码

    首先需要准备一个.properties配置文件

    //此文件为配置文件以key-value键值对的方式出现
    //加载mysql驱动
    jdbc.driver=com.mysql.jdbc.Driver
    //数据库链接地址
    jdbc.connection.url=jdbc:mysql://localhost:3306/lx1
    //数据库用户名
    jdbc.connection.username=root
    //数据库密码
    jdbc.connection.password=

    如图所示的文件:

     接下来就开始编写我们的接口类了

    package cn.dao;
    
    import java.sql.ResultSet;
    //接口类
    public interface JDBC_operation {
        void getConnection();//获得连接的方法
        int executeUpdate(String sql,Object...obj);//增删改  里面需要传入一个sql语句还有一个不定长参数(是为sql语句里面?准备的)
        ResultSet executeQuery(String sql,Object...obj);//查询   里面需要传入一个sql语句还有一个不定长参数(是为sql语句里面?准备的)
        void closeAll();//关闭连接资源
    }

     接下来编写实现类

    package cn.dao;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.sql.*;
    import java.util.Properties;
    
    public class JDBC_impl implements JDBC_operation{
        private static String drivate;
        private static String url;
        private static String username;
        private static String password;
        private Connection connection;
        private PreparedStatement preparedStatement;
        private ResultSet resultSet;
       //静态代码块获得我们连接数据库所需要的信息
        static {
            Properties properties=new Properties();//这个方法可以读取配置文件.properties
            InputStream in = JDBC_impl.class.getClassLoader().getResourceAsStream("database.properties");
            try {
                properties.load(in);//load方法可以读取文件
                //获得配置文件里面的对应内容
                drivate=properties.getProperty("jdbc.driver");
                url=properties.getProperty("jdbc.connection.url");
                username=properties.getProperty("jdbc.connection.username");
                password=properties.getProperty("jdbc.connection.password");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
       //连接
        @Override
        public void getConnection(){
            try {
                //加载驱动
                Class.forName(drivate);
                //获得数据库的连接
                connection = DriverManager.getConnection(url, username, password);
            } catch (SQLException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
       //增删改
        @Override
        public int executeUpdate(String sql,Object...obj) {
            try {
                //用PreparedStatement对象去执行sql代码
                preparedStatement = connection.prepareStatement(sql);
                //不定长参数产生的是一个数组所以我们要用for循环去遍历它的长度(不定长参数可以为空)
                for (int i=0;i<obj.length;i++){
                    //给执行的sql语句里面的?赋值
                    preparedStatement.setObject(i+1,obj[i]);
                }
                //执行增删改的方法
                int i = preparedStatement.executeUpdate();
                //返回行数
                return i;
            } catch (SQLException e) {
                e.printStackTrace();
                //捕获到异常则返回-1
                return -1;
            }
        }
        //查询
        @Override
        public ResultSet executeQuery(String sql,Object...obj) {
            try {
                //用PreparedStatement对象去执行sql代码
                preparedStatement = connection.prepareStatement(sql);
                //不定长参数产生的是一个数组所以我们要用for循环去遍历它的长度(不定长参数可以为空)
                for (int i=0;i<obj.length;i++){
                    //给执行的sql语句里面的?赋值
                    preparedStatement.setObject(i+1,obj[i]);
                }
                //执行查询的方法
                resultSet = preparedStatement.executeQuery();
                //返回结果集
                return resultSet;
            } catch (SQLException e) {
                e.printStackTrace();
                //捕获到异常则返回-1
                return null;
            }
        }
        //关闭
        @Override
        public void closeAll() {
            if(resultSet!=null){
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(preparedStatement!=null){
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(connection!=null){
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    好了,接下来就是我们的动态代理了,为什么在这里需要用到动态代理呢是因为JDBC操作的时候总是要连接数据库和释放资源,如果用动态代理就会省略这两步,让系统自动帮我们实现,这样省去了很多的重复操作。

    package cn.dao;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    //创建动态代理需要实现InvocationHandler接口    面向接口实现的动态代理
    public class Agent implements InvocationHandler {
        private JDBC_operation jdbc;
    
        public Agent(JDBC_operation jdbc) {
            this.jdbc = jdbc;
        }
        public Agent() {
        }
        @Override
        //第一个参数proxy是真实对象的真实代理对象,invoke方法可以返回调用代理对象方法的返回结果,也可以返回对象的真实代理对象(可以使用反射获取代理对象的信息)
        //第二个则是需要代理的接口
        //第三个则是参数
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            long l = System.currentTimeMillis();
            jdbc.getConnection();//代理实现的方法
            System.out.println("已连接");
            Object o = method.invoke(jdbc, args);//需要传递要代理的接口以及参数
            jdbc.closeAll();//代理实现的方法
            System.out.println("已关闭");
            long l1 = System.currentTimeMillis();
            System.out.println("总用毫秒数:"+(l1-l)+"ms");
            return o;
        }
    
    }

    接下来我们就去测试一下

    package cn.dao;
    
    import java.lang.reflect.Proxy;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    public class Test {
        public static void main(String[] args) throws SQLException {
            JDBC_operation jdbc=new JDBC_impl();//实例化自己定义的方法实现类对象
            //第一个参数: 用哪个类加载器去加载代理对象
            //第二个参数:动态代理类需要实现的接口
            //第三个参数:动态代理方法在执行时,会调用InvocationHandler里面的invoke方法去执行
           JDBC_operation o = (JDBC_operation)Proxy.newProxyInstance(jdbc.getClass().getClassLoader(), new Class[]{JDBC_operation.class}, new Agent(jdbc));
            String sql="insert into student(stuname) values('哈哈')";
            int i = o.executeUpdate(sql);
            if (i>0){
                System.out.println("插入数据成功");
            }else {
                System.out.println("插入数据失败");
            }
        }
    }

    结果如下:

    这里需要注意一下,查询的话需要把动态代理的关闭资源方法去掉,需要我们调用之后自己手动关闭,因为不关掉就会出现如下错误:

    这个的意思是:线程“main”java中的异常。sql。SQLException:在com处ResultSet关闭后,不允许操作。mysgl。jdbc。SQLError。原因是数据库不允许这样操作,所以我们直接用对象调用关闭的方法就好了

    增删改不会出现这种错误

    努力到无能为力,拼搏到感动自己
  • 相关阅读:
    使用 SQL Server 2008 数据类型-xml 字段类型参数进行数据的批量选取或删除数据
    启用Windows 7/2008 R2 XPS Viewer
    Office 2010培训资料
    WCF WebHttp Services in .NET 4
    ASP.NET MVC 2示例Tailspin Travel
    .NET 4.0 的Web Form和EF的例子 Employee Info Starter Kit (v4.0.0)
    连任 2010 年度 Microsoft MVP
    MIX 10 Session下载
    Microsoft Silverlight Analytics Framework
    Windows Azure入门教学
  • 原文地址:https://www.cnblogs.com/tkzm/p/11177355.html
Copyright © 2020-2023  润新知