jdbc

前言

调用数据库需要下载对应数据库的驱动

建议把参数写到properties中

JDBC编程六大步骤

1.注册驱动(连接对应品牌的数据库)

2.获取连接(表示JVM的进程和数据库进程之间的通道打开,使用完后一定要关闭)

3.获取数据库操作对象(专门执行sql语句的对象)

4.执行sql语句(DQL,DML…)

5.处理查询结果集(只有当第四步执行的是select语句时才有这一步)

6.释放资源(使用完资源之后一定要关闭资源)

1.注册驱动

DriverManager类的registerDriver(Driver driver)注册所需驱动

Driver driver = new com.mysql.cj.jdbc.Driver();
DriverManager.registerDriver(driver);

常用方式

Class.forName(“com.mysql.cj.jdbc.Driver”);加载这个类来运行静态代码块实现驱动的注册

常用原因:参数是一个字符串,字符串可以写到properties中

2.获取连接

DriverManager类的getConnection(String url, String root, String password)获取到与数据库连接的Connection类

Connection con = null;
con=DriverManager.getConnection("jdbc:mysql://localhost:3306/spj?useSSL=false&serverTimezone=UTC","root","25666524qq");

3.创建可执行sql语句的对象

通过连接connection对象的creatStatement()创建可执行sql语句对象

存在问题:1.存在SQL注入问题 2.存在拼串操作,较为繁琐

Statement statement = null;
statement=con.createStatement();//创建对象

PreparedStatement类

//预编译sql语句,返回PrepareStatement实例
String sql = "update s set STATUS=? where CITY=?";
statement = conn.prepareStatement(sql);
//填充占位符
statement.setObject(1, 10);
statement.setObject(2,"顺德");
//执行
statement.execute();

与Statement相比的好处:

1.解决了拼接字符串的繁琐操作,使用了占位符

2.解决了SQL注入问题,使用了预编译

3.由于使用占位符,所以PreparedStatement可操作Blob数据

4.提高了批处理的效率

1.处理Blob数据

上传

用FileInputStream载入图片,再通过PreparedStatement的setBlob(int index, InputStream is);来设置占位符

下载

通过查询获取的结果集ResultSet,用InputStream来接收ResultSet的getBinaryStream()从而得到输入流,再通过OutputStream输出流来输出就可得到Blob数据即图片等非文本资源

2.批处理

在获取连接设置url时要加入rewriteBatchedStatements = true,开启数据库的批处理

其次关闭连接的自动提交即setAutocommit (false)

然后通过addBatch()添加命令

添加到一定程度后executeBatch()执行批处理

然后clearBatch()清空为了接收下一批任务

最后全部完成了才提交即Connection的commit()

4.执行sql语句

使用String sql=" …"传递sql语句到数据库并执行返回结果

jdbc中的sql语句不能有分号

statement对象中executeUpdate(sql)专门执行DML语句(insert delete update) 返回值为受影响的数据库中记录条数

插入

insert into …

删除

delete

更新

update

-------

statement对象中executeQuery(sql)专门执行DQL语句(select)返回值为查询结果集

查询

select

5.处理查询结果集

getString()方法的特点是:不管数据库中数据类型是什么,都以String形式返回;下标都是从1开始

getString(String Label_Name)通过列名称获取数据,不是表中列名称是查询结果集的列名称

还有getInt()、getDouble()

ResultSetMetaData rsmd = set.getMetaData();

通过ResultSetMetaData 获取元数据来获取列数

通过反射给对象赋值

ResultSetMetaData rsmd = set.getMetaData();
while(set.next()){
Factory factory = new Factory();
for(int i=0;i<rsmd.getColumnCount();i++){
    Object colValue = set.getObject(i+1);
    try {
        Field field = Factory.class.getDeclaredField(rsmd.getColumnLabel(i+1));
        field.setAccessible(true);
        field.set(factory,colValue);
    } catch (NoSuchFieldException | IllegalAccessException e) {
        e.printStackTrace();
    }
}
    System.out.println(factory);
}

6.释放资源

先释放ResultSet再释放statement最后释放connection

7.使用ResourceBundle类调用propreties文件(重点)

使用ResourceBundle类的getBundle(String basename)来实现调用,通过getString(String key)来获取所需数据

8.代码

