jdbc_learn

本文介绍了Java JDBC的基础知识,包括连接参数关闭顺序、PreparedStatement的作用以及时间类型的转换。深入讲解了事务的四大特性,并展示了JDBC处理事务的代码格式。此外,还探讨了数据库连接池的原理,提到了C3P0配置和Tomcat中配置连接池的方法,以及ThreadLocal在管理连接中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、jdbc基础

1.连接参数关闭顺序:倒关

 /**
         * 关闭资源
         *      倒关
         */
        rs.close();
        statement.close();
        conn.close(); //这个必须关

2.jdbc连接时的规范化处理

   @Test
    public void fun1() throws SQLException {
        //先初始化
        Connection conn=null;
        Statement statement=null;
        ResultSet rs=null;
        try{
            String className="com.mysql.cj.jdbc.Driver";
            String uri="jdbc:mysql://localhost:3306/javaweb?serverTimezone=GMT%2B8&useSSL=true";
            String username="root";
            String password="123456";
            Class.forName(className);
            conn= DriverManager.getConnection(uri,username,password);
            statement=conn.createStatement();
            String sql="select * from stu";
            rs=statement.executeQuery(sql);
            ResultSetMetaData metaData=rs.getMetaData();
            int count=metaData.getColumnCount();
            while(rs.next()){
                for(int i=1;i<=count;i++){
                    System.out.print(rs.getString(i));
                    if(i<count)
                        System.out.print(",");
                }
                System.out.println();
            }
        }catch (Exception e){
            throw new RuntimeException(e);
        }finally {
            //一定执行,若不为null,则需要关闭
            if(rs!=null)
                rs.close();
            if(statement!=null)
                statement.close();
            if(conn!=null)
                conn.close();
        }
    }

3.获取结果集元数据
    得到元数据:rs.getMetaData(),返回值为ResultSetMetaData
    获取结果集列数:int getColumnCount()
    获取指定列的列名:String getColumnName(int colindex)

4.PreparedStatement:Statement的子接口
    防SQL攻击,提高代码的可读性,可维护性,提高效率
1.给出sql模板,所有的参数用?替代
2.调用Connnection方法,得到PrepareStatement
3.调用setString\setInt\....给参数赋值
4.调用查询方法,向数据库发送查询语句,executeQuery    

5.sql.Date和Util.Date类型的转换
    领域对象(domain)中的所有属性不能出现java.sql包下的东西,既不能使用java.sql.Date
    ResultSet->getDate中的Date是java.sql.Date()
    PreparedStatemetn->setDate(int,Date)中的Date是java.sql.Date()
时间类型的转换:
    java.util.Date->java.sql.Date\Time\TimeStamp
        将util转换成毫秒值
        再将毫秒值创建sql的Date
    java.sql.Date\Time\TimeStamp->java.util.Date
        这一步不需要处理,因为java.sql.Date是java.util.Date的子类

6.jdbc批处理

  for(int i=0;i<1000;i++){
            statement.setString(1,i+1+"");
            statement.setString(2,i+2+"");
            statement.addBatch();
        }
        long start=System.currentTimeMillis();
        statement.executeBatch();
        long end=System.currentTimeMillis();
        System.out.println(end-start);

注意:进行批处理,需要在url中设置rewriteBatchedStatements=true

二、事务

 1.事务的四大特性:
    原子性:不可再分割,要么全成功,要么全失败
    一致性:事务执行后,数据库状态与其他业务规则保持一致。如转账业务,无论事务执行成功与否,参与转账两个账户金额总额是不变的
    隔离性:隔离性是指在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰
    持久性:事务一旦成功,事务中的所有数据必须被持久化到数据库中,即使提交事务后,数据库马上奔溃,在数据库重启时,也必须能保证通过某种方式恢复数据

2. sql语言开始事务:start transaction
    结束事务:commit 和 rollback

3.在jdbc处理事务,都是通过Connection完成的!
同一事务中的所有操作,都在使用同一Connection对象!!!!

    Connection三个方法与事务相关:
        setAutoCommit(boolean)
            conn.setAutoCommit(false):表示开启事务
        commit():提交结束事务
        rollback():回滚结束事务 

4.    jdbc处理事务的代码格式:
        try{
            conn.setAutoCommit(false);//开启事务
            ......
            ......
            conn.commit();//执行事务
        }catch(){
            conn.rollback();//回滚事务
        }

注意:使用同一Connection对象!!!!

5.事务的并发读问题:
    脏读:读取到另一个事务未提交数据

三、数据库连接池

连接池也是使用四大连接参数来完成创建连接对象
 1.连接池必须实现:javax.sql.DataSource接口
    
