回顾总结21

发布时间:2022-07-05 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了回顾总结21脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

JDBC

JDBC(java.SQL和javax.sql)是为了访问不同的数据库提供了统一的接口(JDBC API),这些接口统一和规范了应用程序与数据库的连接,执行SQL语句,并得到返回结果等各类操作,为使用者屏蔽了细节问题。

Java程序员使用JDBC,可以连接任何提供了JDBC驱动程序的数据库系统,从而完成对数据库的各种操作。

Java可以不直接连接数据库,只提供一个接口,接口里面有一系列的方法让数据库层面去实现,从而获得实现该接口的类。而我们就可以使用这些类来操作相应的数据库

JDBC连接数据库

方式一:

//JDBC编写步骤
//1.注册驱动
Driver driver = new Driver();
//2.获取连接
String url = "jdbc:MySQL://localhost:3306/db02";
//将 数据库的用户名和密码放入到PRoPErties对象
Properties properties = new Properties();
properties.setProperty("user","root");
properties.setProperty("password","1347");
//获取连接
Connection connect = driver.connect(url,properties);
//3.执行SQL
String sql = "insert into actor values(null,'刘德华','男','1970-11-11','788787')";
statement statement = connect.createstatement();
//statement用于执行静态sql语句并返回生成结果的信息
int rows = statement.executeUpdate(sql);
System.out.println(rows > 0 ? "成功" : "失败" );
//4.关闭连接
statement.close();
connect.close();

方式二:

//通过反射加载Driver类,动态加载,更加的灵活,减少依赖性
Class<?> aClass = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver)aClass.newInstance();

方式三:

//使用DriverManager来管理Driver,有更好的扩展性
//1.先获取一个Driver对象
Class<?> aClass = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver)aClass.newInstance();
//2.注册Driver
DriverManager.registerDriver(driver);
//3.得到url和配置文件
String url = "jdbc:mysql://localhost:3306/db02";
//4.将 数据库的用户名和密码放入到Properties对象
Properties properties = new Properties();
properties.setProperty("user","root");
properties.setProperty("password","1347");
//5.获取连接,使用DriverManager
Connection connection = DriverManager.getConnection(url,properties);

方式四:

最常用

