MySQL02

1.SQL注入问题

create table user(
id int(4) primary key auto_increment,
username varchar(10) not null,
password varchar(15)
);
insert into user values(0001,'张三','666666');
insert into user values(0002,'李四','888888');

select*from user where username='' and password ='';
select*from user where username='"+username+"' and password ='"+password+"'

select*from user where username='张三' and password ='a'or'1'='1'

表示一个永真式

先打断点-》debug as -》F5表示进入方法,F6表示一步步走,F8表示进入下一个断点或者结束

2.连接池技术
数据库连接的建立和关闭,由一定的资源消耗,比较大。
传统的数据库访问方式:一次数据库访问对应一次物理连接,每次操作数据库都要打开、关闭物理连接,系统性能严重受损。

解决方案:数据库连接池(Connection Pool),在系统初始化运行时,主动建立足够多的连接,组成一个池,每次
应用程序请求数据连接时,无需重新打开连接,而是从池中取出已有的连接,使用完后,不需要关闭,而是归还。

连接池中连接的使用和释放的原则:
应用启动时,会创建初始化数目的连接,当申请无连接或者达到指定的最小连接数时,按照增量参数值取创建新的连接

为了确保连接池中最小的连接数的策略:
动态检查:定时检查连接池,一旦发现数量小于最小连接,则补充相应的新连接,保证连接池正常运转。
静态检查:空闲连接不足时,系统才能检测到是否达到最小连接数,按需进行分配,用过归还,空闲超时就进行释放。

Apache DBCP连接池
DBCP连接池:数据库连接池,Apache的一个Java连接池的开源项目,同时也是Tomcat使用的连接池组件

连接池是创建和管理连接的缓冲技术,将连接准备好,能够被任何需要的应用使用。

需要两个jar包
commons-dbcp-1.4.jar 连接池实现
commons-pool-1.2.jar 连接池实现依赖的库

通过DataSource获取连接
1)通过属性配置文件获取连接池参数
2)加载参数,获得连接

参数:
初始连接数、最大连接数、最小连接数、最大空闲数、最小空闲数、
每次增加的连接数

3.事务
数据库中保证交易可靠机制,JDBC支持数据库中事务概念,在JDBC中事务默认自动提交

事务特性:
原子性:事务必须是原子工作单位,对于数据修改,要么全部成功,要么全部失败
一致性:事务在完成时,必须全部数据都保持一致状态
隔离性:由并发事务操作的修改必须与其他事务操作的修改隔离
持久性:事务完成之后,它对于系统的影响是永久的

事务是数据库的概念,JDBC是支持事务的,本质还是在数据库中实现的

JDBC事务提供的API(重点)
//获取事务默认的提交方式,默认是自动提交(值为true)
Connection.getAutoCommit();
//设置事务的提交方式,参数true表示自动提交,false表示不自动提交
Connection.setAutoCommit();
//事务提交
Connection.commit();
//事务回滚
Connection.rollback();

 

create table account(
id char(2),
money double(7,2)
);

insert into account values('A',1000);
insert into account values('B',2000);
update account set money=money-500 where id='';
update account set money=1000 where id='A';
update account set money=2000 where id='B';

4.批处理
批处理:发送到数据库,作为一个单元执行的一组语句
批处理好处:降低应用程序和数据库之间的网络应用
相比单个SQL语句的处理,批处理效率高
更为有效
批处理API:
addBatch(String sql)
Statement中的方法,可以将多条SQL语句添加到Statement对象的SQL语句列表中

addBatch()
PreparedStatement中的方法,可以将多条SQL语句添加到PreparedStatement对象的SQL语句列表中

executeBatch()
把Statement或者PreparedStatement对象语句列表中全部SQL语句发送到数据库进行批处理

clearBatch()
清空之前的SQL语句列表

注意:
如果对象中的SQL列表包含过多的待处理语句,可能会产生内存溢出问题。
建议及时处理SQL语句列表

create table student(
id int(4) primary key,
name varchar(10) not null
);

5.返回自动生成的主键值
Oracle通过序列对象进行主键自增长
MySQL是支持主键自增长

dept_xi
emp_xi

//给员工表deptno添加外键约束

alter table emp_xi add foreign key (deptno)
references dept_xi(deptno);

操作:关联数据的插入
插入部门表的同时,往部门表中插入一个员工。主表/从表关联关系,插入数据时保证数据的完整性

如果单表操作,不需要返回插入的主键值
//不推荐,需要跟数据库进行多次交互

insert into dept_xi(dname,location) values('研发部','南京');

select deptno from dept_xi where dname='研发部';

insert into emp_xi(ename,deptno) values('张三',查询出来的部门号);

//推荐
利用PreparedStatement的getGeneratedKeys方法获取自增长类型的数据,性能良好,只有一次SQL交互

ps=con.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
ps=con.prepareStatement(sql,Statement.1);
ps.executeUpdate();

rs=ps.getGeneratedKeys();
rs.next();

//返回部门表插入数据对应的主键值

int deptno=rs.getInt(1);

//添加一个部门信息,同时往部门里添加一个员工

void addDeptAndEmp(Dept dept,Emp emp);

6.分页查询
JDBC实现Oracle的分页查询:利用rownum(伪列),传入SQL语句,以获得分页结果集

select *
from(select empno,ename,rownum rn
from emp_xi)
where rn between ? and ?

//计算公式
page:第几页
pageSize:表示每页的记录
1页 1-5
2 6-10
3 11-15

int begin=(page-1)*pageSize+1;
int end=page*pageSize;

//执行

ps=con.prepareStatement(sql);
ps.setInt(1,begin);
ps.setInt(2,end);
ps.executeUpdate();

JDBC 实现MySQL的分页查询
select*from emp_xi limit begin,pageSize;
select*from emp_xi limit ?,?;

1页 0-4 limit 0,5
2 5-9 limit 5,5
3 10-14 limit 10,5
int begin=(page-1)*pageSize; //开始是从0开始
int end=page*pageSize-1;

//执行

ps=con.prepareStatement(sql);
ps.setInt(1,begin);
ps.setInt(2,pageSize);
ps.executeUpdate();


两种分页策略:
1)每次向数据库请求一页数据量,内存压力小,适合大数据量的表
2)一次性把数据全部查询出来放在缓存中,根据用户看的页数和每页记录数计算,把对应的数据显示出来

posted @ 2018-06-11 09:48  阴翳公子  阅读(125)  评论(0编辑  收藏  举报