当前位置:首页 » 《关注互联网》 » 正文

MySQL数据库学习笔记(三)_骑士逸

17 人参与  2021年08月06日 13:03  分类 : 《关注互联网》  评论

点击全文阅读


连接池

  • 概述:开发中,获取以及释放连接,都是非常消耗资源的操作;为了解决该性能问题,通常情况下都是采用连接池技术。有了连接池,就不用自己创建Connection,而是从连接池中获取Connection;而调用close()方法时,就是归还Connection,而不是直接销毁该Connection;等到下次需要再次使用连接时,就再从连接池中获取Connection。
    在这里插入图片描述
  • 规范:Java为数据库连接池提供了公共的接口:javax.sql.DataSource;各个厂商需要让自己的连接池实现这个接口。

自定义连接池

关键技术点

连接池中由于需要频繁地进行添加/移除操作,故而采用LinkedList集合(链表);释放资源时,不执行close()方法,而是将该Connection放入连接池中;等下次需要使用时,再拿出来。

代码

版本01:

public class MyDataSource_V1 implements DataSource {
 //创建一个连接池(容器使用LinkedList)
 private static LinkedList<Connection> pool = new LinkedList<Connection>();

 //初始化连接池(往连接池里放入10个连接)
 static {
     for (int i = 0; i < 10; ++i) {
         //获取连接
         Connection conn = JDBCUtils_V3.getConnection();
         //把连接放入连接池中
         pool.add(conn);
     }
 }

 //这里只需要实现getConnection()方法,其余方法不实现(或者是空实现)
 @Override
 public Connection getConnection() throws SQLException {
     //获取连接之前先判断连接池里有没有连接
     if (pool.size() > 0) {
         //如果有连接,那就直接获取即可
         return pool.removeFirst();
     } else {
         //如果没有连接,那就往连接池中添加10个连接
         for (int i = 0; i < 10; ++i) {
             pool.add(JDBCUtils_V3.getConnection());
         }
     }
     return pool.removeFirst();
 }

 //释放连接(把连接归还到连接池中)
 public void backConnection(Connection conn) {
     pool.add(conn);
 }

 @Override
 public Connection getConnection(String username, String password) throws SQLException {
     return null;
 }

 @Override
 public <T> T unwrap(Class<T> iface) throws SQLException {
     return null;
 }

 @Override
 public boolean isWrapperFor(Class<?> iface) throws SQLException {
     return false;
 }

 @Override
 public PrintWriter getLogWriter() throws SQLException {
     return null;
 }

 @Override
 public void setLogWriter(PrintWriter out) throws SQLException {

 }

 @Override
 public void setLoginTimeout(int seconds) throws SQLException {

 }

 @Override
 public int getLoginTimeout() throws SQLException {
     return 0;
 }

 @Override
 public Logger getParentLogger() throws SQLFeatureNotSupportedException {
     return null;
 }
}

版本02:

升级:版本2.0相比较于版本1.0,提升的地方在于使用close方法时,V2.0是把连接归还到连接池中,而不是释放资源。

升级实现原理:

  1. 创建MyConnection类并继承Connection接口;
  2. 创建成员变量conn和pool;
  3. 写有参构造函数,把conn和pool作为参数传入构造函数中;
  4. 因为继承了Connection接口,所以要实现方法,但这里只需要实现close()和prepareStatement(sql)方法,其余方法只需要空实现即可;这里还需要实现prepareStatement(sql)方法的原因是,放入连接池中的是MyConnection而不是Connection对象,故而当调用conn.prepareStatement(sql)方法时,如果不在MyConnection类里面实现prepareStatement(sql)方法,那么该方法就会空实现(也就是会return null),那么就会报错。
public class MyConnection implements Connection {
 //成员变量Connection(连接)
 private Connection conn;
 //成员变量(连接池,因为增强close方法时,需要把连接归还给连接池)
 private LinkedList<Connection> pool;

 //有参构造方法(把Connection对象传入,从而进行增强)
 public MyConnection(Connection conn, LinkedList<Connection> pool) {
     this.conn = conn;
     this.pool = pool;
 }

 @Override
 public void close() throws SQLException {
     //增强close方法
     pool.add(conn);
 }

 //要重写prepareStatement方法
 @Override
 public PreparedStatement prepareStatement(String sql) throws SQLException {
     return conn.prepareStatement(sql);
//        return null;
 }

//其余方法都是空实现
}

public class MyDataSource_V2 implements DataSource {
 //创建一个连接池(容器使用LinkedList)
 private static LinkedList<Connection> pool = new LinkedList<Connection>();