//使用Class.forName会自动完成注册驱动
//底层进行了优化,会帮我们进行driver的注册
//在mysql驱动5.1.6以后,Class.forName也可省略。
//因为jdk1.5以后使用了jdbc4,不再需要显示调用class.forName,而是自动调用
//在jar包下的META-iNFservicesjava.sql.Driver文本中的类名去注册
//但是老师建议写上这句话,更加明确可读性高。
Class.forName("com.mysql.jdbc.Driver");
//得到url和配置信息
String url = "jdbc:mysql://localhost:3306/db02";
//将 数据库的用户名和密码放入到Properties对象
Properties properties = new Properties();
properties.setProperty("user","root");
properties.setProperty("password","1347");
//获取连接
Connection connection = DriverManager.getConnection(url,prop

方式五:

建议使用

//得到url和配置信息
//将 数据库的用户名和密码放入到Properties对象
Properties properties = new Properties();
properties.load(new FileinputStream("src\mysql.properties"));
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
//会自动完成注册驱动.建议写上
Class.forName(driver);
//获取连接
Connection connection = DriverManager.getConnection(url,user,password);

ResultSet结果集

  1. 表示数据库结果集的数据表,通常通过执行查询数据库的语句生成
  2. ResultSet对象保持一个光标指向其当前的数据行,最初,光标位于表头
  3. next方法将光标移动到下一行,并且由于ResultSet对象中没有更多行时返回false,因此可以在while循环中使用循环来遍历结果集

获取查询表的数据,通过exectuQuery返回一个ResultSet集合,集合中存储了查询表的数据,我们可以通过方法来进行读取

每一个ResultSet底层是ArrayList,ArrayList每一行的数据是使用ByteArrayRow存储的

//获得连接数据库的参数,账号、密码、数据库、驱动
Properties properties = new Properties();
properties.load(new FileInputStream("src\mysql.properties"));

String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");

//1.注册驱动,通过反射方式
Class.forName(driver);
//2.获取数据库连接
Connection connection = DriverManager.getConnection(url,user,password);
//3.写sql语句,获得操作sql语句的statement
String sql = "select name,pwd From admin";
Preparedstatement preparedStatement = connection.prepareStatement(sql);
//获取结果集,并打印输出
ResultSet resultSet = preparedStatement.executeQuery();
while(resultSet.next()){
    String name = resultSet.getString(1);
    String pwd = resultSet.getString(2);
    System.out.println(name + "t" + pwd);
}
//关流
resultSet.close();
preparedStatement.close();
connection.close();

Statement

  1. Statement对象,用于执行SQL语句并返回其生成结果
  2. 连接建立后,需要对数据库进行访问,执行命令或是SQL语句,可以通过
    • Statement【存在SQL注入】
    • PreparedStatement【预处理】
    • CallableStatement【存储过程】
  3. Statement对象执行SQL语句,存在SQL注入风险
  4. SQL注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据注入非法的SQL语句段或命令,恶意攻击数据库
  5. 范SQL注入,只要用PreparedStatement取代Statement就可以了

SQL注入

通过传入的用户名和密码,改动查询条件,达到绕过验证的操作

比如一条查询语句是 SELECT * From WHERE id = '账号' AND pwd = '密码'只有当账号密码和数据库中的数据对应上,才能登录进去现在我们尝试SQL注入,改变查询条件,输入id = '(1'or)' AND pwd = '(or'1' = '1)'将查询条件改为了 SELECT * FROM WHERE (id = '1') OR ('AND pwd =') OR ('1' = '1')

preparedStatement优点

  1. 不再使用 + 拼接sql语句,减少语法错误
  2. 有效解决了sql注入问题
  3. 大大减少了编译次数,效率较高
//获得连接数据库的参数,账号、密码、数据库、驱动
Properties properties = new Properties();
properties.load(new FileInputStream("src\mysql.properties"));

String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");

//1.注册驱动,通过反射方式
Class.forName(driver);
//2.获取数据库连接
Connection connection = DriverManager.getConnection(url,user,password);
//增
String sql = "insert into admin values (?,?)";
//改
//String sql = "update admin set name = ? where name = ?";
//删
//String sql = "delete from admin where name = ?";
//获得操作sql语句的statement
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,"king");
preparedStatement.setString(2,"tom");
//返回语句执行结果
int i = preparedStatement.executeUpdate();
System.out.println(i > 0 ? "成功" : "失败" );
//关流
preparedStatement.close();
connection.close();

JDBC API小结

DriverManager驱动管理类

getConnection(url,user,pwd) :获取到连接

Connection接口

createStatement:创建Statement对象,有sql注入风险prepareStatement(sql):生成preparedStatement预处理对象,解决了sql注入

Statement接口

executeUpdate(sql):执行dML语句,返回被影响的行数executeQuery(sql):执行查询,返回ResultSet对象execute(sql):执行任意的sql,返回布尔值

PreparedStatement接口

executeUpdate(sql):执行dml语句,返回被影响的行数executeQuery(sql):执行查询,返回ResultSet对象execute(sql):执行任意的sql,返回布尔值setXxx(占位符索引,占位符值):用来替换前面的占位符,接收类型为XxxsetObject(占位符索引,占位符的值):当做对象处理,接收类型为Object

ResultSet结果集

next:向下移动一行,如果没有下一行,就返回falseprevious:向上移动一行,如果没有上一行,返回falsegetXxx(列的索引名)或者getXxx(列名):获取对应列的值,接收类型为XxxgetObject(列的索引名)或者getXxx(列名):同上,接收类型为Object

事务

JDBC开启事务,不使用start transaction,使用setautocommIT为false,停止事务的自动提交相当于开启你自己的事务。

批处理

  1. 当需要成批插入或者更新记录时,可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理,通常情况下比单独提交处理更有效率

  2. JDBC的批处理语句包括下面方法

    addBatch:添加需要批量处理的SQL语句或参数

    executeBatch:执行批量处理语句

    clearBatch:清空批处理包的语句

  3. 批处理底层是ArrayList,通过将sql语句放入arrayList,满足条件后,将arrayList里的sql语句一次性传输给mysql执行。

