JDBC

1、JDBC概述
一、什么是JDBC、为何要学习JDBC?java

JDBC(Java DataBase Connectivity)Java数据库链接
其实就是利用Java语言/Java程序链接并访问数据库的一门技术

虽然以前咱们能够经过 cmd或者navicat 链接数据库,也能够对数据库、表、表记录等进行操做。
可是,未来在开发中更多的是经过程序来链接数据库,若是是Java语言,经过Java程序链接数据库,就必需要学习JDBC这门技术。

二、如何经过Java程序链接mysql数据库?(快速入门)
建立一个测试类: com.tedu.JdbcTest01mysql

//1.注册数据库驱动
//2.获取数据库链接
//3.获取传输器
//4.发送SQL语句到服务器执行,并返回结果
//5.处理执行的结果
//6.释放资源

三、JDBC API总结正则表达式

1)Class.forName("com.mysql.cj.jdbc.Driver");
将mysql驱动包中的"com.mysql.cj.jdbc.Driver"类加载到内存中,Driver类中的静态代码块就会执行,而在Driver类的静态代码块中有一行代码是用于注册驱动的,所以这行代码能够注册驱动!
注册驱动: 将mysql驱动交给JDBC程序管理,以便于使用其中的功能
在JDBC4.0之后的版本中,这一步能够省略,但仍是建议加上

2)DriverManager.getConnection(url,user,password) 
    url:指定要链接的是哪个位置的哪个库
        jdbc:mysql://localhost:3306/jt_db?characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    若是链接的数据库端口是3306,端口能够省略不写:
        jdbc:mysql://localhost/jt_db?characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    若是是链接本机上的数据库,主机名/IP地址能够省略不写:
        jdbc:mysql:///jt_db?characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    getConnection方法返回一个Connection对象,用于表示Java程序和数据库服务器之间的链接。
3)Statement stat = conn.createStatement()
    conn.createStatement() -- 用于获取向数据库发送SQL语句的传输器对象
    stat.executeQuery(sql) -- 用于执行查询类型的SQL语句,返回的是一个ResultSet对象
    stat.executeUpdate(sql)  -- 用于执行新增、删除、修改类型的SQL语句,返回一个int值,表示影响的记录行数

4)rs.next() -- 用于将指向数据行的箭头往下挪动一行,而且返回布尔值(true或false),
    true表示箭头往下挪动一行后,指向的行有数据;false表示箭头往下挪动一行后,指向的行没有数据;

5)在ResultSet结果集对象上提供了获取数据的方法,常见的有:
    rs.getInt( colName );
    rs.getInt( colCount );
    rs.getString( colName );
    rs.getString( colCount );
    rs.getDobule( colName );
    rs.getDobule( colCount );
    ...
    rs.getObject( colName );
    rs.getObject( colCount );

2、JDBC的增删改查sql

一、新增:往account表中添加一条记录:名称为'lucy',金额是3500
二、修改:修改account表中名称为'lucy'的金额,将金额改成2000
三、删除:删除account表中名称为'lucy'的记录

3、junit单元测试框架数据库

junit(单元测试框架): 能够不用添加main函数,也不用建立类的实例就能够执行一个方法
可以用单元测试执行的方法必须知足以下条件:
    1)方法必须是公共的(public)
    2)方法必须是非静态的
    3)方法必须是无返回值的(void)
    4)方法必须是无参数的
若是执行的方法不知足以上任何一个条件,就会报以下错误:
java.lang.Exception: No tests found matching...

junit(单元测试框架)经常使用的三个注解: @Test、@Before、@After
@Test:使用了该注解的方法,每次选中方法名,右键-->Run as-->junit test均可以执行该方法
@Before:使用了该注解的方法,每次会在@Test标记的方法以前执行。也就是说,每次在执行@Test标记的方法以前都会执行@Before标记的方法
@After:使用了该注解的方法,每次会在@Test标记的方法以后执行。也就是说,每次在执行@Test标记的方法以后都会执行@After标记的方法

4、PreparedStatement对象安全

Statement 传输器
PreparedStatement 传输器对象

一、模拟用户登陆案例服务器

PreparedStatement对象是Statement传输器对象的子对象
PreparedStatement对象比Statement对象更加安全,在某些方面执行的效率上也会更高一些!
下面以一个模拟登陆的案例来说解PreparedStatement对象
----------------------------------------------------------
请登陆: 
请输入用户名: 
tom'#'
请输入密码: 

select * from user where username='tom'#'' and password=''
恭喜您登陆成功!
----------------------------------------------------------
请登陆: 
请输入用户名: 
张飞' or '1=1
请输入密码: 

