一、SQL注入使用占位符解决
//使用jdbc发送sql语句, 到数据库tb_user 查询是否有该用户名和密码的用户
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/mytest?useUnicode=true&characterEncoding=utf8&useSSL=false";
conn = DriverManager.getConnection(url,"root","123");
String sql ="SELECT * FROM tb_user WHERE username = ? AND PASSWORD = ?";
pstmt = conn.prepareStatement(sql);
//给?赋值
pstmt.setString(1,username);
pstmt.setString(2,password);
//PreparedStatement 调用executeQuery() executeUpdate() 无参
rs = pstmt.executeQuery();
return rs.next();
} catch (Exception e) {
e.printStackTrace();
// throw new RuntimeException(e);
}finally {
try {
if(rs != null) rs.close();
if(pstmt != null) pstmt.close();
if(conn != null) conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return false;
二、ResultSet
- 加载驱动类
- 获取连接
- 编写sql select
- 创建Statement对象
- 执行之,并接收结果 executeUpdate(sql) executeQuery(sql)
- 如果查询, 解析ResultSet
- 关闭资源
1.移动行指针: ResultSet 的boolean next()
2.提供一堆:Xxx getXxx() Xxx: 数据类型名: getString() getInt() getLong() getObject()...
3.close() 关闭ResultSet
三、JDBC工具类
数据库四大参数 放在db.properties文件中
Map的实现类: java.util.Properties类
load(输入流) 把指定的properties文件的数据加载到Properties集合中
四、封装
Dao层模式
jdbc代码操作数据库, 比如CURD, 全部写在main, 肯定不行
对jdbc的代码进行封装, 开发中. jdbc代码封装在dao层(数据访问层)
层: 一个包
表 --> 类
列--> 属性
一行记录-->一个对象
多行记录--> 多个对象: List<对象>
表: tb_user表 User类 UserDao(封装了对tb_user增删改查)
tb_emp表 Emp类 EmpDao(封装了对tb_emp增删改查)
对应数据库表的类: pojo类, entity类(实体类)
UserDao 接口
|-- UserDaoImpl 实现类
EmpDao 接口
|-- EmpDaoImpl 实现类
pojo类的要求:
属性必须私有的,
属性的数据类型必须包装类
属性的日期类型: java.util.Date
属性名必须遵循小驼峰命名法
列名: stu_name --> 属性名 : stuName
如果手动添加了构造方法, 一定添加一个无参构造方法
db.properties
#驱动类全限定名 driverClass = com.mysql.jdbc.Driver #jdbc的url url = jdbc:mysql://localhost:3306/mytest?useUnicode=true&characterEncoding=utf8&useSSL=false #用户名 username = root #密码 password = 123
五、单元测试
UserDaoImpl类包含多个方法
对方法进行测试: 单元测试,
- 传统方式: main方法测试
缺点: 1.测试结果靠人工判断, 输出结果判断
2. 一个类只能有一个main()方法,测试方法写在一起,不方便单元测试
- 基于junit单元测试
步骤: 1.导入junit依赖: junit3 淘汰了 junit4(使用) junit5(最新的)
3编写测试类 取名的规范: 被测试类类名Test, idea 可以自动创建测试类
常用的注解:
@Test 标记在测试方法上面,表示该方法是一个测试方法, 直接运行
junit4测试方法的要求:
测试方法必须为public
测试方法的返回值类型必须为void
测试方法必须是无参的
@Before 标记的方法,表示该方法在@Test标记的方法之前执行
@After标记的方法,表示该方法在@Test标记的方法之后执行
六、事务
实际开发中一个业务功能可能执行的sql语句多条, 有一种策略: 一组sql语句要就全部成功,要就全部失败 这种策略:称为事务
同一个事务下的所有的sql语句,要就全部成功,要就全部失败
dao类一个方法只执行一条sql, 业务类中, 一个方法执行多条sql(调用多个Dao类多个方法),
实际开发中: 事务加在业务层
事务四大特性: ACID
事务具有4个基本特征,分别是:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Duration),简称ACID
① 原子性 事务的原子性是指事务必须是一个原子的操作序列单元。事务中包含的各项操作在一次执行过程中,只允许出现两种状态之一,要么都成功,要么都失败
任何一项操作都会导致整个事务的失败,同时其它已经被执行的操作都将被撤销并回滚,只有所有的操作全部成功,整个事务才算是成功完成
② 一致性(Consistency) 事务的一致性是指事务的执行不能破坏数据库数据的完整性和一致性,一个事务在执行之前和执行之后,数据库都必须处以一致性状态。
比如:如果从A账户转账到B账户,不可能因为A账户扣了钱,而B账户没有加钱
③ 隔离性 行锁 事务的隔离性是指在并发环境中,并发的事务是互相隔离的,一个事务的执行不能被其它事务干扰。也就是说,不同的事务并发操作相同的数据时,每个事务都有各自完整的数据空间。
一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务是不能互相干扰的
④ 持久性(Duration) 事务的持久性是指事务一旦提交后,数据库中的数据必须被永久的保存下来。即使服务器系统崩溃或服务器宕机等故障。只要数据库重新启动,那么一定能够将其恢复到事务成功结束后的状态
mysql: 默认自动提交的
执行完一条DML(增删改)的sql, 自动提交事务
事务结束:
- 事务提交
- 事务回滚