PO类与分层架构
文章目录
- 一、PO类(Persistent Object,持久化对象)
- 二、分层架构核心层
- 1. 持久层(数据访问层,DAO层)
- 2. 业务层(Service层)
- 三、接口回调
- 四、SQL安全与Statement
- 1. SQL攻击(SQL注入)
- 2. Statement与PreparedStatement
- 五、时间与滴答数
一、PO类(Persistent Object,持久化对象)
- 定义:PO类是与数据库表结构一一对应的Java类,用于在程序中封装数据库表中的记录。每个PO类的属性通常对应数据库表的字段,字段名、数据类型需保持一致(或通过映射配置关联)。
- 作用:作为内存中的数据载体,实现数据库数据与Java对象的转换,是ORM(对象关系映射)思想的具体体现。
- 反向生成:通过ORM框架(如Hibernate、MyBatis)的“反向工程”功能,可根据数据库表结构自动生成PO类(即“反向rs po类”,rs可理解为Resultset,从结果集反向映射为对象),减少手动编写实体类的工作量。
二、分层架构核心层
1. 持久层(数据访问层,DAO层)
- 定义:负责与数据库交互,完成数据的增删改查(CRUD)操作,隔离数据库访问细节,为上层提供数据服务。
- 常用技术:
- Hibernate:全自动化ORM框架,封装程度高,配置复杂,相对“笨重”,适合快速开发但灵活性较低。
- MyBatis:半自动化ORM框架,通过XML或注解配置SQL语句,灵活性高,需手动编写SQL,适合对SQL优化有需求的场景。
- MyBatis-Plus:基于MyBatis的增强工具,提供CRUD通用接口、条件构造器等功能,简化重复代码,提高开发效率。
- Spring JDBC Template:Spring框架提供的轻量级JDBC封装工具,简化数据库连接、Statement创建、结果集处理等操作,无需手动管理资源。
- 核心思想:通过ORM(对象关系映射)技术,将Java对象与数据库表关联,避免直接编写原生JDBC代码,降低耦合度。
2. 业务层(Service层)
- 定义:位于持久层之上,负责封装业务逻辑,协调多个DAO层操作完成复杂业务(如事务管理、数据校验、业务规则执行等),不直接与数据库交互。
- 作用:隔离业务逻辑与数据访问,保证业务的独立性和可复用性。
三、接口回调
- 核心思想:当一个类(A)需要使用另一个类(B)的功能,但A不了解B的具体实现时,可定义一个接口,让B实现该接口,A通过接口调用B的方法。即“交给知道属性(实现细节)的人写实现,调用方只关心接口”。
- 反向应用:例如在框架设计中,框架定义接口(如回调接口),用户根据需求实现接口,框架在特定时机自动调用用户的实现逻辑(如Spring的BeanPostProcessor接口,用户实现后框架会在Bean初始化前后回调)。
四、SQL安全与Statement
1. SQL攻击(SQL注入)
- 定义:攻击者通过在输入参数中插入恶意SQL片段(如
' OR '1'='1
),改变原SQL语句的逻辑,非法获取或修改数据。例如:
原SQL:SELECT * FROM user WHERE username='xxx' AND password='xxx'
注入后:SELECT * FROM user WHERE username='xxx' OR '1'='1' --' AND password='xxx'
(条件恒成立,绕过验证)。
2. Statement与PreparedStatement
特性 | Statement | PreparedStatement |
---|---|---|
定义 | 用于执行静态SQL语句的接口 | Statement的子接口,用于执行预编译SQL语句 |
预编译 | 无预编译,每次执行需重新解析SQL | 提前编译SQL模板,参数用? 作为占位符 |
参数设置 | 需手动拼接SQL字符串,易引发注入 | 通过setXxx(index, value) 设置参数(如stmt.setString(1, userID) ),参数从左到右按索引(1开始)匹配 |
SQL攻击防护 | 无防护,拼接参数易被注入 | 自动对参数进行转义,屏蔽恶意SQL片段,防止注入 |
执行效率 | 重复执行相同SQL时效率低 | 预编译后可重复使用,效率更高 |
执行方式 | 调用execute() 等带SQL参数的方法 | 预编译后调用无参execute() 等方法(SQL模板已确定) |
五、时间与滴答数
- 长整型存储时间:常用
long
类型存储时间,通常以“滴答数”(如系统启动后的毫秒数、自1970-01-01 00:00:00 GMT以来的毫秒数)表示。 - 时间间隔计算:两个滴答数相减,结果即为时间间隔(单位与滴答数一致,如毫秒)。例如:
long start = System.currentTimeMillis();
long end = System.currentTimeMillis();
long interval = end - start; // 得到间隔毫秒数
- 场景示例:实现“输错后有二次机会,24小时后重新判断”的逻辑时,可记录第一次错误的滴答数,后续判断当前滴答数与第一次的差值是否超过24小时(24×60×60×1000毫秒)。