select * from user where username='张飞' or '1=1' and password=''
select * from user where username='tom' or '1=1' and password=''
恭喜您登陆成功!
----------------------------------------------------------

二、SQL注入攻击框架

SQL注入攻击产生的缘由:因为SQL语句中的参数是拼接而来的,其中的参数值(username和password的值)是用户提交过来的,若是用户在提交参数时,在参数中掺杂一些SQL关键字或特殊字符(or、#、-- 、/* */等)就可能会致使SQL语句的语义被篡改,从而执行一些意外的操做(好比用户名或密码错误也能够登陆系统或网站)
delete from user where id=1 or 1=1;

三、如何解决SQL注入攻击问题函数

1)能够对用户提交过来的参数进行校验(例如经过正则表达式对用户名和密码进行校验),若是用户名或密码中有相似于 or、#、-- 等符号,就再也不登陆,直接提示用户输入不合法,请从新登陆!
2)或者使用JDBC中提供的PreparedStatement对象,能够解决SQL注入攻击问题!

PreparedStatement对象是如何解决SQL注入攻击的?
1)PreparedStatement对象是先将SQL语句的骨架(不包含参数)发送给服务器编译并肯定下来。
    String sql = "select * from user where username=? and password=?";
    PreparedStatement stat = conn.prepareStatement(sql);
2)再将SQL语句中的参数值传递给服务器
    //设置SQL语句中的参数值
    stat.setString( 1, user );
    stat.setString( 2, psw );
    //执行SQL语句,返回执行结果
    ResultSet rs = stat.executeQuery();
因为前面SQL语句的骨架已经被肯定了,所以SQL参数中即便再包含SQL关键字或者特殊符号,也不会影响SQL语句的骨架或语义,只会被当前普通的文原本处理,所以能够防止SQL注入!

5、数据库链接池
一、什么是链接池?单元测试

池:常量池、线程池、链接池等中的池都是一个容器。是指内存中的一片空间
链接池:就是将一批链接资源存入到一个容器中。目的是为了实现链接的复用,减小链接建立和关闭的次数,以此来提升程序执行的效率!

二、为何要使用链接池?

传统方式中,每次须要链接都是直接建立一个链接(对象/资源),再基于这个建立的链接去访问数据库,最后用完链接还要关闭!
而每次【建立链接】和【关闭链接】相比使用链接是要消耗大量的时间和资源,致使程序的执行效率很是低下!

为了提升程序执行的效率,咱们能够在程序一启动时,就建立一批链接放在一个链接池中,供整个程序共享。
当用户须要链接时,不用再去建立链接,而是直接从链接池中获取一个链接进行使用,在用完链接后,也不须要关闭,而是直接将链接还回到链接池中。这样一来,用来用去都是链接池中的这一批链接,必然能够实现链接的复用,减小链接建立和关闭的次数。提升程序执行的效率!

三、如何使用c3p0链接池?

dbcp/c3p0/druid/hikari
因为全部的链接池技术都实现了SUN公司所提供的DataSource接口
因此链接池也叫做"数据源"

    
第01步:在程序中建立一个c3p0链接池对象(存放链接的容器)
    ComboPooledDataSource pool = new ComboPooledDataSource();
    
第02步:设置链接数据库的基本信息(四个参数)
方式一:将链接数据库的参数经过setXxx方法直接经过java代码写死在程序中
    pool.setDriverClass("com.mysql.cj.jdbc.Driver");
    pool.setJdbcUrl("jdbc:mysql:///jt_db?characterEncoding=utf-8&serverTimezone=Asia/Shanghai");
    pool.setUser("root");
    pool.setPassword("root");
    这种方式不推荐使用,由于这种方式将链接参数写死在程序中了,未来一旦参数发生变化,就须要咱们去改程序,改完以后须要对项目从新编译、打包、部署、运行等,会提升维护成本!
    
方式二:将链接数据库的参数提取到 c3p0.properties(文件名是固定的) 文件中
    而且须要将这个文件放在源码根目录(src根目录)下,文件内容以下:
    -----------------------------------------
    c3p0.driverClass=com.mysql.cj.jdbc.Driver
    c3p0.jdbcUrl=jdbc:mysql:///jt_db?characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    c3p0.user=root
    c3p0.password=root
    -----------------------------------------
    再次强调:这个文件的位置和名字都是固定的,由于底层c3p0会到指定的位置找指定名称的文件,若是没有按照要求去存放文件或者没有按照要求去指定文件名称,都会致使c3p0找不到这个文件,也就没法读取其中的配置信息,必然会致使连不上数据库!
