本帖最后由 小石姐姐 于 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包?
- 项目根目录下创建名为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, 数据库管理系统. 是操作和管理数据库的大型软件, 用于建立, 使用和维护数据库, 对数据库进行统一管理和控制, 以保证数据库的安全性和完整性. 用户通过数据库管理系统访问数据库中表内的数据
- 常见数据库
- 数据库: 存储数据表
- 数据表: 存储记录
- DBMS: 操作数据库
- 表和Java类的对应关系
- 表名: Java类名
- 列名: 成员属性名
- 记录: 类对象
- MySQL
- 安装
- 配置和遇到的问题
- 命令行的登录和退出
- 登录: mysql -u 用户名 -p
- 退出: exit
- SQL基本语言
- SQL的概念: Structured Query Language, 结构化查询语言
- 结构: 数据表是由行和列组成的, 是有结构的, 从这种结构中查询
- SQL的4中分类
- DDL: Data Defination Language, 数据定义语言, 用来定义数据库对象(库, 表等)
- DML: Data Manipulation Language, 数据操作语言, 对表中的记录进行增, 删, 改
- DQL: Data Query Language, 数据查询语言, 对表中的记录进行查
- 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 库名;
- 指定字符集: CREATE DATABASE 库名 CHARACTER SET '字符集';
- 删除库
- 查看所有库
- 使用库
- 查看当前使用的库
- 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...: 在一个范围内(包含头和尾)
- IN (): 在列表中, 满足列表中一个即可
- 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(列名): 计算记录数量
- SUM(列名): 将该列的值求总和
- MAX(列名): 求该列值中的最大值
- MIN(列名): 求该列值中的最小值
- AVG(列名): 求该列所有值的平均值
- 分组
- 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)
- 执行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(重点)
|
|