public void JDBCTest(){
    Connection con = null;
    Statement statement = null;
    ResultSet set = null;
    try {
        //获取属性值
        ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
        String driver = bundle.getString("Driver_Name");
        String url = bundle.getString("url");
        String user = bundle.getString("user");
        String password = bundle.getString("password");


        //1.注册驱动(反射)
        Class.forName(driver);

        //2.获取连接
        con = DriverManager.getConnection(url, user, password);

        //3.创建可执行sql语句对象(statement)
        statement = con.createStatement();

        //4.执行sql语句
        String sql = "select * from s";
        set = statement.executeQuery(sql);

        //5.处理查询结果集
        while(set.next()){
            System.out.println(set.getString(1)+"|"+set.getString(2)+"|"+set.getString(3)+"|"+set.getString(4));
        }



    } catch (SQLException | ClassNotFoundException e) {
        e.printStackTrace();
    }finally {//6.关闭资源(先关statement再关connection)
        if(set!=null){
            try {
                set.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(statement!=null){
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(con!=null){
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }
}

9.封装性

使用类的静态方法返回连接connection

使用方法关闭资源public void closeResource(Connection conn, Statement statement)

10.ORM封装思想

ORM: object relational mapping

一个数据表对应一个java类

表中的一条记录对应java类的一个对象

表中的一个字段对应java类的一个属性

public class Factory{
    private String SNO;
    private String SNAME;
    private String STATUS;
    private String CITY;

    public Factory() {
        super();
    }

    public Factory(String SNO, String SNAME, String STATUS, String CITY) {
        this.SNO = SNO;
        this.SNAME = SNAME;
        this.STATUS = STATUS;
        this.CITY = CITY;
    }

    public String getSNO() {
        return SNO;
    }

    public void setSNO(String SNO) {
        this.SNO = SNO;
    }

    public String getSNAME() {
        return SNAME;
    }

    public void setSNAME(String SNAME) {
        this.SNAME = SNAME;
    }

    public String getSTATUS() {
        return STATUS;
    }

    public void setSTATUS(String STATUS) {
        this.STATUS = STATUS;
    }

    public String getCITY() {
        return CITY;
    }

    public void setCITY(String CITY) {
        this.CITY = CITY;
    }

    @Override
    public String toString() {
        return "Factory{" +
                "SNO='" + SNO + '\'' +
                ", SNAME='" + SNAME + '\'' +
                ", STATUS='" + STATUS + '\'' +
                ", CITY='" + CITY + '\'' +
                '}';
    }
}
set = statement.executeQuery();
while(set.next()){
    String sno = set.getString(1);
    String sname = set.getString(2);
    String status = set.getString(3);
    String city = set.getString(4);
    Factory factory = new Factory(sno, sname, status, city);
    System.out.println(factory);
}

11.事务

**事务:**一组逻辑操作单元使数据从一种状态变换到另一种状态

**事务处理:**保证所有事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式,当在一个事务中执行多个操作时,要么所有的事务都被提交commit;要么放弃所有的修改,整个事务回滚rollback到上一次提交的状态。

哪些操作会导致自动提交

1.DDL(creat\alter\drop)(无法通过setAutocommit = false来取消)

2.DML 可通过设置setAutocommit = false来取消自动提交

3.关闭连接

为了避免自动提交,一般处理事务的连接由外部自行提供、关闭

由于考虑到数据库连接池,需要先将连接状态设置为默认即自动提交打开,再关闭连接

ACID属性

1.原子性

事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生

2.一致性

事务必须使数据库从一个一致性状态变换到另一个一致性状态

3.隔离性

一个事务的执行不能被其他事务干扰

4.持久性

一个事务一旦被提交,它对数据库中的改变都是永久的

并发问题

脏读:两个事务A、B,A读取了已经被B更新但还没被提交的字段,若B回滚,A读取的内容就是临时且无效的;

不可重复读:对于两个事务A、B,A读取一个字段然后B更新了该字段,然后A再次读取同一字段值就不同了

幻读:对于两个事务A、B,A从一个表中读取一个字段,然后B在该表中插入一些新的行,之后,A再次读取同一个表就会多出几行

四种隔离级别

1.读取未提交数据

2.读取已提交事务

3.可重复读(锁操作行)

4.串行化(锁操作表)

12.连接池Druid

1.导jar包

2.设置properties配置文件

3.读取properties获取所需参数

4.通过DruidDataSourceFactory.createDataSource(properties)创建DruidDataSource类

5.通过getConnection()获取一个连接,最后将连接参数调为默认后close()

13.(commons-dbutils)开源的JDBC工具类库

使用QueryRunner类

关于不同的返回结果使用的handler:MapHandler、MapListHandler、BeanHandler

特殊值的需求如最大值或个数:ScalarHandler

自定义handler:ResultSetHandler<>{}

关闭资源

使用dbutils.jar包中的DbUtils.close(…)比如connection、Statement、ResultSet

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值