数据库操作之Jdbc下

2017-02-14  本文已影响0人  joshul
1.事务
1.1事务的四大特性(ACID)
1.2mysql中操作事务

在控制台中输入语句:start transaction;即开始事务。

在控制台中输入语句:commit transaction;即提交事务。

在控制台中输入语句:rollback;回滚事务,即在此事务中执行的操作全部无效,数据库回到start transaction;之前(前提是使用该语法前没有执行commit transaction;操作)。

1.3Jdbc中操作事务

在Jdbc中处理事务都是通过Connection对象完成的,同一事务中的所有操作,都在使用同一个Connection对象。

setAutoCommit(boolean);设置是否自动提交事务,如果为true表示自动提交(默认值就是true),也就是每条执行的sql语句都是一个单独的事务,如果设置false,那么就相当于开启了事务了。con.setAutoCommit(false);语句表示开启事务。

con.commit();提交并结束事务。

con.rollback();回滚事务。

2.事务的隔离级别
2.1事务的并发读问题
2.2四大隔离级别(防止上述问题)
2.3查看mysql的隔离级别

在控制台中输入语句:select @@tx_isolation;

也可以通过下面命令来设置隔离级别:set transaction isolationlevel[4选1];

2.4在Jdbc中设置隔离级别

con.setTransactionisolation[int lever];

3.数据库连接池

用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出、拓机。如下图所示:

Paste_Image.png

数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现的尤为突出.。对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标。数据库连接池正式针对这个问题提出来的。数据库连接池负责分配,管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。如下图所示:

Paste_Image.png

数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中, 这些数据库连接的数量是由最小数据库连接数来设定的.无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量.连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中
数据库连接池的最小连接数和最大连接数的设置要考虑到以下几个因素:

3.1池参数(所有池参数都有默认值)

设置初始化大小:connection.setInitialSize();
设置最小空闲连接数:connection.setMinIdle();
设置最大空闲连接数:connection.setMaxIdle();
设置最小连接数:connection.setMinActive();
设置最大连接数:connection.setMaxActive();
设置增量:一次创建的最小单位。
设置最大的等待时间:connection.setMaxWait();

3.2四大连接参数

连接池也是使用Jdbc中的四大连接参数和驱动jar包来完成创建连接对象。

3.3实现的接口

连接池必须实现javax.sql.DataSource接口。

从连接池返回的Connection对象,它的close()方法与众不同。调用它的close()方法不是关闭,而是把连接归还给池。

3.4DBCP数据库连接池

DBCP是Apache软件基金组织下的开源连接池实现,要使用DBCP数据源,需要应用程序应在系统中增加如下两个jar文件:

public class Demo{
    public static void main(String[] args)
    {
        /*
         *1.创建连接池对象
         *2.配置四大参数
         *3.配置池参数
         *4.得到连接对象
         */
        BasicDataSource dataSource=new BasicDataSource();
        
        dataSource.setDriverClassName(“com.mysql.jdbc.Driver”);
        dataSource.setUrl(“jdbc:mysql://localhost:3306/mydb”);
        dataSource.setUsername(“root”);
        dataSource.setPassword(123);
        
        dataSource.setMaxActive(20);
        dataSource.setMinIdle(3);
        dataSource.setMaxWait(1000);
        
        Connection con=dataSource.getConnection();
        System.out.println(con);
        
      /*
        *连接池内部使用四大参数创建了连接对象,即mysql驱动提供的Connection
        *连接池使用mysql的连接对象进行了装饰,只对close()方法进行了增强!
        *装饰之后的Connection的close()方法,用来把当前连接归还给池
        */
        con.close();//把连接归还给池。
    }
}

既然谈到装饰,那下面我们就在下文3.7中来谈谈装饰者模式。

3.5c3p0数据库连接池

c3p0,全名叫ComboPooledDataSource;

需要导入的jar包:

连接池的实现:c3p0-0.9.5.2.jar
依赖库:mchange-commons.jar

public class Demo{
    public static void main(String[] args)
    {
        //创建连接池对象
        ComboPooledDataSource dataSource=new ComboPooledDataSource();
        
        //进行四大参数的配置
        dataSource.setDriverClass(“com.mysql.jdbc.Driver”);
        dataSource.setJdbcUrl(“jdbc:mysql://localhost:3306/mydb”);
        dataSource.setUser("root");
        dataSource.setPassword("123");
        
        //池配置
        dataSource.setAcquireIncrement(5);
        dataSource.setInitialPoolSize(20);
        dataSource.setMinPoolSize(2);
        dataSource.setMaxPoolSize(50);
        
        Connection con=dataSource.getConnection();
        System.out.println(con);
        
        con.close();
    }
}
3.5.1c3p0配置文件的使用

配置文件要求:

文件名称:必须叫c3p0-config.xml。
文件的位置:必须在src下。

c3p0配置文件:


Paste_Image.png

写入配置文件后的Demo:

public class Demo{
    public static void main(String[] args)
    {
        //在创建连接池对象时,这个对象就会自动加载配置文件,不用我们来指定。
        ComboPooledDataSource data=new comboPooledDataSource();
        Connection con=data.getConnection();
        System.out.println(con);
    }
}

3.7装饰者模式
将对象增强的手段有:

下面通过一个简单的例子来对装饰者模式进行讲解

class 咖啡类 {};
class 加奶咖啡 extends 咖啡类 {};
class 加糖咖啡 extends 咖啡类 {};
class 加盐咖啡 extends 咖啡类 {};

咖啡 a=new 加糖咖啡();
咖啡 b=new 加盐咖啡(a);//对a进行装饰,就是给a加盐
咖啡 c=new 加奶咖啡(b);//对b进行装饰,就是给b加奶

装饰者模式在Java API中的IO流中用到的很多。如BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter、ObjectInputStream、ObjectOutputStream这几个都是运用了装饰模式的装饰流。

4.ThreadLocal

早在JDK 1.2的版本中就提供Java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。

4.1Thread API
4.2ThreadLocal内部结构

ThreadLocal内部用Map来保存数据。虽然在使用上述API时没有给出键,但其实它内部使用了当前线程作为键。内部结构见下面demo:

class ThreadLocal
{
    private Map<Thread,T> map=new HashMap<Thread,T>();
    
