黑马程序员技术交流社区
标题:
【石家庄校区】反射到数据库知识点
[打印本页]
作者:
Chrisyu
时间:
2018-1-11 15:25
标题:
【石家庄校区】反射到数据库知识点
本帖最后由 小石姐姐 于 2018-1-12 11:12 编辑
反射到数据库知识点
Java进阶(反射, JavaBean, BeanUtils工具类)
反射机制概述, 获取字节码对象的3种方式
反射:
Reflection. 在程序运行时, 获取任何一个类的所有属性和方法(包括私有的), 调用任意一个对象的所有属性和方法(包括私有的)
反射的前提
获取类的字节码对象
获取字节码对象的3种方法
对象.getClass()
类名.class
Class.forName(String clasName)
反射获取构造方法并创建对象
反射使用的相关类和方法
java.lang.Class类: 类的字节码对象
获取构造方法
Constructor<?>[] getConstructors(): 以数组形式返回该类中所有public的构造方法. 如果没有public的, 则数组长度为0
Constructor<?>[] getDeclaredConstructors(): 以数组形式返回该类中所有权限的构造方法, 包括private的. 如果该类是接口, 基本类型, 数组, void, 则数组长度为0
Constructor<T> getConstructor(Class<?>... parameterTypes): 根据参数列表返回指定的public的构造方法. 参数列表填写参数的字节码对象
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes): 根据参数列表返回指定的所有权限的构造方法, 包括private的. 参数列表填写参数的字节码对象
创建对象
T newInstance(): 使用该类的无参构造创建一个对象
java.lang.reflect.Constructor类: 构造方法对象
T newInstance(): 通过无参构造方法对象创建一个类的对象
T newInstance(Object... initargs): 通过有参构造方法对象创建一个类的对象, 传入构造方法所需的参数列表
void setAccessible(boolean canAccess): 设置为true时禁用Java的访问安全检查, 可以访问所有权限的构造方法
注意:
Class类和Constructor类中都有T newInstance()方法, 都使用类的无参构造创建对象
反射获取一个类的构造方法的步骤
获取该类Class字节码对象(3种方式)
通过Class对象获取构Constructor造方法对象
通过Constructor对象创建该类的对象
反射获取public成员变量: 设置和获取值
Class类中获取成员变量的方法
Field[] getFields(): 获取所有public的成员变量
Field[] getDeclaredFields(): 获取所有权限的成员变量, 包括private的
Field getField(String fieldName): 通过指定的成员变量名获取指定的public的成员变量
Field getDeclaredField(String fieldName): 通过指定的成员变量名获取指定的所有权限的成员变量, 包括private的
java.lang.reflect.Field类: 成员变量对象
Object get(Object obj): 获取指定对象的属性值
void set(Object obj, Object value): 将指定对象的属性值设置为指定的值
void setAccessible(boolean canAccess): 设置为true时禁用Java的访问安全检查, 可以访问所有权限的成员属性
反射获取一个类的public成员变量的步骤
获取该类Class字节码对象(3种方式)
通过Class对象调用newInstance()方法创建该类的对象
通过Class对象调用获取成员属性的方法获取属性对象
通过Field对象设置或获取属性值
反射获取私有成员变量并修改
反射获取非public成员变量并修改的步骤
获取该类Class字节码对象(3种方式)
通过Class对象调用newInstance()方法创建该类的对象
通过Class对象调用获取成员属性的方法获取属性对象
设置Field对象的访问权限(也叫作暴力访问)
void setAccessible(boolean canAccess): 设置为true时可以访问所有权限的成员属性
通过Field对象设置或获取属性值
小结
getXxx(): 只能得到public的属性或方法
getDeclaredXxx(): 可以得到所有权限的属性或方法. 但如果访问权限不足, 则无法操作
setAccessible(true): 获取成员变量, 构造方法, 成员方法的访问权限
反射获取成员方法并调用
获取成员方法
Method[] getMethods(): 返回所有public的方法数组
Method[] getDeclaredMethods(): 返回所有权限的方法数组
Method getMethod(String name, Class<?>... parameterTypes): 获取public的方法, 传入方法名和方法形参字节码对象
Method getDeclaredMethod(String name, Class<?>... parameterTypes): 获取所有权限的指定方法, 传入方法名和方法形参字节码对象
java.lang.reflect.Method类: 成员方法对象 *Object invoke(Object obj, Object... args): 调用指定对象的成员方法 *void setAccessible(boolean canAccess): 设置为true时禁用Java的访问安全检查, 可以访问所有权限的成员方法
反射获取成员方法并调用的步骤
获取该类Class字节码对象(3种方式)
通过Class对象调用newInstance()方法创建该类的对象
通过Class对象调用获取成员方法的方法获取方法对象
使用Method对象的Object invoke(Object obj, Object... args)方法调用方法, 传入该类的对象和参数, 返回方法的返回值
私有方法, 也是setAccessible(true)获取访问权限
--=
JavaBean概述和规范
JavaBean:
概念: 就是一个类
作用: 封装数据
规范:
类必须是public修饰的
通过private的成员变量保存数据
通过public的get/set方法操作数据
至少提供一个无参构造方法
实现Serializable接口(用于写入文件中)
BeanUtils概述和jar包
jar包
Java ARchive, 一个后缀名为.jar的文件, 类似于rar, 是一个压缩文件, 只不过专门用于压缩Java项目, 所以叫jar
作用
jar包中是写好的代码编译出来的class文件, 有了这些类文件, 就可以调用其中的方法
jar包从哪里来?
相关类库的官方网站上下载
自己导出jar包
如何使用jar包?
项目根目录下
创建名为lib的目录
复制jar文件, 粘贴到项目根目录下的lib目录下
选中项目中的jar包, 右键, 选择Build Path, 点击Add to Build Path. 此时项目中的Referenced Libraries中会出现jar包名称的奶瓶, 说明已经添加成功
导入的jar包整个项目都能使用
BeanUtils
Apache组织提供的第三方类库Commons中的一个组件
作用:
利用反射技术给一个类的对象的成员属性赋值或获取值, 用于快速封装数据到JavaBean
使用BeanUtils所需jar包
commons-beanutils
commons-logging
BeanUtils的常用方法
org.apache.commons.beanutils.BeanUtils类
常用静态方法
static void setProperty(Object bean, String name, Object value): 给对象的成员属性赋值. 传入对象, 成员属性名, 属性值
static String getProperty(Object bean, String name): 获取对象成员属性值. 传入对象, 成员属性名, 返回属性值的字符串形式
static void populate(Object bean, Map properties): 批量给对象的成员属性赋值, 传入对象, Map的key是属性名, value是属性值
BeanUtils的setProperty和getProperty原理
方法底层是通过调用JavaBean的public的get/set方法来获取和设置属性
get/set方法是通过反射来找到的
所以如果没有get/set方法则会报错
数据库 MySQL SQL语句
数据库
概念: 存储数据的仓库. 本质是一个文件系统, 数据按照指定的格式将数据存储起来, 用户可以对数据库中的数据进行增删改查
DBMS: Database Management System, 数据库管理系统. 是操作和管理数据库的大型软件, 用于建立, 使用和维护数据库, 对数据库进行统一管理和控制, 以保证数据库的安全性和完整性. 用户通过数据库管理系统访问数据库中表内的数据
常见数据库
MySQL
Oracle
数据库: 存储数据表
数据表: 存储记录
由行和列组成的
DBMS: 操作数据库
表和Java类的对应关系
表名: Java类名
列名: 成员属性名
记录: 类对象
MySQL
安装
配置和遇到的问题
命令行的登录和退出
登录: mysql -u 用户名 -p
退出: exit
SQL基本语言
SQL的概念: Structured Query Language, 结构化查询语言
结构: 数据表是由行和列组成的, 是有结构的, 从这种结构中查询
SQL的4中分类
DDL: Data Defination Language, 数据定义语言, 用来定义数据库对象(库, 表等)
CREATE
ALTER
DROP
DML: Data Manipulation Language, 数据操作语言, 对表中的记录进行增, 删, 改
INSERT
UPDATE
DELETE
DQL: Data Query Language, 数据查询语言, 对表中的记录进行查
SELECT
FROM
WHERE
DCL: Data Control Language, 数据控制语言, 创建修改用户, 权限
SQL特点
SQL不区分大小写
一条SQL语句以;分号结尾, 一条语句可以多行书写
单词之间通过空格分隔, 参数之间通过,逗号分隔
字符串和日期要用''或""引起来, 建议单引号
SQL注释(2+1种)
2种单行注释
#单行注释
-- 单行注释: 减号后必须有一个空格
1种多行注释: /* 注释内容 */
SQL的数据类型
INT: 整数
DOUBLE: 小数
VARCHAR: 可变长度字符
CHAR: 固定长度字符
其他看文档
VARCHAR和CHAR的区别:
VARCHAR(200), 可变长度字符, 存储占用的内存空间是可变的, 如果你的数据容量小于我们指定的空间大小, 那么就会按照实际的数据空间来开辟内存大小
优点: 节省内存
缺点: 因为每次存入数据时都会判断数据的实际大小, 来动态修改内存空间, 所以需要占用资源, 效率低
CHAR(200), 固定长度字符, 存储占用的内存空间是不可变的. 无论实际存入的数据容量是多大, 都占用这么大的空间
优点: 插入数据时不需要额外操作, 效率高
缺点: 可能会浪费空间
SQL对库的操作
创建库
使用默认字符集创建库: CREATE DATABASE 库名;
默认是UTF-8编码
指定字符集: CREATE DATABASE 库名 CHARACTER SET '字符集';
删除库
DROP DATABASE 库名;
查看所有库
SHOW DATABASES;
使用库
USE 库名;
查看当前使用的库
SELECT DATABASE();
SQL对表的操作
创建表: CREATE TABLE 表名 (列名1 数据类型 约束, 列名2 数据类型 约束);
删除表: DROP TABLE 表名;
查看当前库中的所有表: SHOW TABLES;
修改表的结构: ALTER TABLE 表名 操作关键字 列名 数据类型 约束;
增加列: ALTER TABLE 表名 ADD 新列名 新数据类型 新约束;
删除列: ALTER TABLE 表名 DROP 列名;
修改列的数据类型和约束(不能修改列名):ALTER TABLE 表名 MODIFY 列名 新数据类型 新约束;
修改列的列名, 数据类型, 约束:ALTER TABLE 表名 CHANGE 旧列名 新列名 新数据类型 新约束;
修改表名: RENAME TABLE 旧表名 TO 新表名;
SQL对记录的操作
增
一次插入一条记录: INSERT INTO 表名 (列1, 列2) VALUES (值1, 值2);
一次性插入一条记录(省略自增主键):INSERT INTO 表名 (非主键自增列1, 非主键自增列2) VALUES (值1, 值2);
一次插入所有列的记录(省略列名): INSERT INTO 表名 VALUES (值1, 值2);
值的数量和顺序必须和表的列一致
一次插入多个记录(指定列):INSERT INTO 表名 (列1, 列2) VALUES (记录1值1, 记录1值2), (记录2值1, 记录2值2);
一次插入多个记录(省略列):INSERT INTO 表名 VALUES (记录1值1, 记录1值2), (记录2值1, 记录2值2);
删
删除符合条件的记录: DELETE FROM 表名 WHERE 条件;
删除所有记录: DELETE FROM 表名;
清空表: TRUNCATE TABLE 表名;
DELETE FROM 表名;和TRUNCATE TABLE 表名;的区别
DELETE, 逐条删除记录, 不会重置自增计数器
TRUNCATE, 删除表再重建, 会重置自增计数器
改
修改符合条件的记录:UPDATE 表名 SET 列名1=新值, 列名2=新值 WHERE 条件;
修改所有记录: UPDATE 表名 SET 列名1=新值, 列名2=新值;
查
查询指定列: SELECT 列名1, 列名2 FROM 表名;
查询所有列: SELECT * FROM 表名;
条件查询: SELECT 列名1, 列名2 FROM 表名 WHERE 条件;
运算符
比较运算符
=: 相等
<>或!=: 不等
>: 大于
<: 小于
>=: 大于等于
<=: 小于等于
BETWEEN...AND...: 在一个范围内(包含头和尾)
如: BETWEEN 0 AND 10
IN (): 在列表中, 满足列表中一个即可
如: IN (1, 3, 5)
IS NULL: 是空
LIKE '通配符': 模糊查询
%: 一个百分号可以表示任意个字符. 比如'王%', 王大锤, 王五
_: 一个下划线可以表示一个字符. 比如'王_', 只能匹配王五
逻辑运算符
AND: 与. 两边条件同时成立才成立
OR: 或. 两边条件只要有一个成立就成立
NOT: 非, 取相反结果
NOT BETWEEN ... AND ...: 不在范围内
NOT IN: 不在列表中
NOT LIKE: 不匹配
IS NOT NULL: 非空
去重: SELECT DICTINCT 列名1, 列名2 ... FROM 表名 WHERE 条件;
别名:
字段名 AS 别名
表名 AS 别名
高级SQL
排序
ORDER BY 列名 ASC|DESC;
注意:
默认顺序为升序ASC
WHERE在前, ORDER BY在后
聚合函数
用在SELECT后或HAVING后
COUNT(列名): 计算记录数量
NULL值不会被算入数量
SUM(列名): 将该列的值求总和
如果不是数字类型, 则结果为0
MAX(列名): 求该列值中的最大值
MIN(列名): 求该列值中的最小值
AVG(列名): 求该列所有值的平均值
如果不是数字类型, 则结果为0
分组
GROUP BY 列名 HAVING 条件;: 对查询结果集分组, 然后再按条件过滤
注意:
聚合函数与分组的使用效果
使用聚合函数后再进行分组, 才相当于汇总统计
SELECT zname, SUM(zmoney) FROM zhangwu GROUP BY zname;
不使用聚合函数的分组, 只有第一条记录的值
SELECT zname, zmoney FROM zhangwu GROUP BY zname;
HAVING和WHERE的区别
过滤时机不同
WHERE是在分组前先对查询结果进行过滤
HAVING是在查询结果分组后再次过滤
是否可跟随聚合函数不同
WHERE条件中不可使用聚合函数
HAVING条件中可以使用聚合函数
条件可用列名不同
HAVING条件中的列名必须是SELECT或GROUP BY中使用过的列名
WHERE条件中可以使用表的所有列名
JDBC
JDBC: Java数据库连接. SUN公司提供的接口, 用来让数据库厂商实现数据库操作的功能
数据库驱动: 就是JDBC的实现
JDBC开发步骤:
前提: 导包(数据库驱动)
步骤:
注册驱动
DriverManager.registerDriver(): 是真实的注册驱动的方法
因为驱动中实现了这个方法, 推荐我们使用:
Class.forName("数据库驱动的Driver实现类全类名")
获取连接:
Connection conn = DriverManager.getConnection(url, username, password)
获取执行平台:
Statement s = conn.createStatement();: 不安全的
PreparedStatement ps = conn.prepareStatement(String sql);: 可以防范SQL注入
设置参数:
占位符: ?, 即使是字符串, 也不要给问号加引号
void setObject(int index, Object obj)
index从1开始
执行SQL语句
Statement
增删改: int s.executeUpdate(String sql)
判断操作是否成功: 判断返回值是否>0则生效, 否则不成功
查: ResultSet rs = s.executeQuery(String sql)
思考: 判断操作是否成功: 是返回null呢还是调用.next()用是否为true判断?
PreparedStatement
增删改: int ps.executeUpdate();
判断操作是否成功: 判断返回值是否>0则生效, 否则不成功
查: ResultSet rs = ps.executeQuery();
处理结果
ResultSet
boolean next();: 将指针向后移动, 如果有下一个记录则true, 否则false
默认不执行的之后, 指针在第一条记录之前; 只有调用一次才能指向第一条: while (rs.next()) {}
String getString(String 列名): 获取指定列的值, 以String类型
Object getObject(String 列名): 获取指定列的值, 以Object类型
释放资源
resultSet.close()
preparedStatement.close()
statement.close()
connection.close()
SQL注入
原理: 拼接SQL导致用户的输入可以改变SQL的意义, Statement无法避免注入
超级密码: 1' OR '1=1
如何避免: 使用PreparedStatement替换Statement
JDBCUtils工具类的自定义
在静态代码块中初始化连接对象
定义方法获取连接对象, 释放资源
今日重点
高级SQL语句
排序ORDER BY
聚合函数
SUM()
COUNT()
MIN()
MAX()
AVG()
分组: GROUP BY 列名 HAVING 条件
JDBC
数据库驱动和JDBC原理: 多态的调用
代码:
JDBC操作的6个步骤:
(先导入jar包) 注册驱动
获取连接
获取执行平台
执行SQL语句
处理结果
释放资源
执行平台
Statement(不能用)
PreparedStatement(重点)
作者:
Port
时间:
2018-1-11 17:20
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2