high-level——桥接模式,模板模式及使用 jdbc 连接数据库的通用方法(19)

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

一、桥接模式(bridge)

  1. 属于结构型模式。
  2. 在抽象化和实现化之间实现脱耦。抽象化就是把对象的实现采用抽象类的方式,实现化把对象的实现采用接口。脱耦就是让抽象化体系与实现化体系不要耦合在一起。
  3. 对象功能的扩展一般都使用继承,在有些情况下会造成子类数量增长的非常快,也就是为了扩展类的功能,可能会写很多类。
  4. 把抽象类的体系剥离出来,让实现类去实现接口,让抽象类去组合实现类。
  • package com.zhong.test_11;
    
    public interface TypePC {
        void sale();
    }
    
    package com.zhong.test_11;
    
    public class DeskTopTypePC implements TypePC {
        @Override
        public void sale() {
            System.out.println("桌面电脑");
        }
    }
    
    package com.zhong.test_11;
    
    public class NotBookTypePC implements TypePC {
        @Override
        public void sale() {
            System.out.println("笔记本电脑");
        }
    }
    
    package com.zhong.test_11;
    
    public class PadTypePC implements TypePC {
        @Override
        public void sale() {
            System.out.println("Pad电脑");
        }
    }
    
    package com.zhong.test_11;
    
    public abstract class Brand {
        protected TypePC typePC;
    
        public Brand(TypePC typePC) {
            this.typePC = typePC;
        }
    
        public abstract void sale();
    }
    
    package com.zhong.test_11;
    
    public class AcerBrand extends Brand {
    
        public AcerBrand(TypePC typePC) {
            super(typePC);
        }
    
        @Override
        public void sale() {
            System.out.print("宏基");
            typePC.sale();
        }
    }
    
    package com.zhong.test_11;
    
    public class HuaWeiBrand extends Brand {
    
        public HuaWeiBrand(TypePC typePC) {
            super(typePC);
        }
    
        @Override
        public void sale() {
            System.out.print("华为");
            typePC.sale();
        }
    }
    
    package com.zhong.test_11;
    
    public class LenoveBrand extends Brand {
    
        public LenoveBrand(TypePC typePC) {
            super(typePC);
        }
    
        @Override
        public void sale() {
            System.out.print("联想");
            typePC.sale();
        }
    }
    
    package com.zhong.test_11;
    
    public class BridgeDemo {
        public static void main(String[] args) {
            TypePC typePC1 = new DeskTopTypePC();
            TypePC typePC2 = new PadTypePC();
            TypePC typePC3 = new NotBookTypePC();
    
            Brand brand1 = new LenoveBrand(typePC1);
            Brand brand2 = new AcerBrand(typePC2);
            Brand brand3 = new HuaWeiBrand(typePC3);
    
            brand1.sale();
            brand2.sale();
            brand3.sale();
    
        }
    }
    

二、JDBC 的基本概念

  1. 全称 java 数据库的连接技术。这里有两个含义,一个是建立应用程序与数据库两个进程之间的通讯管道( socket 就是两端的插口);另一个要创建连接对象。
  2. jdbc 在 jdk 中的位置
    • java.sql 包中是 jdbc 的基础 api ,主要包含驱动管理,连接创建,命令发送,结果的接收,数据类型等。
    • javax.sql 包是 jdbc 的扩展 api ,主要包含数据库连接池的相关规范。
  3. jdbc 出现的原因
    • 现在有很多厂商的数据库产品,每个数据库所提供的接口调用是不同的,应用程序操作数据库时,即使是同一种操作,代码却写的不一样。这样实现数据库相关的管理系统,代码的编写会很困难,一个程序员需要熟悉多种数据库所提供的不同的接口。java 的设计者为了解决这种问题,提供了一套操作数据库的 API 的标准,该标准提供了一系列的接口,并把它们分发给所有的数据库厂商,让他们基于这套标准来实现各自的驱动程序及操作数据库的各种对象类型。那么这套标准就成为了现在的 jdbc 技术。作为开发人员,只要知道如何使用 jdbc 就可以了。从而让开发人员更容易写出数据库的应用程序。
  4. jdbc 的基本架构:接口 --> 驱动程序 --> 数据库
  5. 使用 jdbc 操作数据库的步骤
    • 创建连接 – >发送 sql 命令 – >接收并处理结果