 //初始化连接池(往连接池里放入10个连接)
 static {
     for (int i = 0; i < 10; ++i) {
         //获取连接
         Connection conn = JDBCUtils_V3.getConnection();
         //创建MyConnection对象
         MyConnection myConnection = new MyConnection(conn, pool);
         //把连接放入连接池中
         pool.add(myConnection); //此时放入的是MyConnection对象了
         //所以,获取到的也是MyConnection对象了
     }
 }

 //这里只需要重写getConnection()方法,其余方法不重写
 @Override
 public Connection getConnection() throws SQLException {
     //获取连接之前先判断连接池里有没有连接
     if (pool.size() > 0) {
         //如果有连接,那就直接获取即可
         return pool.removeFirst();
     } else {
         //如果没有连接,那就往连接池中添加10个连接
         for (int i = 0; i < 10; ++i) {
             pool.add(new MyConnection(JDBCUtils_V3.getConnection(), pool));
         }
     }
     return pool.removeFirst();
 }


 @Override
 public Connection getConnection(String username, String password) throws SQLException {
     return null;
 }

 @Override
 public <T> T unwrap(Class<T> iface) throws SQLException {
     return null;
 }

 @Override
 public boolean isWrapperFor(Class<?> iface) throws SQLException {
     return false;
 }

 @Override
 public PrintWriter getLogWriter() throws SQLException {
     return null;
 }

 @Override
 public void setLogWriter(PrintWriter out) throws SQLException {

 }

 @Override
 public void setLoginTimeout(int seconds) throws SQLException {

 }

 @Override
 public int getLoginTimeout() throws SQLException {
     return 0;
 }

 @Override
 public Logger getParentLogger() throws SQLFeatureNotSupportedException {
     return null;
 }
}

C3P0的使用

  • 导包:
    在这里插入图片描述
  • 写配置文件:
    在这里插入图片描述
    配置文件中有两个配置,一个是默认配置(default-config),另一个是有名字的配置(named-config)。这两者的区别在于,当创建ComboPooledDataSource时,如果不传参数,那么就加载默认的配置信息;如果传入参数(就是name=“qishiyi"中的"qishiyi”),那么就根据name来加载有名字的配置信息。
  • 加载配置文件:ComboPooledDataSource ds=new ComboPooledDataSource();
    在这里插入图片描述
  • 获取连接:Connection ds.getConnection();
    在这里插入图片描述
    在这里插入图片描述

DBCP连接池

  • 导包:
    在这里插入图片描述
    在这里插入图片描述
  • 写配置文件:
    在这里插入图片描述
  • 加载配置文件:
    • 使用Properties对象加载配置信息:
      在这里插入图片描述
    • 创建DataSource:DataSource ds=BasicDataSourceFactory.createDataSource(prop);
    • 获取Connection:Connection ds.getConnection();

DBCPUtils(自己封装的)

在这里插入图片描述
在这里插入图片描述

Druid的使用

  • 导包:
    在这里插入图片描述
  • 写配置文件:
    在这里插入图片描述
  • 加载配置文件:
    在这里插入图片描述
  • 获取Connection:
    DataSource ds = DruidDataSourceFactory.createDataSource(prop);
    在这里插入图片描述
  • 小结:
    在这里插入图片描述
  • DruidUtils:
public class DruidUtils {
    private static DataSource ds;

    static {
        InputStream in = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");
        Properties prop = new Properties();
        try {
            prop.load(in);
            ds = DruidDataSourceFactory.createDataSource(prop);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }

    public static void close(Connection conn, Statement statement) throws SQLException {
        if (statement != null)
            statement.close();
        if (conn != null)
            conn.close();
    }
}

JDBCTemplate

在这里插入图片描述

  • 练习
    在这里插入图片描述
  • 代码:
public class JDBCTemplateDemo {
    /**
     * 1. 修改1号数据的 salary 为 10000
     * 2. 添加一条记录
     * 3. 删除刚才添加的记录
     * 4. 查询id为1的记录,将其封装为Map集合
     * 5. 查询所有记录,将其封装为List
     * 6. 查询所有记录,将其封装为Emp对象的List集合
     * 7. 查询总记录数
     */

    private JdbcTemplate jdbcTemplate = new JdbcTemplate(DruidUtils.getDataSource());

    //1. 修改92号数据的内容为“修改记录”
    @Test
    public void test01() {
        String sql = "update weibo set wcontent=? where wid=?";
        int update = jdbcTemplate.update(sql, "修改记录", 92);
        System.out.println(update);
    }