    public void set(T value){
    
        map.put(Thread.currentThread(),value);
    }
    
    public void remove(){
        map.remove(Thread.currentThread());
    }
    
    public T get(){
        return map.get(Thread.currentThread());
    }
}
5.dbtils结果集处理器介绍

需要导入的jar包:

关键要得到QueryRunner对象,然后调用其各种方法。

update()方法:

query()方法:

ResultSetHandler接口

dbutil结果处理集原理代码:

package demo;
    import javax.sql.DataSource;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    /**
     * Created by codingBoy on 16/10/19.
     */
     public class QR<T>
     {
        private DataSource dataSource;

    public QR(DataSource dataSource)
    {
        this.dataSource=dataSource;
    }

    public QR(){
        super();
    }

    public int update(String sql,Object... params)
    {
        Connection con=null;
        PreparedStatement pstmt=null;

        try
        {
            con=dataSource.getConnection();//通过连接池得到连接对象
            pstmt=con.prepareStatement(sql);

            initParams(pstmt,params);//给出参数

            return pstmt.executeUpdate();//调用update执行增、删、该
        }catch (Exception e)
        {
            throw new RuntimeException(e);
        }finally {
            try{
                if (pstmt!=null) pstmt.close();
                if (con!=null) con.close();
            }catch (SQLException e){}
        }
    }

    //给参数赋值
    public void initParams(PreparedStatement pstmt,Object... params) throws SQLException {
        for (int i = 0; i < params.length; i++)
        {
            pstmt.setObject(i+1,params[i]);
        }
    }

    public T query(String sql,RsHandler<T> rh,Object... params) throws SQLException {
        Connection con=null;
        PreparedStatement pstmt=null;
        ResultSet rs=null;

        try
        {
            con=dataSource.getConnection();//通过连接池得到连接对象
            pstmt=con.prepareStatement(sql);

            initParams(pstmt,params);//给出参数

            rs=pstmt.executeQuery();//调用update执行增、删、该

            return rh.handle(rs);
        }catch (Exception e)
        {
            throw new RuntimeException(e);
        }finally {
            
            if (rs!=null) rs.close();
            if (pstmt!=null) pstmt.close();
            if (con!=null) con.close();

        }
    }

    interface RsHandler<T>
    {
        public T handle(ResultSet rs);
    }
    }

这样我们以后对数据库进行增、删、改操作时,只需写以下代码即可:

    1.QueryRunner qr=new QueryRunner(JdbcUtils.getDataSource);//创建QueryRunner对象,并传入连接池对象
    
    2.String sql="insert into user values(?,?,?,?);//给出sql语句模板
    3.Object[] params={参数1,参数2,参数3,参数4};//传入参数
    4.qr.update(sql,params);//调用qr方法。

通过这简单的四步就可以对数据库进行增删改了。
对数据库进行查询操作时,只需写以下代码:

1.QueryRunner qr=new QueryRunner(JdbcUtils.getDataSource);//创建QueryRunner对象,并传入连接池对象
2.String sql="select * from user where id=?";//给出sql语句模板
3. Object[] params={参数};//传入参数
//4. ResultSetHandler<Object> rsh=new ResultSetHandler(){
//      @Override
//      public Object handle(Result rs) throws SQLException{
//          return null;
//      }
//  };
5.Object object=qr.query(sql,new BeanHandler<Object>(Object.class),params);
上一篇下一篇

猜你喜欢

热点阅读