sql注入:
select * from user where username = ‘rose’ and password = ‘erterfre’ or ‘1’=‘1’
概述:
sql注入指的是,用户输入的信息成为了sql语句的一部分.
//获取语句执行者
connection.createStatament();
PreparedStatement: 预编译对象
先将sql传递给数据库,将sql语句事先编译好,使用时直接赋真实的值,执行sql即可
查询:
select * from user where id = 1;
select * from user where id = ?;
作用:
降低mysql数据库的压力
提高sql的执行效率: mysql数据库只会将相同的sql语句预编译一次
提高安全性: 可以解决sql注入的风险
使用步骤:
1.编写预编译的sql
String sql = "select * from user where name=? and password=? ";
String sql = "insert into user values(null,?,?) ";
2.创建预编译对象
PreparedStatement pst = conn.prepareStatement(sql);
3.设置具体的参数
pst.setXXX(int a,XXX 值);
a: 第几个 ? (占位符)
XXX: 具体类型的值
4.执行sql即可
ResultSet rs = pst.executeQuery(); // 执行查询,返回 resultSet
int i = pst.executeUpdate(); // 执行 增 删 改 返回的是影响的行数
使用预编译对象完成用户登录
public static void main(String[] args) {
try {
Scanner scanner = new Scanner(System.in);
// 1.提示用户输入用户名和密码
System.out.println("请输入您的用户名:");
String username = scanner.nextLine();
System.out.println("请输入密码:");
String password = scanner.nextLine();
// 2.获取用户输入的用户名和密码
// 3.使用JDBC查询数据库完成登录
//a 从工具类中获取链接
Connection conn = JDBCUtils.getConnection();
//b.编写sql语句
//String sql = "select * from user where username = '"+username+"'and password = '"+password+"'";
String sql = "select * from user where username = ? and password = ? ";
//c.获取语句执行者
//Statement st = conn.createStatement();
//获取预编译语句执行者
PreparedStatement st = conn.prepareStatement(sql);
//给占位符赋值
st.setString(1,username);
st.setString(2,password);
//d.执行sql并返回结果
ResultSet rs = st.executeQuery();
// e.判断执行结果
if(rs.next()){
//登录成功
System.out.println("恭喜<"+ username+">登录成功");
}else {
System.out.println("用户名或密码错误");
}
//f.释放资源
JDBCUtils.close(rs,st,conn);
} catch (SQLException e) {
System.out.println("当前功能正在维护....");
}
}
使用预编译对象完成商品表的增删改查:
public static void main(String[] args) throws Exception {
//查询
//select();
//添加
//insert();
//删除
//delete();
//修改
update();
}
/**
* 将id为7的商品 名称改为椰子 价格改为1899
*/
private static void update() throws SQLException {
Connection conn = JDBCUtils.getConnection();
String sql = "update product set price = ?,name=? where id = ?";
PreparedStatement pst = conn.prepareStatement(sql);
pst.setDouble(1,1899);
pst.setString(2,"椰子");
pst.setInt(3,7);
int i = pst.executeUpdate();
if (i>0){
System.out.println("修改成功");
JDBCUtils.close(pst,conn);
}
}
/**
* 删除id为8
*/
private static void delete() throws SQLException {
Connection conn = JDBCUtils.getConnection();
String sql = "delete from product where id = ? ";
PreparedStatement pst = conn.prepareStatement(sql);
pst.setInt(1,9);
int i = pst.executeUpdate();
if (i>0){
System.out.println("删除成功");
}
JDBCUtils.close(pst,conn);
}
/**
* 添加
*/
public static void insert() throws Exception {
//使用工具类注册驱动获取连接
Connection conn = JDBCUtils.getConnection();
//3.编写sql语句
String sql = "insert into product values(null,?,?)";
//使用预编译对象
PreparedStatement pst = conn.prepareStatement(sql);
pst.setString(1,"椰子700");
pst.setDouble(2,1899);
//4.获取语句执行者
//5.执行sql语句
int i = pst.executeUpdate();
//6.打印结果集
System.out.println(i);
//7.释放资源
JDBCUtils.close(pst,conn);
}
/**
* 查询
*/
private static void select() throws Exception {
Connection conn = JDBCUtils.getConnection();
//3.编写sql语句
String sql = "select * from product";
//4.获取语句执行者 小货车
Statement st = conn.createStatement();
//5.执行sql语句 返回的是集合
ResultSet rs = st.executeQuery(sql);
//6.处理结果集 next():判断是否还有下一条数据
while (rs.next()){
int id = rs.getInt(1);
String name = rs.getString(2);
double price = rs.getDouble(3);
System.out.println(id+":"+name+":"+price);
}
//7.释放资源
JDBCUtils.close(rs,st,conn);
}
连接池
Connection: 连接
List
连接池本质上就是一个存放很多连接的list集合
概述
连接池是创建和管理数据库连接的缓冲池技术。连接池就是一个容器,连接池中保存了一些数据库连接,这些连接是可以重复使用的。
API: 连接池规范
Java为数据库连接池提供了公共的接口(规范)
DataSource 接口:
getConnection(): 从连接池中获取连接的方法
close(): 将该连接归还给连接池
开发常用连接池
C3P0连接池
C3P0是一个开源的连接池,Hibernate框架默认使用的就是C3P0连接池(SSH:Struts2 + Spring + Hibernate)
SSM: SpringMVC + Spring + Mybatis (三大框架)
ComboPooledDataSource : C3P0的连接池对象
public ComboPooledDataSource()
无参构造使用默认配置(使用xml中default‐config标签中对应的参数)
public ComboPooledDataSource(String configName)
有参构造使用命名配置(configName:xml中配置的名称,使用xml中named‐config标签中对应的参数)
public Connection getConnection()
从连接池中取出一个连接
Connection:
conn.close();将连接归还到连接池中
硬编码实现c3p0:
public static void main(String[] args) throws PropertyVetoException, SQLException {
//0.导入c3p0连接池的jar包 (2个)
//1.创建c3p0连接池对象
ComboPooledDataSource dataSource = new ComboPooledDataSource();
//2.设置连接的基本信息(driver,url,username,password)
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/94db1");
dataSource.setUser("root");
dataSource.setPassword("root");
//3.设置连接池的基本信息
dataSource.setInitialPoolSize(5); // 设置初始化连接数量
dataSource.setMaxPoolSize(10); // 设置最大连接数量
dataSource.setCheckoutTimeout(3000); // 设置最大等待时间
dataSource.setMaxIdleTime(5000); // 设置最大空闲时间
//4.使用连接池中的连接
/*for (int i = 0; i < 11; i++) {
Connection conn = dataSource.getConnection();
System.out.println(conn);
if(i==9){
// 将当前连接归还到连接池中
conn.close();
}
}*/
//5.使用连接池中的连接操作数据库
Connection conn = dataSource.getConnection();
String sql = "select * from product ";
PreparedStatement pst = conn.prepareStatement(sql);
ResultSet rs = pst.executeQuery();
while(rs.next()){
System.out.println(rs.getInt(1)+" : "+
rs.getString(2)+" : "+
rs.getDouble(3)
);
}
//6.释放资源
rs.close();
pst.close();
conn.close(); // 归还连接
}
配置文件实现c3p0
public static void main(String[] args) throws PropertyVetoException, SQLException {
//0.导入c3p0连接池的jar包 (2个) 和 配置文件
// c3p0连接池的配置文件名为: c3p0-config.xml (不能更改)
// 配置文件存放在src目录下
//1.创建c3p0连接池对象
// 如果调用无参构造,c3p0会自动解析配置文件,使用配置文件中的默认配置信息
// 如果调用有参构造,参数为配置文件中配置信息的名称
ComboPooledDataSource dataSource = new ComboPooledDataSource();
//4.使用连接池中的连接
for (int i = 0; i < 9; i++) {
Connection conn = dataSource.getConnection();
System.out.println(conn);
}
//5.使用连接池中的连接操作数据库
/* Connection conn = dataSource.getConnection();
String sql = "select * from product ";
PreparedStatement pst = conn.prepareStatement(sql);
ResultSet rs = pst.executeQuery();
while(rs.next()){
System.out.println(rs.getInt(1)+" : "+
rs.getString(2)+" : "+
rs.getDouble(3)
);
}
//6.释放资源
rs.close();
pst.close();
conn.close(); // 归还连接*/
}
DRUID(德鲁伊)
com.alibaba.druid.pool.DruidDataSourceFactory 类有创建连接池的方法
public static void main(String[] args) throws Exception {
//0.导入jar包(1个)和配置文件(properties)
//1.使用Druid工厂创建 Druid连接池
InputStream is = DruidDemo.class.getResourceAsStream("/druid.properties");
Properties prop = new Properties();
prop.load(is);
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
Connection conn = dataSource.getConnection();
String sql = "select * from product";
PreparedStatement pst = conn.prepareStatement(sql);
ResultSet rs = pst.executeQuery();
while (rs.next()){
int id = rs.getInt(1);
String name = rs.getString(2);
double price = rs.getDouble(3);
System.out.println(id+":"+name+":"+price);
}
JDBCUtils.close(rs,pst,conn);
//2.从连接池中获取连接
// for (int i = 0; i <11 ; i++) {
// Connection conn = dataSource.getConnection();
// System.out.println(conn);
// }
}
DRUID工具类封装
public class DruidPoolUtils {
private static DataSource dataSource;
static {
//解析配置文件,让durid工厂根据配置文件创建druid连接池
try {
InputStream is = DruidPoolUtils.class.getResourceAsStream("/druid.properties");
Properties prop = new Properties();
prop.load(is);
dataSource = DruidDataSourceFactory.createDataSource(prop);
} catch (Exception e) {
e.printStackTrace();
}
}
//获取连接池的方法
public static DataSource getDataSource(){
return dataSource;
}
//2.获取连接的方法
public static Connection getConnection() throws Exception {
return dataSource.getConnection();
}
//3.释放资源(归还链接)
public static void close(ResultSet rs, Statement st,Connection conn){
try {
if (rs!=null){
rs.close();
}
if (st!=null){
st.close();
}
if (conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
// 重载方法
public static void close(Statement st,Connection conn){
close(null,st,conn);
}
}
测试Druid工具类
public class TestDruidDemo {
public static void main(String[] args) throws Exception {
//1.从连接池工具类中获取连接
Connection conn = DruidPoolUtils.getConnection();
//2.使用连接操作数据库
String sql = "select * from product";
PreparedStatement pst = conn.prepareStatement(sql);
ResultSet rs = pst.executeQuery();
while (rs.next()){
int id = rs.getInt(1);
String name = rs.getString(2);
double price = rs.getDouble(3);
System.out.println(id+":"+name+":"+price);
}
//3.归还连接
DruidPoolUtils.close(rs,pst,conn);
}
}
动态代理: 方法增强
设计模式: 23种
java代码在编写时固定的格式
方法增强:
继承
装饰者模式
动态代理★
装饰者模式:
1.装饰者类和被装饰者类必须实现相同的接口,或继承同一个类
2.在装饰者类必须要有被装饰者类的引用
3.在装饰者类中对需要增强的方法进行增强
4.在装饰者类中对不需要增强的方法调用原来的业务逻辑
动态代理的实现方式:
基于接口的: Proxy (JDK提供的) ★
基于子类的: Cglib (Spring)
装饰者模式
Car接口
public interface Car {
void run();
void color();
String jiaYou(String you);
}
QQ.java实现Car接口
public class QQ implements Car {
@Override
public void run() {
System.out.println("qq车以每秒一米的速度在挪动");
}
@Override
public void color() {
System.out.println("绿色的");
}
@Override
public String jiaYou(String you) {
return "qq车在加油"+you;
}
}
QQWarpper.java实现Car接口
public class QQWarpper implements Car {
private QQ qq;
public QQWarpper(QQ qq){
this.qq = qq;
}
@Override
public void run() {
System.out.println("qq车以每秒1千米的速度在飞奔");
}
@Override
public void color() {
qq.color();
}
@Override
public String jiaYou(String you) {
return qq.jiaYou(you);
}
}
测试 test.java
public class Test {
public static void main(String[] args) {
QQ qq = new QQ();
qq.color();
qq.run();
String you = qq.jiaYou("93#");
System.out.println(you);
// QQWarpper warpper = new QQWarpper(new QQ());
// warpper.run();
// warpper.color();
// String you = warpper.jiaYou("93#");
// System.out.println(you);
}
}
总结:
preparedStatement: 预编译语句执行者
sql语句中如果出现变动的值,使用 ? 占位
获取预编译语句执行者
为sql语句中的占位符设置执行的值
连接池:
存放很多连接的list集合
C3P0连接池:
Druid连接池:
Druid连接池工具类:
动态代理:
方法增强:
继承
装饰者模式
动态代理 ★