    //2. 添加一条记录
    @Test
    public void test02() {
        String sql = "insert into weibo values(null,?,?,?,?,?)";
        int update = jdbcTemplate.update(sql, "添加一条记录", "2021-07-28 09:21:23", "0", "0", "PC");
        System.out.println(update);
    }

    //3. 删除刚才添加的记录
    @Test
    public void test03() {
        String sql = "delete from weibo where wid=?";
        int update = jdbcTemplate.update(sql, 93);
        System.out.println(update);
    }

    //4. 查询id为92的记录,将其封装为Map集合
    @Test
    public void test04() {
        String sql = "select * from weibo where wid=?";
        //封装成Map时只能封装一条数据
        Map<String, Object> map = jdbcTemplate.queryForMap(sql, 92);
        System.out.println(map);
    }

    //5. 查询所有记录,将其封装为List
    @Test
    public void test05() {
        String sql = "select * from weibo";
        List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
        for (Map<String, Object> m : maps) {
            System.out.println(m);
        }
    }

    //6. 查询所有记录,将其封装为Emp对象的List集合
    @Test
    public void test06_01() {
        String sql = "select * from weibo";
        List<MyWeibo> list = jdbcTemplate.query(sql, new RowMapper<MyWeibo>() {
            @Override
            public MyWeibo mapRow(ResultSet rs, int i) throws SQLException {
                //封装实体(MyWeiBo)
                MyWeibo myWeibo = new MyWeibo();
                myWeibo.setWcontent(rs.getString("wcontent"));
                //封装其余剩下的

                return myWeibo;
            }
        });

        for (MyWeibo myWeibo : list)
            System.out.println(myWeibo);
    }

    @Test
    public void test06_02() {
        String sql = "select * from weibo";
        List<MyWeibo> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<MyWeibo>(MyWeibo.class));
        for (MyWeibo myWeibo : list)
            System.out.println(myWeibo);
    }

    //7. 查询总记录数
    @Test
    public void test07() {
        String sql = "select count(wid) from weibo";
        Long count = jdbcTemplate.queryForObject(sql, Long.class);
        System.out.println(count);
    }
}

JavaBean

JavaBean就是一个类,它在开发中常用于封装数据,其要求如下:
实现java.io.Serializable接口;提供成员变量(私有字段)private 数据类型 变量名;提供无参构造函数;提供get/set方法。
在这里插入图片描述

DBUtils

  • 介绍:
    commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,创建连接、结果集封装、释放资源,同时也不会影响程序的性能。因此dbutils成为很多不喜欢hibernate的公司的首选。DBUtils是Java编程中的数据库操作工具,小巧实用。DBUtils封装了对jdbc的操作,可以减少代码量
  • DBUtils的三个核心功能:
    • QueryRunner
      • 作用:提供数据库连接池,DBUtils底层自动维护连接Connection(连接的获得、释放等)。
      • 创建:new QueryRunner(DataSource ds);数据库配置信息是根据传入的连接池的配置信息而来的。
      • 方法:
        • int update(String sql,Object ... params):执行增删改,具体是根据传入的sql语句来执行的;返回影响的行数;pamams是参数,一般是创建一个Object类型的数组params,把这个数组传入。在这里插入图片描述
        • query(String sql,ResultSetHandler handler,Object ... params)
    • ResultSetHandler
      • BeanHandler:new BeanHandler<T>(T.class)把查询到的第一条数据封装到Bean对象中。
      • BeanListHandler:new BeanListHandler<T>(T.class)把查询的数据集(可以有很多条数据)封装到Bean对象中。在这里插入图片描述
      • ScalarHandler:new Scalar()它用于单数据,例如select count(*) from table_name,返回Long类型数据。在这里插入图片描述
      • ColumnListHandler:new ColumnListHandler(String columnName)把查询到的数据(可以有很多条数据)的某一个字段封装到List集合中,具体是哪一个字段要根据传入的参数columnName来决定。是没有ColumnHandler的;只有ColumnListHandler在这里插入图片描述
      • MapHandler:new MapHandler()把查询到的数据(如果查询到很多条数据就只获取第一条数据)以键值对的形式封装到Map集合中,键是字段名,值是该字段的值。在这里插入图片描述
      • MapListHandler:new MapListHandler()把查询到的数据(可以是多条数据)以键值对的形式封装到一个类型为Map<String,Object>的List集合中。也就是一个Map里面有好几个键值对,不过这一个Map只是List集合中的一个“元素”,还有其他很多的Map。在这里插入图片描述

点击全文阅读


本文链接:http://zhangshiyu.com/post/24726.html

连接  封装  方法  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1