三、 jdbc 的技术架构

  1. 接口的部分

    • public interface Driver
      

      每个驱动程序类必须实现的接口。

    • public interface Connection extends Wrapper, AutoCloseable
      

      与特定数据库的连接(会话)。 执行SQL语句并在连接的上下文中返回结果

    • public interface Statement extends Wrapper, AutoCloseable
      

      用于执行静态SQL语句并返回其生成的结果的对象。一般称为陈述对象,陈述就是表达一个具体的操作。

    • public interface PreparedStatement extends Statement
      

      表示预编译的SQL语句的对象。预编译陈述对象。

    • public interface ResultSet extends Wrapper, AutoCloseable
      

      表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。 它包含查询的结果数据。

  2. 类的部分

    • public class DriverManager extends Object
      

      用于管理一组JDBC驱动程序的基本服务。主要作用:

      1. 注册驱动程序
      2. 利用驱动程序得到连接对象
  3. 枚举的部分

    • public enum JDBCType extends Enum<JDBCType> implements SQLType
      

      定义用于标识通用SQL类型(称为JDBC类型)的常量。

  4. 异常的部分

    • public class SQLException extends Exception implements Iterable<Throwable>
      

      提供有关数据库访问错误或其他错误的信息的异常。

四、使用 jdbc 操作数据库

  1. 创建连接,前提是加载数据库的驱动程序。

    package com.zhong.test_12;
    
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    
    public class JDBCDemo {
        //建立数据库连接需要四要素:驱动程序名;连接的url;用户名;密码
        static private String driverName = "com.mysql.cj.jdbc.Driver";//5.XX版本为com.mysql.jdbc.Driver
        //5.XXX版本可直接写jdbc:mysql://127.0.0.1:3306/数据库名?characterEncoding=utf-8
        static private String url = "jdbc:mysql://127.0.0.1:3306/students?useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true&characterEncoding=utf-8";
        static private String userName = "";
        static private String password = "";
    
        public static void main(String[] args) throws ClassNotFoundException {
            //加载驱动程序,向程序中注册加载的驱动程序
            Class.forName(driverName);
            //得到连接对象
            try (Connection connection = DriverManager.getConnection(url, userName, password)) {
                System.out.println(connection);
            } catch (SQLException sqlException) {
                sqlException.printStackTrace();
            }
    
        }
    }
    

    常用连接参数:

    • useUnicode,是否使用 Unicode 字符集,如果参数 characterEncoding 设置为 gb2312 或 gbk,本参数值必须设置为 true
    • characterEncoding,当 useUnicode 设置为 true,给定编码,常用utf8,默认是:autodetect
    • allowMultiQueries,允许一个 statement 执行多个用;分割的sql,默认false 使用 update 或 insert 执行多行语句时必须为 true
    • useSSL,连接 MySQL 5.5.45+, 5.6.26+ or 5.7.6+ 默认为 true,之前低版本为 false
    • useAffectedRows,默认 false 此时使用 update 或 insert 返回匹配到的行数,改为 true 返回实际影响的记录数
    • serverTimezone,默认CST 但由于 CST 定义解析混乱 应改为 GMT%2B8 或 Asia / Shanghai

    注意,远程连接 mysql 时需要在 my.ini(win) 或 my.conf(linux) 里添加参数:bind-address=0.0.0.0(这里写允许通过的地址,有多个地址用空格分开),并且在本地连接中依次执行 use mysql; 和 select Host,User from user; 命令,Host 为%表示允许任意地址连接此数据库,为 localhost 或 127.0.0.1 则表示只允许本地连接。此时可执行 update user set Host=‘符合预期的地址’ where User=‘目标账号’;命令可以修改。也就是说要想远程连接本地数据库需要修改两处。

    • 问题:DriverManager 提供了 getConnection() 方法来得到连接对象,该方法是工厂方法,因此属于工厂模式。连接对象是由 DriverManager 创建的吗?

      private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();
      
      • 线程安全的 List,如果需要改变集合中的元素,先把集合复制一份,在复制品上进行修改,然后把复制品转换为源集合。所有的驱动程序加载后都存放在该集合中。这个过程就是驱动程序的注册。

        源码:

      • private static Connection getConnection(
            String url, java.util.Properties info, Class<?> caller) throws SQLException {
            /*
             * When callerCl is null, we should check the application's
             * (which is invoking this class indirectly)
             * classloader, so that the JDBC driver class outside rt.jar
             * can be loaded from here.
             */
            ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
            synchronized(DriverManager.class) {
                // synchronize loading of the correct classloader.
                if (callerCL == null) {
                    callerCL = Thread.currentThread().getContextClassLoader();
                }
            }
        
            if(url == null) {
                throw new SQLException("The url cannot be null", "08001");
            }
        
            println("DriverManager.getConnection(\"" + url + "\")");
        
            // Walk through the loaded registeredDrivers attempting to make a connection.
            // Remember the first exception that gets raised so we can reraise it.
            SQLException reason = null;
        
            for(DriverInfo aDriver : registeredDrivers) {
                // If the caller does not have permission to load the driver then
                // skip it.
                if(isDriverAllowed(aDriver.driver, callerCL)) {
                    try {
                        println("    trying " + aDriver.driver.getClass().getName());
                        Connection con = aDriver.driver.connect(url, info);
                        if (con != null) {
                            // Success!
                            println("getConnection returning " + aDriver.driver.getClass().getName());
                            return (con);
                        }
                    } catch (SQLException ex) {
                        if (reason == null) {
                            reason = ex;
                        }
                    }
        
                } else {
                    println("    skipping: " + aDriver.getClass().getName());
                }
        
            }
        
            // if we got here nobody could connect.
            if (reason != null)    {
                println("getConnection failed: " + reason);
                throw reason;
            }
        
            println("getConnection: no suitable driver found for "+ url);
            throw new SQLException("No suitable driver found for "+ url, "08001");
        }
        
      • 连接对象是由数据库驱动程序创建的。Connection con = aDriver.driver.connect(url,info);得到的连接对象是单例的。