方式三:将链接数据库的参数提取到 c3p0-config.xml(文件名也是固定的) 文件中
    而且须要将这个文件放在源码根目录(src根目录)下,文件内容以下:
    -----------------------------------------
    <?xml version="1.0" encoding="UTF-8"?>
    <c3p0-config>
        <default-config>
            <property name="driverClass">
                com.mysql.cj.jdbc.Driver
            </property>
            <property name="jdbcUrl">
                jdbc:mysql:///jt_db?characterEncoding=utf-8&amp;serverTimezone=Asia/Shanghai
            </property>
            <property name="user">root</property>
            <property name="password">root</property>
        </default-config>
    </c3p0-config>
    -----------------------------------------
    再次强调:这个文件的位置和名字都是固定的,由于c3p0底层会到指定的位置找指定名称的文件,若是没有按照要求去存放文件或者没有按照要求去指定文件名称,都会致使c3p0找不到这个文件,也就没法读取其中的配置信息,必然会致使连不上数据库!
第04步:从链接池中获取一个链接对象进行使用
    Connection conn = pool.getConnection();
    
第05步:将用完的链接对象还回到链接池中
    conn.close();
若是在程序中没有使用任何链接池,须要链接就经过 DriverManager.getConnection获取(建立)一个链接,用完以后,调用conn.close()就是将链接资源关闭。
若是使用了链接池,经过 链接池对象调用 getConnection方法获取一个链接对象,此时获取的链接对象已经被改造了。用完以后,再调用conn.close()方法是将链接还回到链接池中。也就是说,从链接池中获取的链接对象上的close方法被改形成了还链接到链接池!

四、补充内容:xml文件和properties文件的区别

相同点:这两种文件在企业开发中均可以做为配置文件使用,并且用的特别多
不一样点:1)xml文件缺点:配置信息多,编写起来比较麻烦,若是须要经过java程序读取,代码也比较麻烦。
2)xml文件的优势:能够保存有结构的数据(例如在xml文件中保存中国全部的省份以及省份包含的市区)
3)properties文件缺点:配置信息结构是key/value,没法保存有结构的数据
4)properties文件优势:配置信息简洁,若是须要经过java程序读取,读取起来也比较方便。

==================================================
1、什么是事务?

事务:简单的说,事务是将一堆的SQL语句绑定在一块儿执行,结果是要么全都执行成功,要么全都执行失败。并且是都成功了才算成功,但凡是有一条执行失败,就按全失败来处理!

举例: 张三(1000)给李四(1000)转帐100元
-- 开启事务(start transaction)
-- 给张三的帐户金额减去100元
update 帐户表 set money=money-100 where name='张三'; -- 1000
-- 给李四的帐户金额加上100元
update 帐户表 set money=money+100 where name='李四'; -- 1000
-- 提交事务(commit)/ 回滚事务(rollback)

举例: 网上购物
-- 开启事务
-- 往订单表中插入一条订单信息(用户、订单号、商品信息、商品数据量、单价、总金额等)
insert into 订单表 value(....);
-- 减去商品库存表中的库存数量
update 商品库存表 set count=count-2 where...
-- 提交事务/回滚事务

2、事务的四大特性(重要)

一、原子性:表示事务中的全部操做(SQL)是一个总体,不能被分割,要么全都执行成功,要么全都执行失败!

二、一致性:在事务先后的业务数据之和是保持一致的。
    在转帐操做以前,张三帐户金额(1000)和李四帐户金额(1000)之和为2000元
    在转帐操做以后,不管事务提交了仍是回滚了,张三和李四的帐户金额之和仍是2000元。

三、隔离性:是指全部的事务都是隔离开来的,在一个事务中看不到另一个事务正在进行中的状态!
    事务1: 查询A(1000)和B(1000)的帐户总金额 
    
    事务2: -- 开启事务
    A帐户减去100元 -- A:900
    B帐户加上100元 -- B:1100
    -- 提交事务/回滚事务
    
四、持久性:在事务提交后,对数据的更新操做才会持久的保存到数据库中
    -- 开启事务
    A帐户(1000元)减去100元 -- A:900
    B帐户(1000元)加上100元 -- B:1100
    -- 提交事务/回滚事务

3、MySQL中的事务

在mysql中默认一条SQL语句就是一个事务。
若是但愿将多条SQL放在一个事务中执行,能够手动开启事务,并手动结束事务
开启事务: start transaction / begin;
结束事务:提交(commit) 和 回滚(rollback)
例子:使用转帐演示mysql中如何开启事务以及如何结束事务
    -- 开启事务
    start transaction;
    -- A帐户减去100元
    update acc set money=money-100 where name='A';
    -- B帐户加上100元
    update acc set money=money+100 where name='B';
    select * from acc;
    -- 回滚事务 | 提交事务
    rollback; | commit;
    select * from acc;
相关文章
相关标签/搜索