连接池返回的Connection对象,它的close方法与众不同,调用它的close不是关闭,而是把连接归还给池

2.    创建连接池对象---> 配置四大参数---> 配置池参数 ---> 得到连接对象

3.    连接池内部使用了四大参数创建了对象,即mysql驱动提供的Connection
    连接池使用了mysql的连接对象进行了装饰,只对close方法进行了增强
    装饰之后的Connection的close方法,用来把当前连接归还给池

附:装饰者模式(见OneNote笔记)

4.C3P0配置文件(开源免费的连接池)
(1)导入:c3p0-jar 和 mchange-commons-java
(2)配置文件要求:
    文件名称:必须叫c3p0-config.xml
    文件位置:必须在src下

<?xml version="1.0" encoding="UTF-8" ?>
<c3p0-config>
    <default-config>
        <!--四大配置参数-->
        <property name="jdbcUrl"><![CDATA[jdbc:mysql://localhost:3306/javaweb?serverTimezone=GMT%2B8&useSSL=true]]></property>
        <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
        <property name="user">root</property>
        <property name="password">123456</property>
        <!--池参数配置-->
        <property name="initialPoolSize">10</property>
        <property name="acquireIncrement">3</property>
        <property name="maxPoolSize">10</property>
        <property name="minPoolSize">2</property>

    </default-config>
</c3p0-config>

(3)JdbcUtil.java如下(装饰者模式):

package C3P0;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class JdbcUtils {
    //配置文件的默认配置,要求你必须给出c3p0-config.xml!!!!
    private static ComboPooledDataSource dataSource=new ComboPooledDataSource();
    /**
     * 使用连接池返回一个连接对象
     * @return
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
    /**
     * 返回连接池
     * @return
     */
    public static DataSource getDataSource(){
        return dataSource;
    }

5.Commons DbUtils 1.7 jar包

导入 Commons DbUtils 1.7 jar包,简易操作数据库
其中方法的实现是依靠反射机制实现的

增删改操作:
        1.创建QueryRunner,需要提供数据库连接池对象(即可使用以上c3p0其配置)
            QueryRunner qr=new QueryRunner(JdbcUtils.getDataSource());
        2.给出sql
            String sql="insert into user values(?,?)";
        3.给出参数数组
            Object [] params={"大佬","666666"};
        4.传入sql和参数数组,执行增删改操作
            qr.update(sql,params);
   查询操作:
        1.创建QueryRunner,需要提供数据库连接池对象
            QueryRunner qr=new QueryRunner(JdbcUtils.getDataSource());
        2.给出sql
            String sql="select * from user where username=?";
        3.执行query()方法,需要给出结果集处理器,即ResultSetHandler的实现类对象
          我们要给出的是BeanHandler,它实现了ResultSetHandler
          它需要一个类型,它会把rs中数据封装到指定类型的javabean对象中,然后返回到javabean中
          注意:此对象需要数据库的属性的对象的属性及名称完全一致
            User user=qr.query(sql,new BeanHandler<User>(User.class),"大佬");
            System.out.println(user); 

附:dbUtils其他方法,见OneNote

6.tomcat配置连接池
    jndi作用:


    tomcat配置jndi资源
    1.在tomcat的conf文件夹下的context.xml配置文件中加入:

              <Resource name="jndi/learn"   
                auth="Container"   
                type="javax.sql.DataSource"   
                driverClassName="com.mysql.cj.jdbc.Driver"   
                url="jdbc:mysql://localhost:3306/javaweb?serverTimezone=GMT%2B8&amp;useSSL=true"   
                username="root"   
                password="123456"   
                  />

        2.在项目的web.xml中加入资源引用:

            <resource-ref>
                <description>JNDI DataSource</description>
                <res-ref-name>jndi/learn</res-ref-name>
                <res-type>javax.sql.DataSource</res-type>
                <res-auth>Container</res-auth>
            </resource-ref>

     注意:其中res-ref-name值要和context.xml的name值一致。
        

7.ThreadLocal
ThreadLocal通常用在一个类的成员上
多个线程访问它时,每个线程都有它的副本,互不干扰!
Spring中把Connection放到了ThreadLoacal中!(后期继续改进JdbcUtils)

@Test
    public void fun1(){
        ThreadLocal<String> threadLocal=new ThreadLocal<String>();
        threadLocal.set("hello");
        new Thread(){
            public void run(){
                System.out.println(threadLocal.get());
            }
        }.start();
        threadLocal.remove();
    }

其输出结果为:null,即利用ThreadLocal不同线程资源互不干扰。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值