JDBC优化

目录

JDBC优化

1.元数据

2.ORM 对象关系映射(Object Relational Mapping)

3.DAO 数据库访问对象(DataAccess Object) 

BeanUtils组件

DBUtils组件

数据库连接池

DBCP连接池:

C3P0连接池:

分页技术


JDBC优化


1.元数据

在jdbc中获取数据库的定义,例如:数据库、表、列的定义信息。就用到元数据。
 在jdbc中可以获取: 数据库元数据参数元数据结果集元数据(元数据定义相关api: . . .MetaData)

// 首先获取连接
Connection conn = JdbcUtil.getConnection();
--------------------------------------------------------------------------
// 1.数据库元数据   (-----通过连接,获取数据库信息-----)
DatabaseMetaData metaData = conn.getMetaData();
        metaData.getURL():返回一个String类对象,代表数据库的URL。
        metaData.getUserName():返回连接当前数据库管理系统的用户名。
        metaData.getDatabaseProductName():返回数据库的产品名称。
        metaData.getDatabaseProductVersion():返回数据库的版本号。
        metaData.getDriverName():返回驱动驱动程序的名称。
        metaData.getDriverVersion():返回驱动程序的版本号。
        metaData.isReadOnly():返回一个boolean值,指示数据库是否只允许读操作。
--------------------------------------------------------------------------
String sql = "select * from dept where deptid=? and deptName=?";
PreparedStatement pstmt = conn.prepareStatement(sql);
//2. 参数元数据   (-----通过预编译sql语句,获取它的参数个数与类型-----)
ParameterMetaData p_metaDate = pstmt.getParameterMetaData();
        p_metaDate.getParameterCount() :获得指定参数的个数
        p_metaDate.getParameterType(int param) :获得指定参数的sql类型
--------------------------------------------------------------------------
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
// 3.得到结果集元数据   (-----通过rs结果集元数据,得到列的名称-----)
ResultSetMetaData rs_metaData = rs.getMetaData();
    while (rs.next()) {
        int count = rs_metaData.getColumnCount(): 返回resultset对象的列数
        for (int i=0; i<count; i++) {
            String columnName = rs_metaData.getColumnName(int column): 获得指定列的名称
            rs_metaData.getColumnTypeName(int column):获得指定列的类型
            //根据列名称获取值
            rs.getObject(columnName);
        }
    }

2.ORM 对象关系映射(Object Relational Mapping)

思路:一个对象,对应数据库里的一条记录     

设计:按照这个思路设计一些方法,封装数据库操作,对外提供可操作的对象

结果:不需要理解数据库操作,只调用对象方法

通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。

常用O-R Mapping映射工具:

Hibernate

Ibatis

Commons DBUtils(只是对JDBC简单封装)


3.DAO 数据库访问对象(DataAccess Object) 

运用了ORM中的思路,把数据库相关的操作都封装在这个类里面,其他地方看不到JDBC的代码