details

  1. 如果要使用批处理,需要在配置文件的url添加?rewriteBatchedStatements=true

  2. sql语句要写的规范。例如insert into admin values(null,?,?),批处理不生效。在values和插入数据间加个空格就好了。insert into admin values (null,?,?)

数据库连接池

传统连接Connection问题分析

  1. 传统的JDBC数据库连接使用DriverManager获取,每次向数据库建立连接的时候都要将Connection加载到内存中,再验证IP地址,用户名和密码(0.05s~1s时间)。需要数据库连接的时候,就向数据库要求一个,频繁的进行数据库连接操作将占用很多的系统资,容易造成服务器崩溃
  2. 每一次数据库连接,使用完后都得断开,如果程序出现异常而未能关闭,将导致数据库内存泄露,最终将导致重启数据库
  3. 传统获取连接的方式,不能控制创建的连接数量,如连接过多,也可能导致内存泄露,Mysql崩溃
  4. 解决传统开发中的数据库连接问题,可以采用数据库连接池技。(connection pool)

数据库连接池

  1. 预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从"缓冲池"中取出一个,使用完毕之后再放回去
  2. 数据库连接池负责分配,管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。
  3. 当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中

数据库连接池种类

JDBC的数据库连接池使用javax.sql.DataSource来表示,DataSource只是一个接口,该接口通常由第三方提供实现

  1. C3P0数据库连接池:速度相对较慢,稳定性不错(应用在hibernate,spring)
  2. DBCP数据库连接池:速度相对C3P0较快,但是不稳定
  3. Proxool数据库连接池:有监控连接池状态的功能,稳定性较C3P0差一点
  4. BoneCP数据库连接池:速度快
  5. Druid(德鲁伊)是阿里提供的数据库连接池,集DBCP、C3P0、Proxool优点于一身的数据库连接池

传统方式连接数据库

#mysql.properties配置文件
url=jdbc:mysql://localhost:3306/db02?rewriteBatchedStatements=true
user=root
password=1347
driver=com.mysql.jdbc.Driver
Properties properties = new Properties();
properties.load(new FileInputStream("src\mysql.properties"));

String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");

Class.forName(driver);
Connection connection = DriverManager.getConnection(url,user,password);

C3P0连接池

首先要引用对应jar包

方式一

Properties properties = new Properties();
properties.load(new FileInputStream("src\mysql.properties"));

String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
//创建数据源对象
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
//给数据源设置相关的参数
comboPooledDataSource.setDriverClass(driver);
comboPooledDataSource.setJdbcUrl(url);
comboPooledDataSource.setUser(user);
comboPooledDataSource.setPassword(password);
//设置初始化连接数和最大连接数
comboPooledDataSource.setInitialPoolSize(10);
comboPooledDataSource.setMaxConnectionAge(50);
//获取连接,从连接池中拿取连接
Connection connection = comboPooledDataSource.getConnection();

方式二

//使用c3p0的xml配置文件,将所有信息写入XMl文件,获取连接池的时候直接读取//xml文件内容如下,文件名为c3p0-config.xml<c3p0-config>    <!-- 连接池的名称 -->    <named-config name="comboPool_name">        <!-- 驱动类 -->        <property name="driverClass">com.mysql.jdbc.Driver</property>        <!-- url -->        <property name="jdbcUrl">jdbc:mysql://localhost/db02</property>        <!-- 数据库用户名 -->        <property name="user">root</property>        <!-- 密码 -->        <property name="password">1347</property>        <!-- 每次增长的连接数 -->        <property name="acquireIncrement">5</property>        <!-- 初始的连接数 -->        <property name="initialPoolSize">10</property>        <!-- 最小连接数 -->        <property name="minPoolSize">5</property>        <!-- 最大连接数 -->        <property name="maxpoolSize">10</property>        <!-- 可连接的最多的命令对象数 -->        <property name="maxStatements">5</property>        <!-- 每个连接对象可连接的最多的命令对象数 -->        <property name="maxStatementsPerConnection">2</property>    </name-config></c3p0-config>
//有了xml文件之后使用c3p0连接池//创建数据源对象(连接池)ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("comboPool_name");//获取连接,从连接池中拿取连接Connection connection = comboPooledDataSource.getConnection();

Druid连接池

引入druid的jar包