五、通过属性文件来保存连接的四要素

  • package com.zhong.test_12;
    
    
    import java.io.FileReader;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.util.Properties;
    
    public class JDBCDemo {
        //建立数据库连接需要四要素:驱动程序名;连接的url;用户名;密码
        //5.XXX版本可直接写jdbc:mysql://127.0.0.1:3306/数据库名?characterEncoding=utf-8
    
        static {
            try {
                //加载驱动程序,向程序中注册加载的驱动程序
                Class.forName(getProperties().getProperty("driverName"));
                //Class.forName(Objects.requireNonNull(getProperties()).getProperty("driverName"));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            //得到连接对象
            Connection connection = getConnection();
            System.out.println(connection);
        }
    
        private static Properties getProperties() {
            Properties properties;
            try {
                properties = new Properties();
                properties.load(new FileReader("E:\\IDEA project\\src\\com\\zhong\\test_12\\db.properties"));
                return properties;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        private static Connection getConnection() {
            Properties prop = getProperties();
            Connection connection = null;
            try {
                assert prop != null;
                connection = DriverManager.getConnection(prop.getProperty("url"), prop.getProperty("userName"), prop.getProperty("password"));
            } catch (SQLException sqlException) {
                sqlException.printStackTrace();
            }
            return connection;
        }
    }
    
  • 遵循面向对象的五大设计原则(SOLID)的第一个原则也就是职责单一原则来获得连接对象,把原来 main 方法中的代码拆成四个部分,驱动程序的加载放在静态代码块中保证本类被加载后驱动程序就被加载;把获得 Properties 对象和获得连接对象分别放在不同的方法中,在 main 方法中调用相关方法得到连接对象。

六、测试创建连接的耗时

  • 利用 jdbc 操作数据库的几种操作都属于重量级的操作。解决连接耗时问题方案:
  1. 使用数据库连接池

    • 使用数据库连接池要管理连接
    1. dbcp,属于 apache 公司的连接池,内嵌在 tomcat 中。单线程
    2. c3p0,比 dbcp 速度更快。单线程
    3. druid,属于阿里巴巴,比上面两个要快很多。多线程
  2. 把使用频率高的数据放在缓存中

  3. 使用 CDN 网络,把最常用且不怎么变化的数据放在离用户最近的地方

  • 使用 druid 连接池

    (1)项目中引用 druid 的 jar 包

    (2)创建连接池对象,指定与连接池相关的一些属性。一部分是四个连接要素,另一部分就是与连接池相关的要素。

    (3)通过连接池对象得到连接对象。

    (4)把使用完成的连接对象归还到池中,保证连接对象可以被复用。避免了重复创建连接对象的操作。

    • 使用连接池节约的时间与不使用情况下的差距有十几倍(不同环境下结果可能会相差很大)。

    • package com.zhong.test_12;
      
      
      import com.alibaba.druid.pool.DruidDataSource;
      
      import java.io.FileReader;
      import java.sql.Connection;
      import java.sql.DriverManager;
      import java.sql.SQLException;
      import java.util.Properties;
      
      public class JDBCDemo {
          //建立数据库连接需要四要素:驱动程序名;连接的url;用户名;密码
          //5.XXX版本可直接写jdbc:mysql://127.0.0.1:3306/数据库名?characterEncoding=utf-8
          static DruidDataSource dds;
      
          static {
              try {
                  Class.forName(getProperties().getProperty("driverName"));//
                  long begin = System.currentTimeMillis();
                  dds = new DruidDataSource();
                  //加载驱动程序,向程序中注册加载的驱动程序
                  dds.setDriverClassName(getProperties().getProperty("driverName"));
                  //dds.setDriverClassName(Objects.requireNonNull(getProperties()).getProperty("driverName"));
                  dds.setUrl(getProperties().getProperty("url"));
                  dds.setUsername(getProperties().getProperty("userName"));
                  dds.setPassword(getProperties().getProperty("password"));
                  dds.setInitialSize(5);
                  dds.setMinIdle(5);
                  dds.setMaxActive(20);
                  long end = System.currentTimeMillis();
                  System.out.println("create pool cost total time:" + (end - begin));
      
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      
          public static void main(String[] args) {
      
              //得到连接对象
              for (int i = 0; i < 100; i++) {
                  new Thread(() -> {
                      long begin = System.currentTimeMillis();
                      //Connection connection = getConnection();
                      Connection connection = null;
                      try {
                          connection = dds.getConnection();
                      } catch (SQLException sqlException) {
                          sqlException.printStackTrace();
                      }
                      try {
                          assert connection != null;
                          connection.close();
                      } catch (SQLException e) {
                          e.printStackTrace();
                      }
                      long end = System.currentTimeMillis();
                      System.out.println("getConnection " + connection + " " + (end - begin));
                  }).start();
              }
      
      
          }
      
          private static Properties getProperties() {
              Properties properties;
              try {
                  properties = new Properties();
                  properties.load(new FileReader("E:\\IDEA project\\src\\com\\zhong\\test_12\\db.properties"));
                  return properties;
              } catch (Exception e) {
                  e.printStackTrace();
              }
              return null;
          }
      
          private static Connection getConnection() {
              Properties prop = getProperties();
              Connection connection = null;
              try {
                  assert prop != null;
                  connection = DriverManager.getConnection(prop.getProperty("url"), prop.getProperty("userName"), prop.getProperty("password"));
              } catch (SQLException sqlException) {
                  sqlException.printStackTrace();
              }
              return connection;
          }
      
      }
      

七、模板模式(Template)

  1. 某些算法有确定的步骤,还有可能其中的某些步骤是完全一样的,这样可用抽象类把算法的具体步骤固定,把具有相同代码的步骤具体化,从而形成算法的骨架,再把其中抽象的方法放到子类中实现,因此完整功能的实现由抽象类与子类共同完成,这样在子类中实现的方法是一种延迟的实现。
  2. 好处在于明确了执行步骤,公共的代码实现了共享,符合五大设计原则(SOLID)中的第二大原则 “开放闭合原则” ,也就是对扩展开放,对修改关闭。
  3. 缺点在于子类的数量不受控制。

八、学习 jdbc 中对数据库的表操作

  1. 创建连接池,产生连接,释放资源的功能封装为一个工具类。
  2. 创建实现增删改操作的类。
    • 这里使用了 PrepareStatement 这个声明接口对象,而没有使用 Statement 这个陈述接口和对象。使用 Statement 来发送 sql,sql 是静态的,在执行前要把参数拼接到 sql 命令中,这样容易拼错,Statement 的同一命令每次执行都需要数据库进行编译,执行效率不高。
    • PrepareStatement 提供了预编译功能,同一命令在数据库端只编译一次,后面再执行时不在编译,执行效率高。它的 sql 命令中的参数不需要进行拼接,用 “?” 作为占位符,通过 setXXX(index,参数) 的方法进行参数的传递,使用比较简单,不易出错。
    • 现代的主流 ORM 框架内部都使用 PrepareStatement 来执行命令。
  3. 在实现增删改的功能时,要使用显示的事务处理机制。 jdbc 默认的事务处理是隐式的处理,这种事务是针对单一的 DML 操作命令。在 java 程序中,需要开启显示事务,在命令成功执行后提交事务,命令执行失败就回滚事务。
  4. ResultSet 接口的对象包含了查询的结果,结果以一种虚拟表的形式来表示,可以包含多条记录。它内部有一个指针,可以指向每一条记录,指针指向的记录就是当前记录,程序可以对当前记录进行处理。指针可以移动(一般从上到下),每处理完一条记录指针就向下移动一条记录,就可以处理下一条记录。结果集刚生成时,指针指向头部(第一条记录的前面),最终指针会移动到尾部(最后一条记录的后面),此时处理过程也就结束了。
    • next() 把指针向下移动一条记录,如果指向了具体的记录返回 true,如果到达了尾部返回 false。
  5. 对于查询功能,其中的代码分为两个部分,第一部分是不变的部分(任何查询都要执行),第二部分是可变的代码。
  6. 采用模板模式来设计查询功能
    • 定义一个抽象类,封装公共的部分,变化的部分调用抽象方法;定义一个子类并继承抽象类,实现抽象的方法(具体的实现)。这样有多少个不同的实现就要创建多少个类。
    • 一下 DBUtils,DML,DQL 是通用类,可用于任意 sql 连接。
package com.zhong.test_12;

import com.alibaba.druid.pool.DruidDataSource;

import java.io.FileReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

/**
 * 数据库工具类,提供创建连接池,产生连接对象,关闭资源等功能
 */

public class DBUtils {
    //建立数据库连接需要四要素:驱动程序名;连接的url;用户名;密码
    //5.XXX版本可直接写jdbc:mysql://127.0.0.1:3306/数据库名?characterEncoding=utf-8
    private DruidDataSource dds;
    private final String propPath;

    public DBUtils(String propPath) {
        //初始化
        this.propPath = propPath;
        try {
            Class.forName(getProperties().getProperty("driverName"));//加上这个会提高效率
            //Class.forName(Objects.requireNonNull(getProperties()).getProperty("driverName"));//加上这个会提高效率
            dds = new DruidDataSource();
            //加载驱动程序,向程序中注册加载的驱动程序
            dds.setDriverClassName(getProperties().getProperty("driverName"));
            //dds.setDriverClassName(Objects.requireNonNull(getProperties()).getProperty("driverName"));
            dds.setUrl(getProperties().getProperty("url"));
            dds.setUsername(getProperties().getProperty("userName"));
            dds.setPassword(getProperties().getProperty("password"));
            dds.setInitialSize(Integer.parseInt(getProperties().getProperty("initialSize")));//初始数量
            dds.setMinIdle(Integer.parseInt(getProperties().getProperty("minIdle")));//最小的空闲连接数量
            dds.setMaxActive(Integer.parseInt(getProperties().getProperty("maxActive")));//最大允许的连接数量
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //读取属性文件
    private Properties getProperties() {
        Properties properties;
        try {
            properties = new Properties();
            properties.load(new FileReader(this.propPath));
            return properties;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    //得到连接
    public Connection getConnection() {
        try {
            // return DriverManager.getConnection(getProperties().getProperty("url"), getProperties().getProperty("userName"), getProperties().getProperty("password"));
            return this.dds.getConnection();
        } catch (SQLException sqlException) {
            sqlException.printStackTrace();
        }
        return null;
    }
	//关闭连接
    public static void release(Connection con, PreparedStatement pst, ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (pst != null) {
            try {
                pst.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (con != null) {
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
package com.zhong.test_12;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class DML {
    /**
     * 实现增删改的操作
     * 需要先调用setConnection方法
     * @param *sql,增删改命令
     * @param *params sql命令中的参数
     */
    private static Connection con;
    private static PreparedStatement pst;

    public static void setConnection(Connection con) {
        DML.con = con;
    }

    //private static Connection con;
    public static void update(String sql, Object... params) {
        try {
            pst = con.prepareStatement(sql);//创建预编译声明对象

            //给 sql 命令注入参数
            for (int i = 0; i < (params == null ? -1 : params.length); i++) {
                pst.setObject(i + 1, params[i]);
            }
            //发送并执行命令
            //设置事务为显示事务
            con.setAutoCommit(false);
            int result = pst.executeUpdate();
            if (result == 0) System.out.println("执行失败!");
            else {
                System.out.println("执行成功!");
                //提交事务
                con.commit();
            }

        } catch (SQLException sqlException) {
            //命令执行失败,回滚事务
            try {
                con.rollback();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            sqlException.printStackTrace();
        } finally {
            DBUtils.release(con, pst, null);
        }
    }
}
package com.zhong.test_12;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

/**
 * 实现查询操作,不需要考虑事务的问题
 * 使用模板设计模式
 *
 * @param *sql查询命令
 * @param *sql命令中的参数
 * 需要先调用setConnection方法
 */

public abstract class DQL<T> {
    private static Connection con;
    private static PreparedStatement pst;
    private ResultSet rs;

    public static void setConnection(Connection con) {
        //得到连接
        DQL.con = con;
    }
    public List<T> query(String sql, Object... params) {
        try {
            pst = con.prepareStatement(sql);//创建预编译声明对象
            //给 sql 命令注入参数
            for (int i = 0; i < (params == null ? -1 : params.length); i++) {
                pst.setObject(i + 1, params[i]);
            }
            //发送并执行命令,得到结果集
            rs = pst.executeQuery();
            //处理结果的具体代码,本方法的设计者不知道最终用户要如何处理结果
            return process(rs);

        } catch (SQLException sqlException) {
            sqlException.printStackTrace();
        } finally {
            DBUtils.release(con, pst, rs);
        }
        return null;
    }
    protected abstract List<T> process(ResultSet rs);//对返回的结果的具体操作
}
package com.zhong.test_12;

import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * 处理数据的一种方式,这是需要改变的。
 */

public class ProductQuery extends DQL<Products> {
    @Override
    protected List<Products> process(ResultSet rs) {
        List<Products> list = new ArrayList<>();
        try {
            while (rs != null && rs.next()) {
                Products p = new Products();//特别注意:这行代码必须在循环内,否则会出现 list 内的值全是最后一条记录的情况,别问我怎么知道
                p.setProd_id(rs.getString(1));
                p.setVend_id(rs.getString(2));
                p.setProd_name(rs.getString(3));
                p.setProd_price(rs.getDouble(4));
                p.setProd_desc(rs.getString(5));
                list.add(p);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }
}
package com.zhong.test_12;
//实体类,和数据库中相应表中字段对应
public class Products {
    private String prod_id;
    private String vend_id;
    private String prod_name;
    private double prod_price;
    private String prod_desc;

    public String getProd_id() {
        return prod_id;
    }

    public void setProd_id(String prod_id) {
        this.prod_id = prod_id;
    }

    public String getVend_id() {
        return vend_id;
    }

    public void setVend_id(String vend_id) {
        this.vend_id = vend_id;
    }

    public String getProd_name() {
        return prod_name;
    }

    public void setProd_name(String prod_name) {
        this.prod_name = prod_name;
    }

    public double getProd_price() {
        return prod_price;
    }

    public void setProd_price(double prod_price) {
        this.prod_price = prod_price;
    }

    public String getProd_desc() {
        return prod_desc;
    }

    public void setProd_desc(String prod_desc) {
        this.prod_desc = prod_desc;
    }
    
    @Override
    public String toString() {
        return "Products{" +
                "prod_id='" + prod_id + '\'' +
                ", vend_id='" + vend_id + '\'' +
                ", prod_name='" + prod_name + '\'' +
                ", prod_price=" + prod_price +
                ", prod_desc='" + prod_desc + '\'' +
                '}';
    }
}
package com.zhong.test_12;

import org.junit.Test;

import java.util.List;

/**
 * 测试类,其中的方法都是测试方法,测试具体功能的执行是否正常
 *
 * @Test 修饰的方法是测试方法
 */

public class StudentsTest {

    static {
        DML.setConnection(new DBUtils("E:\\IDEA project\\src\\com\\zhong\\test_12\\db.properties").getConnection());
        DQL.setConnection(new DBUtils("E:\\IDEA project\\src\\com\\zhong\\test_12\\db.properties").getConnection());
    }

    @Test
    public void testInsert() {
        DML.update("insert into products(prod_id,vend_id,prod_name,prod_price,prod_desc) values(?,?,?,?,?);", "111", "DLL01", "111", 6.25, "111");
    }

    @Test
    public void testUpdate() {
        DML.update("update products set prod_name = ? where prod_id = ?", "aaa", "111");
    }

    @Test
    public void testDelete() {
        DML.update("delete from products where prod_id = ?", "111");
    }

    @Test
    public void testQuery() {
        ProductQuery pq = new ProductQuery();
        List<Products> list = pq.query("select * from products;", null);
        for (Products products : list) {
            System.out.println(products);
        }
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Æ_华韵流风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值