//数据库=DAO对象
//数据库操作=DAO对象方法
public interface DAO{
    //增加
    public void add(Hero hero);
    //修改
    public void update(Hero hero);
    //删除
    public void delete(int id);
    //获取
    public Hero get(int id);
    //查询
    public List<Hero> list();
    //分页查询
    public List<Hero> list(int start, int count);
}
//具体实现数据库对象操作
public class HeroDAO implements DAO{
    //加载数据库驱动
    public HeroDAO() {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    //获取数据库连接
    public Connection getConnection() throws SQLException {
        return DriverManager.getConnection("url地址", "用户名","密码");
    }
    //add方法实现
    public void add(Hero hero) {
        String sql = "insert into hero values(null,?,?,?)";
        try (Connection c = getConnection(); PreparedStatement ps = c.prepareStatement(sql);) {
            ps.setString(1, hero.name);
            ps.setFloat(2, hero.hp);
            ps.setInt(3, hero.damage);
              ps.execute();
              ResultSet rs = ps.getGeneratedKeys();
            if (rs.next()) {
                int id = rs.getInt(1);
                hero.id = id;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    ......实现其他方法
}

 


BeanUtils组件

程序中对javabean的操作很频繁, 所以apache提供了一套开源的api,方便对javabean的操作。即BeanUtils组件:作用是简化javabean的操作

使用BenUtils组件:

  1. 引入commons-beanutils-1.8.3.jar核心包
  2. 引入日志支持包: commons-logging-1.1.3.jar

注:缺少日志jar文件,报错:java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory

基本用法:

1. 对象属性的拷贝,赋值给javabean(反射原理)

BeanUtils.copyProperty(bean, "name", value);

BeanUtils.setProperty(bean, "age", value);

2. 对象的拷贝

BeanUtils.copyProperties(newAdmin, admin);

3. map数据拷贝到javabean中 (注意:map的key要与javabean的属性名称一致。不一致不会报错,值为0)

BeanUtils.populate(bean, map);

4.日期类型的拷贝:

注意:对于基本数据类型,会自动进行类型转换,但日期类型则需要注册日期类型转换器,

1.自定义日期类型转换器
ConvertUtils.register(new Converter() {
            // 转换的内部实现方法,需要重写
            @Override
            public Object convert(Class type, Object value) {
                // 判断null与空字符串
                if (type != Date.class) {
                    returnnull;
                }
                if (value ==null || "".equals(value.toString().trim())) {
                    returnnull;
                }
                try {
                    // 字符串转换为日期
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                    return sdf.parse(value.toString());
                } catch (ParseException e) {
                    thrownew RuntimeException(e);
                }
            }
        },Date.class);

2.使用提供的日期类型转换器工具类
//注意:不能判断空字符串
ConvertUtils.register(newDateLocaleConverter(), Date.class);

 


DBUtils组件

commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。
作用:DbUtils组件能简化jdbc操作
下载组件,引入jar文件 : commons-dbutils-1.6.jar

主要类方法:

|-- DbUtils 关闭资源、加载驱动
|-- QueryRunner 组件的核心工具类:定义了所有的与数据库操作的方法(查询、更新)

Int update(Connection conn, String sql, Object param);      执行更新带一个占位符的sql

Int update(Connection conn, String sql, Object… param);      执行更新带多个占位符的sql

Int[] batch(Connection conn, String sql, Object[][] params)      批处理

T query(Connection conn ,String sql,  ResultSetHandler<T> rsh,  Object... params)      查询方法

注意: 如果调用DbUtils组件的操作数据库方法没有传入连接对象,那么在实例化QueryRunner对象的时候需要传入数据源对象: QueryRunner qr = new QueryRunner(ds);

Int update( String sql, Object param);

Int update( String sql, Object… param);

Int[] batch( String sql, Object[][] params)

|-- 封装结果的一些对象:

1)BeanHandler: 查询返回单个对象

2)BeanListHandler: 查询返回list集合,集合元素是指定的对象

3) ArrayHandler, 查询返回结果记录的第一行,封装对对象数组, 即返回:Object[]

4) ArrayListHandler, 把查询的每一行都封装为对象数组,再添加到list集合中

5) ScalarHandler 查询返回结果记录的第一行的第一列 (在聚合函数统计的时候用)

6) MapHandler 查询返回结果的第一条记录封装为map


数据库连接池

原因: 连接资源宝贵,一个数据库同时支持的连接总数是有限的,如果多线程并发量很大,那么数据库连接的总数就会被消耗光,后续线程发起的数据库连接就会失败。

操作一次数据库= 创建连接, 执行操作, 关闭连接.  (每个线程都会创建一次连接, 执行完后关闭)

思路:预先创建一组连接,用的时候每次取出一个,用完后放回,不断的循环使用不关闭连接
 

连接池Connection集合

全局参数:初始化连接数目,最大连接数,当前连接数,连接池集合。

构造方法:创建初始化数目的连接

获取连接:if(有连接){ 直接拿连接} else无连接{ if(达到最大连接数){ 抛出异常} else没达到{ 创建新连接 }}

释放连接:if(池中数目小于初始化数目){放入池中} else {关闭连接}

 

扩展:使用动态代理监测接口中方法,使用代理,可以在不实现接口的情况,对接口的方法进行扩展,添加额外的用户需要的业务逻辑!

对Connection对象,生成一个代理对象:
|--Proxy
    static Object newProxyInstance(
            ClassLoader loader,        //当前使用的类加载器
            Class<?>[] interfaces,         //目标对象(Connection)实现的接口类型    
            InvocationHandler h     //事件处理器:当执行上面接口中的方法的时候,就会自动触发事件处理器代码,把当前执行的方法(method)作为参数传入。
    )
例:执行close方法时把连接放入连接池


Sun公司约定: 如果是连接池技术,需要实现一个接口!:javax.sql.DataSource;

连接池:

DBCP

C3P0


DBCP连接池:

DBCP 是 Apache 软件基金组织下的开源连接池实现,Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。

使用DBCP数据源,应用程序应在系统中增加如下两个 jar 文件:

  1. Commons-dbcp.jar:连接池的实现
  2. Commons-pool.jar:连接池实现的依赖库

核心类:BasicDataSource

 

使用步骤:引入jar文件

1. 硬编码方式实现连接池

// DBCP连接池核心类
        BasicDataSource dataSouce = new BasicDataSource();
// 连接池参数配置:初始化连接数、最大连接数 / 连接字符串、驱动、用户、密码
        dataSouce.setUrl("jdbc:mysql:///jdbc_demo");	//数据库连接字符串
        dataSouce.setDriverClassName("com.mysql.jdbc.Driver"); //数据库驱动
        dataSouce.setUsername("root");	//数据库连接用户
        dataSouce.setPassword("root"); //数据库连接密码
        dataSouce.setInitialSize(3); // 初始化连接
        dataSouce.setMaxActive(6);	// 最大连接
        dataSouce.setMaxIdle(3000); // 最大空闲时间
// 获取连接
        Connection con = dataSouce.getConnection();
        con.prepareStatement("delete from admin where id=3").executeUpdate();
// 关闭
        con.close();

2. 配置方式(properties)实现连接池,便于维护【推荐】

配置文件db.properties中的key与BaseDataSouce中的属性一样

        url=jdbc:mysql:///jdbc_demo
        driverClassName=com.mysql.jdbc.Driver
        username=root
        password=123456
        initialSize=3
        maxActive=6
        maxIdle=3000

 

// 加载prop配置文件
        Properties prop = new Properties();
// 获取文件流
        InputStream inStream = App_DBCP.class.getResourceAsStream("db.properties");
// 加载属性配置文件
        prop.load(inStream);
// 根据prop配置,直接创建数据源对象
        DataSource dataSouce = BasicDataSourceFactory.createDataSource(prop);
// 获取连接
        Connection con = dataSouce.getConnection();
        con.prepareStatement("delete from admin where id=4").executeUpdate();
// 关闭
        con.close();

 


C3P0连接池:

最常用的连接池技术!Spring框架,默认支持C3P0连接池技术!

jar文件: c3p0-0.9.1.2.jar

核心类:CombopooledDataSource ds;


使用步骤:引入jar

1.硬编码方式

// 创建连接池核心工具类
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 设置连接参数:url、驱动、用户密码、初始连接数、最大连接数
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/jdbc_demo");
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setUser("root");
        dataSource.setPassword("root");
        dataSource.setInitialPoolSize(3);
        dataSource.setMaxPoolSize(6);
        dataSource.setMaxIdleTime(1000);
// ---> 从连接池对象中,获取连接对象
        Connection con = dataSource.getConnection();
// 执行更新
        con.prepareStatement("delete from admin where id=7").executeUpdate();
// 关闭
        con.close();

2.配置方式(xml)

// 创建c3p0连接池核心工具类。自动加载src下c3p0的配置文件【c3p0-config.xml】
        ComboPooledDataSource dataSource = new ComboPooledDataSource();// 不指定参数使用默认的配置
// 获取连接
        Connection con = dataSource.getConnection();
// 执行更新
        con.prepareStatement("delete from admin where id=5").executeUpdate();
// 关闭
        con.close();

 

 


分页技术

JSP页面用来显示数据,如果数据有1000条,分页显示,每页显示10条,共100页;   好处: 利于页面布局,且显示的效率高!

分页关键点

  1. 分页SQL语句;
  2. 后台处理: dao -> service -> servlet -> JSP

1.SQL语句:SELECT * FROM  表  LIMIT   从第几行起,   返回几行 ;       (当前页-1)*每页显示多少条, 每页显示多少条

 

2.后台处理

环境准备:引入jar文件及引入配置文件

i. 数据库驱动包

ii. C3P0连接池jar文件 及 配置文件

iii. DbUtis组件: QueryRunner qr = new QueryRuner(dataSouce);
                         qr.update(sql);

公用类: JdbcUtils.java

1. 先设计:分页javabean:
public class PageBean{
    private int currentPage; //当前页
    private int pageCount; // 查询返回的行数
    private int totalCount; // 总记录数
    private int totalPage; // 总页数
    private List pageData; // 分页查询到的数据
}

2. Dao接口设计/实现: 2个方法(分页查询数据,查询总记录数)

3. Service/servlet

4. JSP

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值