#druid.properties配置文件#key=valuedriverclassname=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/db02?rewriteBatchedStatements=true#url=jdbc:mysql://localhost:3306/db02username=rootpassword=1347#initial connection SizeinitialSize=10#min idle connection sizeminIdle=5#max active connection sizemaxActive=20#max wait time (5000 mil seconds)maxWait=5000
//引入配置文件数据Properties properties = new Properties();properties.load(new FileInputStream("src\druid.properties"));//使用Druid创建数据源(连接池)传入配置文件参数DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);Connection connection = dataSource.getConnection();connection.close();

apache--DBUtils

原始方法完成数据转换

连接的事情告一段落之后,我们开始对性能和便利方面进行学习

对于resultSet的许多问题

  1. 结果集合connection是关联的,即如果关闭连接,就不能使用结果集
  2. 结果集不利于数据管理,只能使用一次
  3. 使用返回信息也不方便

之前我们是连接后通过JDBC把java语句转化成sql语句,去数据库中尽心查找,然后返回数据库查找的内容。然后关闭连接。

这会导致很多不方便的操作。我们现在需要的是在java层面,获取数据,并且进行操作。在数据库的连接关闭之后,我们也能留住数据。因此我们可以根据数据库中的表,去设计对应的一个类。表对应类,字段对应字段,获取数据对应方法。一个实例对象对应一条数据库记录,然后存放到ArrayList集合中

//Actor表对应的类public class Actor {    private Integer id;    private String name;    private String sex;    private Date bornDate;    private String phone;    //还有无参构造、有参构造、getset、toString}
//
Connection connection = null;
String sql = "select * from actor where id >= ?";
PreparedStatement preparedStatement = null;
ResultSet set = null;
ArrayList<Actor> list = new ArrayList<>();

try {
    connection = JDBCUtilsByDruid.getConnection();
    preparedStatement = connection.prepareStatement(sql);
    preparedStatement.setInt(1,1);
    set = preparedStatement.executeQuery();
    while (set.next()){
        int id = set.getInt("id");
        String name = set.getString("name");
        String sex = set.getString("sex");
        Date bornDate = set.getDate("bornDate");
        String phone = set.getString("phone");
        list.add(new Actor(id,name,sex,bornDate,phone));
    }
    System.out.println(list);
} catch (Exception e) {
    e.printStackTrace();
}finally {
    JDBCUtilsByDruid.close(set,preparedStatement,connection);
}

Apache介绍

  1. commons-dbutils是Apache组织提供的一个开源JDBC工具类库,它是对JDBC的封装,使用dbutils能极大简化jdbc编码的工作量

DbUtils类

  1. QueryRunner类:该类封装了SQL的执行,是线程安全的,开源实现增、删、改、查、批处理
  2. 使用QueryRunner类实现查询
  3. ResultSetHandler接口:该接口用于处理java.sql.ResultSet,将数据按要求转换为另一种形式

常用方法

  1. ArrayHandler:把结果集中的第一行数据转成对象数组
  2. ArrayListHandler:每一行都转成一个数组,再存放到List中
  3. BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中
  4. BeanListHandler:同上
  5. ColumnListHandler:将结果集中某一列的数据存放到List中
  6. KeyedHandler(name):将结果集中每行数据都封装到Map里,再把这些Mao存到一个Map里,其key为指定的key
  7. MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value是对应的值
  8. MapListHandler:同上

总结

以上相当于完成了在Java程序里对数据库进行操作,但是要操作所有的表,增删改查,没有区分,sql语句是写死的,每操作一次都需要一个新的sql语句。极不方便。

通过下面的方法,我们归类sql语句,将每个表的sql语句单独区分出来,划到各个表的DAO里进行操作增删改查。

DAO(data access object)

以上方法还是存在不足

  1. SQL语句固定,不能通过参数传入,通用性不好,需要进行改进,更方便执行增删改查
  2. 对于select操作,如果有返回值,返回值类型不能固定,需要使用泛型
  3. 将来的表很多,业务需求复杂,不可能只靠一个Java类完成

各司其职,每个DAO,操作对应的表

DAO

数据访问对象

脚本宝典总结

以上是脚本宝典为你收集整理的回顾总结21全部内容,希望文章能够帮你解决回顾总结21所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。