java后端系统学习总结 02_数据库基础学习、jdbc基础学习、er图基础学习、数据库——(完结)
猿猿正在系统的学习一些计算机知识,和后端技术栈,目前阶段主要在系统学习java。此专栏,为我学习过程中的学习笔记,便于日后复习回顾来看,也很适合新人学习参考。
以下是猿猿对数据库和java深入的第一遍学习笔记哦。知识比较细,目录有点长。
文章目录
- 视频学习
- 1.起步
- 什么是数据库?
- 什么是数据管理系统?
- 姓名:
- 作用:
- 常见的数据库管理系统
- 什么是SOL?
- 他们之间的关系
- 2.安装和卸载MySQL
- 安装略
- 卸载
- 3.用命令操作MySQl
- 启动服务
- 关闭服务器
- 登录客户端服务器
- 显示密码的形式登录:
- 隐藏密码的形式登录:
- 退出mysql:
- 参数说明:
- 查看mysql中有哪些数据库
- 选择使用数据库
- 创建数据库
- 查看mysql数据库版本号
- 查看当前使用的是哪个数据库
- 删除数据库
- 终止一条命令的输入
- 分号
- 4.数据库中最基本的单元是表
- 表
- 行
- 列
- 5.关于SQL语句的分类***记忆
- DQL: 数据查询语言
- DML:数据操作语言
- DDL:数据定义语言
- TCL:事务控制语言
- DCL:数据控制语言
- 6.导入文件数据
- 数据的导出
- 注意:
- 导出指定数据库
- 导出指定的表
- 7.查看表
- 查看表中数据
- 不看表中数据只看表的结构
- 8.SQL语句
- ==========SQL语句<始>
- 命名规范
- 8.1简单查询
- 8.1.1 、查询一个字段
- 8.1.2、查询两个字段或多个字段
- 8.1.3、查询所有字段
- 8.1.4、给查询的列起别名
- 注意:
- 8.2条件查询
- 8.2.1、什么是条件查询
- 语法格式:
- 8.2.2、都有哪些条件
- 小于: **<,** 大于: **>**, 不等于: **!=**, 不等于: **<>**, 小于等于: **<=**, 大于等于: **>=**
- 两个值之间: between···and··· (**注意**:左小右大,闭区间) **等同于:** >= and <=
- 为空或不为空: is null(is not null) (**注意**:数据库中null不能使用“=”衡量,它没有值只有值才能被“=”衡量)
- 并且: and
- 或者:or
- and和or同时出现有优先级嘛?
- 包含: in 相当于多个or(not in 不在这个范围)
- 模糊查询: like (支持%或下划线匹配) %任意个字符; _ 下划线,一个下划线只匹配一个字符;
- 8.3 排序
- 8.3.1、默认是升序
- 8.3.2、指定降序
- 8.3.3、指定升序
- 8.3.4、多个字段排序
- 8.3.5、根据字段位置排序(了解)
- 8.3.6、综合案例
- 注意:关键字顺序不能变
- 程序执行顺序:
- 9.数据处理函数
- 9.1、常见的单行处理函数
- lower 转化小写
- upper 转化大写
- concat 字符串的拼接
- substr 取子串
- 案例:
- trim 去空格
- str_to_date 将字符串转为日期
- date_format 格式化日期
- format 设置千分位
- round 四舍五入
- 结论:
- round案例:
- rand() 生成随机数
- ifnull 可以将null转化为一个具体值
- case··when···then···when···then···else···end
- 9.2、分组函数(多行行处理函数)
- 5个:
- 注意:
- 案例:
- 10.分组查询|***重要
- 10.1、什么是分组查询
- 10.2、关键字的顺序不能变
- 执行顺序
- 10.3、案例
- 10.3.1、找出每个工作岗位的工资和
- 注意(重点):
- 10.3.2、找出每个部门的最高薪资
- 10.3.3、找出“每个部门,不同工作岗位”的最高薪资
- 技巧:两个字段联合分组
- 10.3.4、找出每个部门的最高薪资,要求显示最高薪资大于3000的?
- 注意having:
- 10.3.5、where没办法的???
- 11.单表查询大总结
- 关键字顺序不能颠倒
- 执行顺序
- 案例:
- 12.去除重复记录 distinct
- 关键字: distinct
- 注意:
- 13.连接查询 (重要)
- 13.1、什么是连接查询?
- 13.2、连接查询的分类
- 13.2.1、根据年代分类
- 13.2.2、根据连接方式分类
- 13.3、笛卡尔积现象
- 怎么避免笛卡尔积现象?
- 起别名----效率
- 13.4、内连接之等值连接
- SQL92语法:
- SQL99语法:
- 13.5、内连接之非等值连接
- emp表 e
- salgrade表 s
- 语法:
- 13.6、内连接之自连接
- 技巧:一张表看成两张表
- 语法:
- 13.7、外连接 (主次之分)
- 右外连接
- 语法:
- 左外连接
- 语法:
- image-20210908211013024
- 注意:
- 思考:
- 案例:
- 13.8、连接三张表、四张表
- 语法:
- 案例:![在这里插入图片描述](https://img-blog.csdnimg.cn/f287b8801a8e457aafc0def92d4a24a8.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA54Ot54ix5Luj56CB55qE54y_54y_,size_20,color_FFFFFF,t_70,g_se,x_16)
- 效率问题
- 14、子查询
- 14.1、什么是子查询
- 14.2、子查询可以出现在哪里?
- 14.3、where子句中的子查询
- 案例(分组函数):
- 14.4、from子句中的子查询
- 巧妙:
- 15.union合并结果集(高效)
- 案例:
- 优点:避免笛卡尔积的影响
- 使用时的注意事项
- 16.limit (使用在分页中)
- 作用:
- 用法:
- 案例:
- 注意(执行顺序):
- 分页
- 公式:
- 17.DQL语句的大总结
- 关键字顺序:
- 执行顺序:
- ==========SQL语句<完>
- ===========增删改 <始>
- 1.表的创建 (建表)
- 1.1建表的语法格式
- 语法:
- 1.2关于masql中的数据类型
- varchar 可变长度的字符串
- char 定长字符串
- int 等于int
- bigint 等于long
- float 单精度浮点型数据
- double 双精度浮点型数据
- date 短日期类型
- datetime 长日期类型
- clob 字符大对象
- blob 二进制大对象
- 1.3、创建一个学生表
- 查看数据库中有哪些表
- 删除表
- 2、插入数据(增加) insert(DML)
- 语法:
- 注意:
- 插入学生
- 建表时设置默认值
- insert建表时字段名可以省略
- str_to_date 将字符串转为日期
- 语法
- 日期格式
- date_format 格式化日期(查询日期)
- 展示在表中的都是字符串格式
- 3.修改 update (DML)
- 语法:
- 4.删除数据
- 语法
- 注意:
- 5.插入多条数据(重要)
- 语法
- 6.快速建表
- 原理:
- 语法
- 7.插入表
- 语法
- 8.快速删除表中的数据
- 慢方式 (DML)
- 快方式 (DDL):
- 删除表!=删除数据
- 删除表
- 9.对表结构的修改
- 10.约束(很重要)
- 10.1、什么是约束?
- 10.2、约束包括哪些
- 10.2.1非空约束 not null
- 10.2.2、唯一性约束:unique
- 新需求--表级约束
- 什么时候需要使用表级约束?
- unique和not null可以联合
- 10.2.3、主键约束 (primary key,简称PK)
- 主键约束的相关字语:
- 什么是主键?
- 记住:
- 主键的特征
- 给一张表添加主键约束
- 表级约束---复合主键:
- 主键值建议类型
- 主键分类
- 自动维护主键值(重要)
- 10.2.4、外键约束 (foreign key,简称FK) 五星
- 外键约束的相关属于
- 案例:
- 加外键约束
- 语法+引用:
- ===========表<完>
- 1.存储引擎 (了解)
- 1.1、什么是存储引擎?
- 1.2、怎么给表添加存储引擎
- 什么是数据库引擎
- 方式
- 结论:
- 1.3、怎么查看mysql怎么查看存储引擎
- 语法
- 1.4、mysql常用的存储引擎
- MyISAM存储引擎?
- 存储特点:
- 缺点:
- InnoDB存储引擎
- 存储特点:
- MEMORY存储引擎?
- 存储特点
- 2.事务概述(重要且精通)
- 2.1、什么是事务
- 什么是业务逻辑
- 2.2、只有DML语句才会有事务一说
- 2.3、事务为什么存在?
- 什么是事务?
- 2.4事务怎么做到多条语句同时成功和同时失败?
- 2.5、怎么提交事务和回滚事务
- 语法:
- 在mysql默认的事务行为是什么
- 关闭自动提交功能
- 2.6、事务包括四个特性
- 事务的隔离性
- 事务和事务的隔离4级别
- 读未提交
- 读已提交
- 可重复读
- 序列化/串行化
- 2.7、查看隔离级别:
- 2.8、验证:隔离级别
- 验证 read uncommitted
- 验证:read committed
- 验证:repeatable read
- 验证:serializable
- 3.索引(index)
- 3.1、什么是索引
- 注意:
- 3.2、索引的实现原理
- 原理:
- 3.3、什么时候添加索引?
- 3.4、索引创建、删除、语法
- 创建索引
- 删除索引
- 3.5、查看一个sql语句是否使用了索引进行检查
- 3.6、索引有失效的时候
- 第一种(%开头)
- 第二种(or)
- 第三种(复合索引右侧)
- **什么是复合索引?**
- 第四种(字段运算)
- 第五种(函数)
- 3.7、索引优化数据库
- 分类
- 4.视图(view)
- 4.1、什么是视图?
- 4.2、怎么创建视图?
- 表复制
- 创建视图
- 删除视图对象
- 4.3、用视图可以做什么
- 4.4、视图对象在实际开发过程有什么用
- 5.DBA常用命令
- 数据的导出
- 注意:
- 导出指定的表
- 数据的导入
- 注意:
- 创建数据库
- 使用数据库
- 初始化数据库
- 6.数据库设计的三范式(熟记)
- 6.1、什么是数据库设计范式
- 6.2、数据库设计范式共有3个
- 第一范式
- 第二范式
- 第三范式
- 好处:
- 案例
- 第一范式
- 第二范式
- 口诀:多对多的设计
- 第三范式
- 口诀:一对多的设计
- 6.3、总结表的设计
- image-202109131053529326.4、嘱咐一句话
- 求平均薪水的等级最低的部门的部门名称
- JDBC对面的女孩看过来
- idea打开mysql架包
- 一、JDBC简介
- 什么是JDBC
- 工作原理
- 二、使用详情
- 1、准备工作
- 2、JDBC编程步骤
- 小写转大写
- 加载驱动程序需要的驱动:
- 代码:
- 完整代码
- 代码解释
- StringBuilder
- createStatement
- 关于List<Map<String, Object>>
- 详细步骤
- 第一步创建项目:
- 第二步加入驱动:
- 第三步连接数据库
- 三.详设
- 原理
- 解释:
- 视图层
- 流程
- 问题
- 四、回顾
- JDBC的基本概念
- MVC三层架构
- JDBC的链接方式四种
- 扩展
- jdbc占位符的使用
- jdbc查询展示view
- 方法一
- 方法二
- 方法三
- 方法四
- 初始化表格不可编辑
- ER图
- 什么是ER图
- 基本要素
- ER图元素
- 实体补充
- 属性的补充
- 扩展知识
- MVC
- 高内聚低耦合
- this关键字
- 静态方法
- 代码块的分类和执行顺序
- 深入理解static
- 1、static存在的主要意义
- 2、static的独特之处
- 3、static应用场景
- 4、静态变量和实例变量的概念
- 5、静态变量和实例变量区别【重点常用】
- 6、访问静态变量和实例变量的两种方式
- 7、static静态方法
- 8、static静态代码块
- 9、static变量与普通变量区别
- 10、静态内部类
- 11、静态导包
- 12、static注意事项
- 13、final与static的藕断丝连
- 深入理解类的加载
- 理解execute
- 理解HashMap
- HashMap的工作原理以及存取方法过程
- HashMap具体的存取过程如下:
- get值方法的过程是:
- 遍历数组的几种方法
- 数组
- 遍历集合的方法
- 1. 经典循环方式
- 迭代的方式
- 加强for循环
- 使用Lambda表达式的forEach
- 集合map
- java为什么要抛出异常
- 见到的方法
- toUpperCase()
- toLowerCase()
- next()和hasnext()
- SimpleDateFormat
- SimpleDateFormat设置日期格式
- format()方法将日期转换为字符串
- parse()方法将字符串转换为日期
- 获取密码框的值
- .next
- .last
- LAST() 函数
- SQL LAST() 语法
- .getRow
- .berforeFirst
- vector动态数组的遍历
- 获取当前时间,并调整格式
- idea使用教程
- 快捷键
- \1. Ctrl + Space
- \2. Ctrl + N(Ctrl + Shift + N)
- \3. Ctrl + B
- \4. Ctrl + Alt + T
- \5. Ctrl + Alt + B
- \6. Ctrl + W
- \7. Shift + F1
- \8. Ctrl + Q
- \9. Ctrl + /
- \10. F2/Shift + F2
- \11. Shift + F6
- \12. Ctrl + Alt + L
- \13. Ctrl + Alt + I
- \14. Ctrl + Alt + O
- \15. Ctrl + ]/[
- 16.Ctrl+E
- 17.Shift+Click
- 18.Ctrl+Shift+Backspace
- 19.Ctrl+F12
- 20.Ctrl+F7
- 21.Ctrl+Shift+N
- 22.Alt+Q
- 23.Ctrl+P
- 25.Alt+Insert
- 26.Ctrl+Alt+V
- 27.Alt+Up and Alt+Down
- 下面的不是很有用
- 28.Alt+Enter
- 29.Ctrl+Shift+Alt+N
- 30.Ctrl+Shift+Space
- 31.Alt+F3
- 32.Ctrl+O
- 33.Ctrl+Alt+Space
- \34. Ctrl+J
- 35.Ctrl+Shift+F7
- 30.Ctrl+Alt+Up /Ctrl+Alt+Down
- 31.Ctrl+Shift+J
- 32.Alt+F8是计算变量值
- Java几种消息对话框的弹出
- 普通对话框Java代码
- 警示框Java代码
- 错误提示框Java代码
- 基本提示框java代码
- 2.showConfirmDialog
- 3.showOptionDialog(自定义选择提示对话框)
- 4.showInputDialog(下拉框或者输入框)
- 输入框Java代码
- java正则的使用
- Java_Swing中关于关闭窗口的方法
- idea快捷键
- **idea格式化代码时,注释被格式化问题**
- String、StringBuffer和StringBuilder的区别
- String
- StringBuffer
- StringBuilder
- StringBuffer类中实现的方法:
- StringBuilder类中实现的方法:
- **如何在单个窗口打开多个Maven工程啊?**
- 连接池
- 一.什么是数据库连接池
- 二.传统的连接机制与数据库连接池的运行机制区别
- 三.为什么要使用连接池
- 四.常用的开源数据库连接池
- 1.dbcp
- 数据的加密、解密方式
- 级联操作
- 时间戳
- 时区问题
- .时区问题
- .乱码问题
- 储存时间的问题
- idea编码转化
- mysql 单条插入和批量插入
- 单条插入
- 插入多条语句
- getMetaData
- 作品逻辑
- middle 和 product
- middle和buy
- 考核问题总结
视频学习
操作数据库是按照找个步骤写的:
(1)注册驱动;
(2)获取数据库连接;
(3)拼接sql语句,设置sql参数;
(4)执行sql语句;
(5)处理sql返回结果;
(6)关闭执行语句和数据库连接;
1.起步
什么是数据库?
英文单词 DataBase,简称 DB。按照一定格式储存数据的一些文件的组合。
什么是数据管理系统?
姓名:
DataBaseManagement,简称DBMS。
作用:
专门用来管理数据库中的数据,数据库管理系统可以对数据库进行增删改查
常见的数据库管理系统
MySOL、Oracle、MS SqlServer、DB2、Sybase
什么是SOL?
结构化查询语句
他们之间的关系
DBMS----执行–>SOL -----操作 ----->DB
安装数据管理系统MySQL,然后学习SQL语句怎么写,编写SQL语句之后,DBMS对SQL语句进行执行,最终来完成数据库的数据管理
2.安装和卸载MySQL
安装略
卸载
3.用命令操作MySQl
(以下的命令不区分大小写)
启动服务
net start MySQL(数据库名称)
关闭服务器
net stop MySQl(数据库名称)
登录客户端服务器
显示密码的形式登录:
mysql -uroot -p123456
隐藏密码的形式登录:
mysql -uroot -p
退出mysql:
exit; 或 quit;
三个框依次是:用户名、MySQL服务器所在地址、用户密码) 或 mysql -u root -p
参数说明:
- -h : 指定客户端所要登录的 MySQL 主机名, 登录本机(localhost 或 127.0.0.1)该参数可以省略;
- -u : 登录的用户名;
- -p : 告诉服务器将会使用一个密码来登录, 如果所要登录的用户名密码为空, 可以忽略此选项。
查看mysql中有哪些数据库
show databases;//默认带了四个数据库
选择使用数据库
use 数据库名
创建数据库
create database 数据库名
查看mysql数据库版本号
select version();
查看当前使用的是哪个数据库
select database();
删除数据库
drop database 数据库名;
终止一条命令的输入
\c 或 “ ; ”(报错)
分号
注意:mysql 是不见分号“ ; ”不执行," ; "表示结束
4.数据库中最基本的单元是表
表 table 行row(被称为数据/记录) 列 column(被称为字段)
表
- 存储数据
- 数据库下面有很多表
- 查看某个数据库下有某些表 show tables;
行
- 记录/数据
列
- 每一个字段(列)都有:字段名、数据类型、约束等属性
5.关于SQL语句的分类***记忆
DQL: 数据查询语言
凡是带有select关键字的都是查询语句,select···
DML:数据操作语言
- 凡是对表中的数据进行增删改的都是DML
- insert delete update
- insert 增
- delete删
- update改
DDL:数据定义语言
- 凡是带有create、drop、alter的都是DDL
- DDL主要操作的是表的结构,不是表中的数据
- create:新建 等同于增
- drop:删除
- alter:修改
TCL:事务控制语言
- 事务提交: commit
- 事务回滚: rollback
DCL:数据控制语言
如:授权 grant、撤销权限 revoke
6.导入文件数据
怎么导入mysql文件中的数据导入
source 路径名
数据的导出
注意:
在windows的dos命令窗口中:
mysqldump 数据库名 表名 路径\导出后文件名 用户名 密码
导出指定数据库
mysqldump ssm_db >D:\c.sql -uroot -p123456
导出指定的表
mysqldump ssm_db tbl_book >D:\c.sql -uroot -p123456
7.查看表
查看表中数据
select * from 表名; //从表中查所有的数据
不看表中数据只看表的结构
desc 表名;//describe 缩写为desc
8.SQL语句
==========SQL语句<始>
命名规范
所有的标识符都是全部小写,单词和单词之间使用下划线进行衔接
8.1简单查询
8.1.1 、查询一个字段
select 字段名 from 表名;
注意:
- select和from都是关键字
- 字段名和表明都是标识符
8.1.2、查询两个字段或多个字段
使用“ , ”隔开
8.1.3、查询所有字段
把所有字段都写上 select a,b,c,d··· from tablename;
使用* select * from dept;
缺点 (先把*转化为字段)效率低,开发时建议使用
8.1.4、给查询的列起别名
注意:
1.as关键字能省略,别名里面有空格编译会报错
2.解决空格报错:加上单引号或双引号
3.在所有的数据中,字符串统一用单引号括起来,只有在mysql中可以使用
4.字段可以使用数学表达式
8.2条件查询
8.2.1、什么是条件查询
不是将表中所有数据都查出来,查询出符合条件的。
语法格式:
select 字段一,字段二,字段三 from 表名 where 条件;
8.2.2、都有哪些条件
小于: <, 大于: >, 不等于: !=, 不等于: <>, 小于等于: <=, 大于等于: >=
两个值之间: between···and··· (注意:左小右大,闭区间) 等同于: >= and <=
为空或不为空: is null(is not null) (注意:数据库中null不能使用“=”衡量,它没有值只有值才能被“=”衡量)
并且: and
或者:or
and和or同时出现有优先级嘛?
and的优先级高于or
在开发中不确定优先级,就加小括号
使用小括号调整
包含: in 相当于多个or(not in 不在这个范围)
in后面跟的不是区间,而是具体的值
模糊查询: like (支持%或下划线匹配) %任意个字符; _ 下划线,一个下划线只匹配一个字符;
转义字符:
8.3 排序
8.3.1、默认是升序
select 字段一,字段二,字段三 from 表名 order by 字段名;
8.3.2、指定降序
select 字段一,字段二,字段三 from 表名 order by 字段名 desc;
8.3.3、指定升序
select 字段一,字段二,字段三 from 表名 order by 字段名 asc ;
8.3.4、多个字段排序
注意://sal在前,起主导作用,只有字段一相等的时候才会启用字段二排序
select 字段一,字段二,字段三 from 表名 order by 字段一 asc ,字段二 asc;
如果工资一样的话,按照名字的升序排序
8.3.5、根据字段位置排序(了解)
8.3.6、综合案例
注意:关键字顺序不能变
select··· from··· where··· order by···
程序执行顺序:
先找表,赛选条件,选择字段名,排序
9.数据处理函数
- 数据处理函数又被成为单行处理函数
- 单行处理函数的特点:一个输入对应一个输出
- 多行处理函数的特点:多个输入对应一个输出
9.1、常见的单行处理函数
语法: 函数+()
lower 转化小写
一个输入对应一个输出select lower(字段名) as 别名 from 表名;//14个输入对应14个输出-----一个输入对应一个输出
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L0Ra0cqH-1647160218301)(F:/T笔记/Typora/笔记//三月阶段笔记/数据库阶段/数据库——菜鸟教程.assets/image-20210908114048746.png)]
upper 转化大写
concat 字符串的拼接
substr 取子串
select substr(字段名,n(n>0),m) as 别名 from 表名;//substr(被截取的字符串,起始下标,截取的长度)
注意:起始下标是从1开始的,没有0
案例:
找出员工名字第一个字母是A的员工信息
首字母转化为大写在拼接 多函数嵌套
select upper(substr(name,1,1)) from t_student;//首字母转化为大写 select substr(name,2,length(neme)-1) from t_student;//取除首字母外的所有字符串 select concat(upper(substr(name,1,1)),substr(name,,2,length(name)-1)) as result from t_student;//合并
trim 去空格
str_to_date 将字符串转为日期
在插入数据处详讲
date_format 格式化日期
(在插入数据处详讲)把日期转化为字符串
format 设置千分位
round 四舍五入
结论:
select 后面可以跟某个表的字段名(可以等同看成变量名),也可以跟字面量/字面值(数据)。
round案例:
rand() 生成随机数
ifnull 可以将null转化为一个具体值
case··when···then···when···then···else···end
9.2、分组函数(多行行处理函数)
特点:输入多行,最终输出一行
5个:
- count 计数
- sum 求和
- avg 平均值
- max 最大值
- min 最小值
注意:
分组函数使用时必须先进行分组,然后才能用
如果没有对数据进行分组,整张表默认为一组
分组函数自动忽略null,即你不需要对null进行处理
分组函数中count(*) 和 count(具体字段)
count(*) 统计总行数。(只要有数据 count++)
分组函数不能直接使用在where子句中
所有分组函数可以组合起来一起用
案例:
10.分组查询|***重要
10.1、什么是分组查询
select ··· from ··· group by···
10.2、关键字的顺序不能变
select ··· from ··· where ··· group by ··· order by ···
执行顺序
- from 从这张表中找
- where 过滤
- group by 开始分组
- select 查询
- order by 输出
10.3、案例
10.3.1、找出每个工作岗位的工资和
注意(重点):
select后面只能跟被分组的字段和分组函数,别的字段写在这里没有意义
10.3.2、找出每个部门的最高薪资
10.3.3、找出“每个部门,不同工作岗位”的最高薪资
技巧:两个字段联合分组
10.3.4、找出每个部门的最高薪资,要求显示最高薪资大于3000的?
注意having:
- 使用having能对分完组的数据进一步过滤
- having不能单独使用,不能代替where,having必须和group by联合使用
- 优化策略:
- where和having 优先选择where,能用where过滤掉的就有限考虑where
- where实在完成不了的在选择having
10.3.5、where没办法的???
找出每个部门的平均薪资,要求显示平均薪资高于2500
11.单表查询大总结
关键字顺序不能颠倒
select ··· from ··· where ··· group by ··· having ··· order by ···
执行顺序
- from 从这个表中查询
- where 过滤
- group by 分组
- having 再过滤
- select 查询
- order by 输出
案例:
12.去除重复记录 distinct
关键字: distinct
select distinct 字段一,字段二 from emp;
注意:
- 原表数据不会被修改,只是查询结果去重
- distinct只能出现在所有字段的最前方,联合起来去除重复记录
13.连接查询 (重要)
13.1、什么是连接查询?
从一张表中单独查询,称为单表查询
多张表联合起来查询数据,被称为连接查询
13.2、连接查询的分类
13.2.1、根据年代分类
13.2.2、根据连接方式分类
- 内连接 (AB两张表没有主次关系)----inner(可省略)
- 等值连接
- 非等值连接
- 自连接
- 外连接(分主次关系)----outer(可省略)-----------查询所有
- 左外连接(左连接)
- 右外连接(右连接)
- 全连接(暂时不了解)
13.3、笛卡尔积现象
案例:查询每个员工所在部门名称
当两张表进行连接查询时,没有任何条件限制的时候,最终查询结果条数,是两张表条数的乘积。这种现象称为:笛卡尔积现象(这是一个数学现象)
怎么避免笛卡尔积现象?
连接时加条件,满足这条的记录被筛选出来
select ··· ename,dname ···from ··· emp ,dept ··· where emp.depno = dept.deptno
起别名----效率
13.4、内连接之等值连接
案例:查询每个员工所在部门的名称,显示员工名和部门名?
SQL92语法:
缺点:结构不清晰,表的连接条件,和后期进一步筛选的条件,都放在wehere后面
SQL99语法:
内连接
**SQL99优点:**表连接的条件是独立的,连接之后,如果还需要进一步筛选,再往后继续添加where
select ··· from ··· a ··· join b ··· on ··· a和b的连接条件 ··· where ··· 筛选条件 //join(连接)
13.5、内连接之非等值连接
案例:找出每个员工的薪资等级,要求显示员工名、薪资、等级?
emp表 e
salgrade表 s
语法:
selecte.ename,e.sal,s.grade
fromemp e
(inner) joinsalgrade s
one.sal between s.losal and s.hisal; //条件不是一个等量关系,称为非等值连接
13.6、内连接之自连接
案例:查询员工的上级领导,要求显示员工名和对应的领导名?
技巧:一张表看成两张表
语法:
selecta.ename as '员工名',b.ename as '领导名'
fromemp a
join emp b
ona.mgr = b.empno; //员工的领导编号 = 领导的员工编号
13.7、外连接 (主次之分)
右外连接
语法:
左外连接
展示查询结果等效于右外连接查询结果
语法:
注意:
思考:
外连接的查询条数一定是>=内连接的查询结果条数的
案例:
13.8、连接三张表、四张表
语法:
案例:
效率问题
我查询一些资料,有三种看法:
第一种:左连更优。http://stackoverflow.com/questions/17100819/left-join-significantly-faster-than-inner-join
第二种:内连更优。http://stackoverflow.com/questions/2726657/inner-join-vs-left-join-performance-in-sql-server
第三种:取决于实际情况。http://stackoverflow.com/questions/1810465/left-join-faster-or-inner-join-faster
14、子查询
14.1、什么是子查询
select 语句中嵌套select语句,被嵌套的select语句称为子查询
14.2、子查询可以出现在哪里?
多个select
14.3、where子句中的子查询
案例(分组函数):
14.4、from子句中的子查询
巧妙:
可以把from后面表的查询结果当作临时表,进而来作比较
15.union合并结果集(高效)
联合查询,乘法变加法
案例:
查询工作岗位是MANAGER和SALESMAN的员工?
优点:避免笛卡尔积的影响
- union把乘法变加法,减少匹配次数
使用时的注意事项
- 列数相同
- 在oracle数据库中(严格),列和列的数据类型都要相同
16.limit (使用在分页中)
作用:
将查询结果集的一部分取出来。通常使用在分页查询中。
用法:
limit startIndex ,length //完整用法 startIndex是起始下标(从0开始),length是长度
limit 5; 等效 limit 0,5 //取前五
案例:
注意(执行顺序):
mySQL中,limit在order by之后执行
分页
给出页码和条数===>写出sql语句:
公式:
limit (pageNo-1)*pageSize , pageSize
17.DQL语句的大总结
关键字顺序:
执行顺序:
==========SQL语句<完>
===========增删改 <始>
1.表的创建 (建表)
1.1建表的语法格式
语句归属:属于DDL语句,DDL包括:create drop alter
语法:
create table 表名(字段名一 数据类型,字段名二 数据类型,字段名三 数据类型)
1.2关于masql中的数据类型
varchar 可变长度的字符串
最长255
<img src="https://gitee.com/huizai-175/test-typora-photo2/raw/master/typora/202203131615266.png" alt="image-20210909093847654" style="zoom: 67%;" />
char 定长字符串
- 最长255
int 等于int
- 最长11
bigint 等于long
float 单精度浮点型数据
double 双精度浮点型数据
date 短日期类型
- 年月日
- 默认格式
- %Y-%m-%d
datetime 长日期类型
- 年月日时分秒
- 默认格式
- %Y-%m-%d %h:%i:%s
- 获取当前时间函数
- now() 函数 (带有时分秒)
clob 字符大对象
- 最多储存4G的字符串
-
blob 二进制大对象
- 图片、声音、视频等媒体数据
1.3、创建一个学生表
create table t_student(no int,name varchar(32),sex char(1),age int(3),email varchar(255)
);
查看数据库中有哪些表
show tables;
删除表
drop table if exists 表名;
2、插入数据(增加) insert(DML)
语法:
insert into 表名(字段名1,字段名2,字段名3···) values(值1,值2,值3);
注意:
字段名和值要一一对应,数量对应,数据类型对应
插入学生
insert into t_student (no,name,sex,age,email) values(1,'zhangsan','m',20,'zhangsan@123.com');
insert into t_student (no,name,sex,age,email) values(2,'lisi','m',19,'lisi@123.com');
建表时设置默认值
insert建表时字段名可以省略
str_to_date 将字符串转为日期
语法
str_to_date('字符串日期','日期格式')
日期格式
date_format 格式化日期(查询日期)
把数据库中的日期date类型转化为字符串
date_format(日期类型数据,'日期格式')
展示在表中的都是字符串格式
3.修改 update (DML)
语法:
update 表名 set 字段名1=值1,字段名2=值2,字段名3=值3··· wehere 条件
注意:没有条件限制 会导致所有数据全部更新。
4.删除数据
语法
delete from 表名 where 条件;
注意:
没有条件,整张表会被删除
5.插入多条数据(重要)
语法
insert into t_user (字段名1,字段名2···) values (),(),(),();
6.快速建表
原理:
将一个查询结果当作一张新建表,可以完成表的快速复制。表创建出来,同时表的数据也存在
语法
7.插入表
将查询结果插入到一张表当中
语法
8.快速删除表中的数据
慢方式 (DML)
delete from 表名;
- 缺点:数据删除,在硬盘上的真实储存空间不释放,比较慢
- 优点:支持回滚,后悔了可以在恢复数据 ------------ 语法:rollback;
快方式 (DDL):
truncate table 表名;//删除表中的数据,表还在
- 优点:效率高,一次性截断
- 缺点:不支持回滚
删除表!=删除数据
删除表
drop table 表名;
9.对表结构的修改
- 对表结构的修改需要使用: alter
- 属于DDL语句
- DDL包括:create drop alter
10.约束(很重要)
10.1、什么是约束?
可以用来保证表中数据的完整性有效性。
10.2、约束包括哪些
加到列后面的叫列级约束,没有加到列后面的叫表级约束。
ALTER TABLE t_user ADD unique(username) ;
desc t_user
- 非空约束 not null
- 唯一性约束 unique 有表级约束
- 主键约束 primary key(简称PK) 有表级约束
- 外键约束 foreign key(简称FK)
- 检查约束 check(mysql不支持,oracle支持)
10.2.1非空约束 not null
10.2.2、唯一性约束:unique
- 唯一性约束unique约束的字段不能重复,但是可以为多个null
- 拥有表级约束
新需求–表级约束
name和email两个字段联和起来具有唯一性
像这种约束没有添加在 列的后面,这种约束称为表级约束
什么时候需要使用表级约束?
unique和not null可以联合
10.2.3、主键约束 (primary key,简称PK)
主键约束的相关字语:
- 主键约束:一种约束
- 主键字段:该字段上添加了主键约束,这样的字段叫做:主键字段
- 主键值:主键字段中的每一个值都叫做:主键值
什么是主键?
- 主键值是每一行记录的唯一标识
- 主键值是每一行记录的身份证号
- 一张表主键约束只能有一个
记住:
任何表都应该有主键,没有主键 表无效
主键的特征
not null + unique (主键值不能为空,同时也不能重复)
给一张表添加主键约束
表级约束—复合主键:
一个字段做主键叫做单一主键,多个字段做主键叫做复合主键
主键值建议类型
int
bigint
char等类型
不建议使用:varchar来做主键,因为主键值一般都是数字且都是定长的
主键分类
- 单一主键
- 复合主键
- 自然主键
- 业务主键
自动维护主键值(重要)
- 自增:auto_increment 从1开始,以1递增
- 删除表、创建表、插入表、查询表
10.2.4、外键约束 (foreign key,简称FK) 五星
外键约束的相关属于
- 外键约束:一种约束
- **外键字段:**该字段上添加了外键约束
- **外键值:**外键字段当中的每一个值
案例:
请设计数据库表,来描述“班级和学生信息”
加外键约束
语法+引用:
- 被引用的字段必须要有unique约束
- 外键值可以为null
===========表<完>
1.存储引擎 (了解)
1.1、什么是存储引擎?
存储表或组织数据的方式
1.2、怎么给表添加存储引擎
什么是数据库引擎
数据库引擎是用于存储、处理和保护数据的核心服务。利用数据库引擎可控制访问权限并快速处理事务,从而满足企业内大多数需要处理大量数据的应用程序的要求。 使用数据库引擎创建用于联机事务处理或联机分析处理数据的关系数据库。这包括创建用于存储数据的表和用于查看、管理和保护数据安全的数据库对象(如索引、视图和存储过程)。可以使用 SQL Server Management Studio 管理数据库对象,使用 SQL Server Profiler 捕获服务器事件。
方式
在建表的时候,在小括号的最后,给表指定存储引擎
- ENGINE 来指定存储引擎、
- CHARSET 来指定这张表的字符编码方式
结论:
- mysql默认的储存引擎是: InnoDB
- mysql默认的字符编码方式是:utf8
1.3、怎么查看mysql怎么查看存储引擎
语法
show engines \G // 支持九大搜索引擎,版本不同 支持情况不同
1.4、mysql常用的存储引擎
MyISAM存储引擎?
它管理的表具有以下特征:
存储特点:
可被转化为压缩,只读表来节省空间
缺点:
不支持事务机制,安全性低
InnoDB存储引擎
存储特点:
- 效率不是很高,不能压缩
- 安全性高(支持事务)
MEMORY存储引擎?
存储特点
- 查询效率最高,不需要和硬盘交互
- 不安全,关机后数据消失。(因为数据和索引都在内存当中)
2.事务概述(重要且精通)
2.1、什么是事务
- 一个事务就是一个完整的业务逻辑。
- 是一个最小的工作单元,不可再分
- 多条语句捆绑一起,同时成功或同时失败
- 提交(开启事务,语句结束时)和回滚(回滚到上一次 你提交的位置上)
什么是业务逻辑
2.2、只有DML语句才会有事务一说
- insert 增
- delete 删
- update 改
2.3、事务为什么存在?
什么是事务?
事务就是批量的DML语句同时成功,或者同时失败!
2.4事务怎么做到多条语句同时成功和同时失败?
有 用来记录事务性活动的日志文件
2.5、怎么提交事务和回滚事务
语法:
commit //提交事务
rollback //回滚事务
事务对应的英语单词是: transaction
在mysql默认的事务行为是什么
关闭自动提交功能
开发的时候j建议关闭,输入多条语句后 利用 commit提交(在输入rollback就不能撤销成功了,表已经不能被改变)
开启事务,即关闭自动提交功能。
start transaction; //开启事务,即关闭自动提交功能
2.6、事务包括四个特性
- A:原子性(最小的工作单元,不能再分)
- C:一致性(所有事务要求,在同一个事务当中,所有操作必须同时成功或同时失败,以保证事务的一致性)
- I:隔离性(A事务和B事务之间有一定的隔离,教室A和B中间有一个墙,这个墙就是隔离性)
- D:持久性(事务最终结束的一个保障。事务提交,就相当于将没有保存到硬盘上的数据保存到硬盘上)
事务的隔离性
事务和事务的隔离4级别
读未提交
读已提交
可重复读
序列化/串行化
加深理解
读未提交:read uncommitted(最低隔离级别)
- 什么是读未提交?《没有提交就读到了》
- 事务A可以读取到事务B未提交的数据
- 这种隔离级别存在的问题?
- 脏读现象(Dirty Read)
- 我们称读到了脏数据
- 一旦客户端B的事务因为某种原因回滚,所有的操作都将会被撤销,那客户端A查询到的数据其实就是脏数据:
- 一般都是理论上的,大多数数据库的隔离级别都是二挡起步
- 什么是读未提交?《没有提交就读到了》
读已提交:read committed
是oracle数据库的默认隔离级别
- 什么是读已提交?《提交之后才能读到》
- 事务A只能读到事务B提交之后的数据
- 这种隔离级别解决了什么问题?
- 解决了脏读现象
- 读取的是最真实的数据
- 这种隔离级别存在什么问题?
- 不可重复读取数据
- 不可重复读取数据
- 什么是读已提交?《提交之后才能读到》
可重复读:repeatable read
是mysql中默认的事务隔离级别
- 什么是可重复读?《提交之后也读不到,永远读到的都是刚开启事务时的数据》
- 这种隔离级别解决了什么问题?
- 解决了不可重复读数据
- 存在的问题
- 可能会出现幻影读
- 每一次读取到的数据都是幻象,不够真实
- 这种隔离级别解决了什么问题?
- 什么是可重复读?《提交之后也读不到,永远读到的都是刚开启事务时的数据》
序列化/串行化:serializable(最高隔离级别)
级别最高,效率最低,解决了所有的问题
2.7、查看隔离级别:
isolation 隔离 transaction 事务
SELECT @@tx_isolation
2.8、验证:隔离级别
验证 read uncommitted
验证:read committed
最真实的数据
验证:repeatable read
幻像数据
验证:serializable
3.索引(index)
添加索引
3.1、什么是索引
注意:
- 目录(索引)需要排序,因为只有排序了 才会有区间查找
- 缩小查找范围就是扫描某个区间
3.2、索引的实现原理
主键、id和 tnique约束的会自动创建索引对象
原理:
缩小区间范围,避免全局搜索
3.3、什么时候添加索引?
3.4、索引创建、删除、语法
创建索引
create index (起名) emp_ename_index on [表名(字段名)] emp(ename);
给emp表的ename字段添加索引,起名:emp_ename_index
删除索引
drop index emp_ename_index (索引名) on emp(表名);
将emp表上的emp_ename_index 索引对象删除
3.5、查看一个sql语句是否使用了索引进行检查
explain select * from emp where ename = 'KING'; // explain 解释
扫描14条记录,证明没有使用索引 。 type = All;
数组+数 的结合体(内部算法)
3.6、索引有失效的时候
第一种(%开头)
查询条件以“%”开始的时候,会索引失效
第二种(or)
使用or时,要求两边的字段都要有索引,否则不会走索引
第三种(复合索引右侧)
使用复合索引的时候,没有使用左侧的列查找,索引失效
什么是复合索引?
两个字段,或者更多字段联合起来添加一个索引,叫做复合索引
create index emp_job_sal_index on emp(job,sal) //给两个字段添加索引
第四种(字段运算)
在where中,索引列(字段)参加了运算,索引失效
第五种(函数)
在where当中,索引列使用了函数
3.7、索引优化数据库
索引是各种数据库进行优化的重要手段,优化的时候优先考虑的因素就是索引
分类
4.视图(view)
4.1、什么是视图?
view:站在不同的角度去看待同一份数据
4.2、怎么创建视图?
表复制
create table dept2 as secect * from dept;
创建视图
create view dept2_view as select * from dept2;
删除视图对象
drop view dept2_view;
4.3、用视图可以做什么
4.4、视图对象在实际开发过程有什么用
简化sql语句,方便,简化开发,利于维护。as后面只能使查询语句(DQL语句)
视图对象在数据库中也是以文件的形式存在的
5.DBA常用命令
数据的导入和导出(数据的备份)
数据的导出
注意:
在windows的dos命令窗口中:
mysqldump bjpowernode>D:\bjpowernode.sql -uroot -p123456
导出指定的表
mysqldump bjpowernode emp>D:\bjpowernode.sql -uroot -p123456
数据的导入
注意:
要先登录到mysql数据库服务器上
创建数据库
create database bjpowernode;
使用数据库
use bjpowernode
初始化数据库
source D:\bjpowernode.sql
6.数据库设计的三范式(熟记)
6.1、什么是数据库设计范式
6.2、数据库设计范式共有3个
第一范式
第二范式
第三范式
好处:
案例
第一范式
第二范式
口诀:多对多的设计
多对多,三张表,关系表两个外键
建立三张表,分开写 在写一个关系表(用两个外键做)
第三范式
口诀:一对多的设计
一对多,两张表,多的表加外键
6.3、总结表的设计
6.4、嘱咐一句话
求平均薪水的等级最低的部门的部门名称
薪水最低等级一定最低,但等级最低薪水不一定最低
selectt.*,gradefrom(select d.deptno,avg(sal) as avgsal from emp e join dept d on e.deptno=d.deptno group by d.deptno) tjoinsalgrade sont.avgsal between s.losal and s.hisalwheres.grade=(select grade from salgrade where (select avg(sal) as avgsal from emp group by deptno order by avgsal asc limit 1) between losal and hisal);
JDBC对面的女孩看过来
idea打开mysql架包
打开架包
一、JDBC简介
什么是JDBC
JDBC全称:Java Data Basa Connectivity (java数据库连接)
工作原理
二、使用详情
1、准备工作
2、JDBC编程步骤
小写转大写
加载驱动程序需要的驱动:
把驱动加入到环境变量中
代码:
//1.加载驱动程序
Class.forName("com.mysql.jdbc.Driver"); //反射 mysql驱动名
//2.获得数据库的连接
Connection conn=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/imooc"(地址),"root"(用户名),"root"(密码)); //DriverManager驱动类
//3.通过数据库的连接操作数据库。实现增删改查
Statement stmt=conn.createStatement();
ResultSet rs=stmt.executeQuery("select user_name,age from imooc_goddess");//查询的对象被存在了rs对象中
//rs.next() 返回ture,说明rs里面有数据。返回false,说明rs里面没有数据
while(rs.next()) {System.out.println(rs.getString("user_name"+","+rs.getInt(age)));//如果对象中有数据,就会循环打印出来。没有数据不打印
}
完整代码
//加载驱动–>获取数据库的连接—>操作数据库
package com.imooc.db;1import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;public class DBUtil {//"jdbc:mysql:///imooc"private static final String URL= "jdbc:mysql://127.0.0.1:3306/imooc";private static final String USER= "root";private static final String PASSWORD= "123456";public static void main(String[] args) throws Exception {
// 加载驱动程序,通过类名 反射的将这个类加入到环境变量中Class.forName("com.mysql.jdbc.Driver");Connection conn= DriverManager.getConnection(URL, USER, PASSWORD);Statement stmt= conn.createStatement();ResultSet rs = stmt.executeQuery("select user_name,age from imooc_goddess");while(rs.next()){System.out.println(rs.getString("user_name")+","+rs.getInt("age"));}}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Ai9CRU0-1647160218321)(F:\T笔记\Typora\笔记\三月阶段笔记\数据库阶段\数据库——视频学习(完结).assets\image-20210914092025255.png)]
代码解释
Class.forName(“com.mysql.jdbc.Driver”);
1.使用Class.forName(“com.mysql.jdbc.Driver”)后,jvm会加载这个类 2.加载这个类后,进入com.mysql.jdbc.Driver,会立即注册:
StringBuilder
用法
效率
(1):用法:StringBuffer对象则代表一个字符序列可变的字符串,当一个StringBuffer被创建以后,通过StringBuffer提供的append()、insert()、reverse()、setCharAt()、setLength()等方法可以改变这个字符串对象的字符序列。一旦通过StringBuffer生成了最终想要的字符串,就可以调用它的toString()方法将其转换为一个String对象。
(2):效率:
//第一种方法
StringBuilder sb=new StringBuilder();
sb.Append("123");
sb.Append("456");
string str=sb.ToString();
// 第二种方法
string s1=“123”;
string s2=“456”;
string str=s1+s2;
// 处理大规模的字符串的时候第二种方法效率会变低。
createStatement
Statement stmt=conn.createStatement(参数一,参数二)
createStatement返回的Statement对象是执行sql语句用的
第一个参数可以取值为
ResultSet.RTYPE_FORWORD_ONLY,只可向前滚动;
ResultSet.TYPE_SCROLL_INSENSITIVE,双向滚动,但不及时更新,就是如果数据库里的数据修改过,并不在ResultSet中反应出来。
ResultSet.TYPE_SCROLL_SENSITIVE,双向滚动,并及时跟踪数据库的更新,以便更改ResultSet中的数据。
第二个参数可以取值为
ResultSet.CONCUR_READ_ONLY:这是缺省值,指定不可以更新 ResultSet
ResultSet.CONCUR_UPDATABLE:指定可以更新 ResultSet
浅谈 JDBC 中 CreateStatement 和 PrepareStatement 的区别与优劣。
这俩干的活儿都一样,就是创建了一个对象然后去通过对象调用executeQuery方法来执行sql语句。说是CreateStatement和PrepareStatement的区别,但其实说的就是Statement和PrepareStatement的区别
代码背景:我们有一个数据库,里面有一个user表,有username,userpwd两列。我们要查出这两列的数据。
PrepareStatement可以提高代码的可读性
这是使用CreateStatement方法创建了stmt对象,再通过他查询的一部分语句片段。
String sql = "select * from users where username= '"+username+"' and userpwd='"+userpwd+"'";
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
而下面则是使用了PrepareStatement方法创建了pstmt对象,再通过这个对象查询的一部分语句片段。
String sql = "select * from users where username=? and userpwd=?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, username);
pstmt.setString(2, userpwd);
rs = pstmt.executeQuery();
原来PrepareStatement跟Statement的主要区别就是把上面sql语句中的变量抽出来了
第二点优点。ParperStatement提高了代码的灵活性和执行效率。
PrepareStatement接口是Statement接口的子接口,他继承了Statement接口的所有功能。它主要是拿来解决我们使用Statement对象多次执行同一个SQL语句的效率问题的。ParperStatement接口的机制是在数据库支持预编译的情况下预先将SQL语句编译,当多次执行这条SQL语句时,可以直接执行编译好的SQL语句,这样就大大提高了程序的灵活性和执行效率。
第三点优点安全!
关于List<Map<String, Object>>
参考连接
首先map<String,Object>是定义了一个Map集合变量,然后list<map<String,Object>>是定义了一个List的集合变量,是map的一个集合;map是那个list的其中一个值。
List<Map<String,Object> list=new ArrayList<Map<String,Object>>;
Map<String,Object> map=new HashMap<String,Object>;
list.add(map);//map是list中的其中一个值。
java中的jdbc程序为什么要加finally:
finally的作用是保证无论程序正确执行还是发生异常,都把占用资源的connection给close掉,以释放资源。
与其他语言的模型相比,finally 关键字是对 Java 异常处理模型的最佳补充。finally 结构使代码总会执行,而不管有无异常发生。使用 finally 可以维护对象的内部状态,并可以清理非内存资源。 如果没有 finally,您的代码就会很费解。
finally 块必须与 try 或 try/catch 块配合使用。此外,不可能退出 try 块而不执行其 finally 块。如果 finally 块存在,则它总会执行。
详细步骤
第一步创建项目:
创建jdbc_imooc项目
第二步加入驱动:
- 创建驱动文件
- 找到mysql-connector-java-5.0.8.jar文件
- 复制到lib里面
- 将驱动加入到环境变量中
5.驱动加载成功
第三步连接数据库
- 新建一个DBUtil.java 类
- 用main方法连接数据库
三.详设
原理
解释:
视图层
流程
问题
四、回顾
JDBC的基本概念
MVC三层架构
JDBC的链接方式四种
扩展
jdbc占位符的使用
占位符的使用
避开 sql 需要使用字符串拼接的方式,从而解决 sql 注入的安全风险,
什么是SQL注入?
SQL注入(SQLi)是一种注入攻击,,可以执行恶意SQL语句。它通过将任意SQL代码插入数据库查询,使攻击者能够完全控制Web应用程序后面的数据库服务器。攻击者可以使用SQL注入漏洞绕过应用程序安全措施;可以绕过网页或Web应用程序的身份验证和授权,并检索整个SQL数据库的内容;还可以使用SQL注入来添加,修改和删除数据库中的记录。
SQL注入漏洞可能会影响使用SQL数据库(如MySQL,Oracle,SQL Server或其他)的任何网站或Web应用程序。犯罪分子可能会利用它来未经授权访问用户的敏感数据:客户信息,个人数据,商业机密,知识产权等。SQL注入攻击是最古老,最流行,最危险的Web应用程序漏洞之一。
Statement 接口的两个问题:
第一个问题: 使用 Statement 接口 对象发送的 sql 语句需要再数据库进行一次编译之后成为指令才能执行,
每条 sql 语句都需要编译一次, 这样是很慢的.
第二个问题: 使用 Statement 接口 操作的 sql 语句需要使用字符串的拼接方式实现,
这样的方式可能存在 sql 注入的安全风险并且拼接字符串比较麻烦.
对比 Statement 接口, PreparedStatement 接口的优点:
1.使用该接口操作的 sql 语句会先预先编译成指令在发送给数据库, 数据库就执行指令即可, 这样就提高了一定速度,
2.该接口可以避开 sql 需要使用字符串拼接的方式, 从而解决 sql 注入的安全风险,
而是使用 占位符 (?) 来代替原来的字符串拼接.
jdbc查询展示view
方法一
Connection conn = DBUtil.getconnection();ResultSet res = null;//获取ResultSet结果集try {PreparedStatement preparedStatement = conn.prepareStatement("select *from product");//sql语句编译预处理res = preparedStatement.executeQuery();} catch (SQLException e) {e.printStackTrace();}res.last();//游标移动到查询到的数据库数据记录的最后一条int row = res.getRow();//获取记录的总条数res.beforeFirst();//游标回到第一个记录前的位置System.out.println(row);String arr[] = {"商品", "生产日期", "保质期", "品牌"};//定义表格的列名称String comm[][] = new String[row][4];//row行,4列res.next();//游标回到第一个记录的位置for (int i = 0; i < row; i++) {System.out.println(res.getString("product_name"));comm[i][0] = res.getString("product_name");comm[i][1] = res.getString("product_date");comm[i][2] = res.getString("save_date");comm[i][3] = res.getString("brand");res.next();}// //创建表格JTable productsViewTable = new JTable(comm,arr);//设置单元格的高度productsViewTable.setRowHeight(30);//将表格加入到滚动面板上JScrollPane scrollPane1 =new JScrollPane(productsViewTable);//将滚动面板添加到卡片布局面板上cardP.add(scrollPane1);validate();//设置组件可见pack();//自动调整组建大小使每个组键都能显示
方法二
private void fillStudent() {DefaultTableModel dtm = (DefaultTableModel) stuOwnTable.getModel();dtm.setRowCount(0);Student student = new Student(userIdInfor);try {ArrayList<Student> students = studentController.selectStuMessage(student);for (Student s : students) {Vector v = new Vector();v.add(s.getId());v.add(s.getStudentName());v.add(s.getStudentSex());v.add(s.getStudentGrade());v.add(s.getStudentPass());v.add(s.getTeacherName());v.add(s.getOnTheJob());dtm.addRow(v);}} catch (Exception e) {e.printStackTrace();}}
方法三
JTable scoretable = new JTable();
// 设置表格单元格的高度为30scoretable.setRowHeight(30);
// 将表格加入到滚动面板中JScrollPane scorejsp = new JScrollPane(scoretable);
// 设置滚动面板的位置scorejsp.setBounds(57, 48, 877, 464);
// 将滚动面板添加到面板panel_1.add(scorejsp);try {
// 通过联表查询根据账号查询出对应id所有的成绩List<Class_Score> li = scoreaction1.scoreupdate(String.valueOf(useraction.getUser(no).getId()));for (Class_Score a : li) {System.out.println(a);}panel_1.setLayout(null);Vector<String> score_column = new Vector<>();score_column.add("课程编号");score_column.add("课程名称");score_column.add("课程学分");score_column.add("任课教师");score_column.add("课程成绩");Vector<Vector<String>> score_value = new Vector<>();for (Class_Score c : li) {Vector<String> rowC = new Vector<>();rowC.add(c.getClass_no());rowC.add(c.getClass_name());rowC.add(c.getClass_sco());rowC.add(c.getClass_tea());rowC.add(c.getClass_score());if (c.getIn_del() == 0 && c.getClass_del() == 0) {score_value.add(rowC);}}DefaultTableModel scoremodel = (DefaultTableModel) scoretable.getModel();scoremodel.setDataVector(score_value, score_column);System.out.println("成绩更新了");} catch (Exception e2) {// TODO Auto-generated catch blocke2.printStackTrace();}
方法四
DefaultTableModel model = (DefaultTableModel) bookqueryTable.getModel();// 先清空一遍数据model.getDataVector().clear();Vector<java.io.Serializable> rows = null;if (bookList.size() == 0) {rows = new Vector<>();model.addRow(rows);} else if (bookList.size() > 0) {model.getDataVector().clear();for (Book book : bookList) {rows = new Vector<>();rows.add(book.getId());rows.add(book.getBNo());rows.add(book.getBName());rows.add(book.getBAuthor());rows.add(book.getClassifyName());rows.add(book.getBPublisher());rows.add(book.getBPubdate());rows.add(book.getBPrice());rows.add(book.getBPagesnumber());rows.add(book.getBCount());rows.add(book.getBPlace());rows.add(book.getBState());model.addRow(rows);}}reader = readerAction.getInfo(LoginView.LoginCount);ArrayList<Outlog> logs = outLogAction.queryAll();logs.removeIf(log -> log.getRid() != reader.getId());updateOutlogQueryTable(logs);
初始化表格不可编辑
//表格不可编辑public void noEdit() {//初始化表格this.table = new JTable(new DefaultTableModel()){//表格不允许被编辑public boolean isCellEditable(int row, int column){return false;}};}
备份
private void addCarActionPerformed(ActionEvent e) {int index = productsViewTable.getSelectedRow();//选中的行System.out.println("==========");selectRows();}//选中多行public void selectRows() {int[] rows=productsViewTable.getSelectedRows();for(int i:rows) {System.out.println(i);}
// ArrayList list=new ArrayList();
// for(int i=rows.length-1;i>=0;i--){
//
// }
//
// list.clear();}//选中多行public List<Map<String,Object>> selectRows(JTable table) {//存放选中的行int[] rows=table.getSelectedRows();//获取当前选中的行数,并存入数组中int column = table.getColumnCount();//选中的列数//创建一个保存的集合,用来存放选中的所有行List<Map<String,Object>> object =new ArrayList<Map<String,Object>>();for (int j=0;j<rows.length;j++){//存放选中的行Map<String,Object> row = new HashMap<String,Object>();for(int i=0;i<column;i++) {row.put(,table.getValueAt(rows[j],i));}object.add(row);}return object;}//增加到buy表public void addCar() {Vector<Object> result = selectRows(productsViewTable);for(Object a: result) {System.out.println(a);}// result.clear();}public List<List<Object>> selectRows(JTable table) {//存放选中的行int[] rows=table.getSelectedRows();//获取当前选中的行数,并存入数组中int column = table.getColumnCount();//选中的列数//创建一个保存的集合,用来存放选中的所有行List<List<Object>> object =new ArrayList<List<Object>>();for (int j=0;j<rows.length;j++){//存放选中的行List<Object> row = new ArrayList<Object>();for(int i=0;i<column;i++) {row.add(table.getValueAt(rows[j],i));}object.add(row);}return object;}
ER图
什么是ER图
E-R图也称实体-联系图(Entity Relationship Diagram),提供了表示实体类型、属性和联系的方法,用来描述现实世界的概念模型。
用矩形表示实体型,矩形框内写明实体名;用椭圆表示实体的属性,并用无向边将其与相应的实体型连接起来;用菱形表示实体型之间的联系,在菱形框内写明联系名,并用无向边分别与有关实体型连接起来,同时在无向边旁标上联系的类型(1:1,1:n或m:n)。
基本要素
构成E-R图的基本要素是实体、属性和联系,其表示方法为:
˙实体型:用矩形表示,矩形框内写明实体名;
˙属性:用椭圆形或圆角矩形表示,并用无向边将其与相应的实体连接起来;多值属性由双线连接;主属性名称下加下划线;
˙联系:用菱形表示,菱形框内写明联系名,并用无向边分别与有关实体连接起来,同时在无向边旁标上联系的类型
在E-R图中要明确表明1对多关系,1对1关系和多对多关系。
˙1对1关系在两个实体连线方向写1;
˙1对多关系在1的一方写1,多的一方写N;
˙多对多关系则是在两个实体连线方向各写N,M
ER图元素
实体补充
**弱实体:**一个实体必须依赖于另一个实体存在,那么前者是弱实体,后者是强实体,弱实体必须依赖强实体存在,例如上图的学生实体和成绩单实体,成绩单依赖于学生实体而存在,因此学生是强实体,而成绩单是弱实体。
弱实体和强实体的联系必然只有1:N或者1:1,这是由于弱实体完全依赖于强实体,强实体不存在,那么弱实体就不存在,所以弱实体是完全参与联系的,因此弱实体与联系之间的联系也是用的双线菱形。
**复合实体:**复合实体也称联合实体或桥接实体,常常用于实现两个或多个实体间的M:N联系,它由每个关联实体的主玛组成,用长方体内加一个菱形来表示。
属性的补充
**复合属性(composite attribute):**复合属性是指具有多个属性的组合,例如名字属性,它可以包含姓氏属性和名字属性,如下图:
**多值属性(multivalued attribute):**一个实体的某个属性可以有多个不同的取值,例如一本书的分类属性,这本书有多个分类,例如科学、医学等,这个分类就是多值属性, 用双线椭圆表示。
**派生属性(derivers attribute):**是非永久性存于数据库的属性。派生属性的值可以从别的属性值或其他数据(如当前日期)派生出来,用虚线椭圆表示,如下图。
下面的小组人数就是典型的派生属性,随着学生实例的参加的兴趣小组变化,小组人数属性也会变化,一般来讲派生属性不存在于数据库中,而是通过相应的公式进行计算得到,如果要放到数据库中,那么隔一段时间就要进行更新
**可选属性(optional attribute):**并不是所有的属性都必须有值,有些属性的可以没有值,这就是可选属性,在椭圆的文字后用(O)来表示,如下图的地址就是一个可选属性。
**联系属性:**联系属于用户表示多个实体之间联系所具有的属性,一般来讲M:N的两个实体的联系具有联系属性,在1:1和1:M的实体联系中联系属性并不必要。
扩展知识
MVC
什么是MVC_老赵学习专栏-CSDN博客_mvc
MVC的优点:
1.耦合性低
视图层和业务层分离,这样就允许更改视图层代码而不用重新编译模型和控制器代码,同样,一个应用的业务流程或者业务规则的改变只需要改动MVC的模型层即可。因为模型与控制器和视图相分离,所以很容易改变应用程序的数据层和业务规则。
2.重用性高
MVC模式允许使用各种不同样式的视图来访问同一个服务器端的代码,因为多个视图能共享一个模型,它包括任何WEB(HTTP)浏览器或者无线浏览器(wap),比如,用户可以通过电脑也可通过手机来订购某样产品,虽然订购的方式不一样,但处理订购产品的方式是一样的。由于模型返回的数据没有进行格式化,所以同样的构件能被不同的界面使用。
3.部署快,生命周期成本低
MVC使开发和维护用户接口的技术含量降低。使用MVC模式使开发时间得到相当大的缩减,它使程序员(Java开发人员)集中精力于业务逻辑,界面程序员(HTML和JSP开发人员)集中精力于表现形式上。
4.可维护性高
分离视图层和业务逻辑层也使得WEB应用更易于维护和修改。
MVC的缺点:
1.完全理解MVC比较复杂。
由于MVC模式提出的时间不长,加上同学们的实践经验不足,所以完全理解并掌握MVC不是一个很容易的过程。
2.调试困难。
因为模型和视图要严格的分离,这样也给调试应用程序带来了一定的困难,每个构件在使用之前都需要经过彻底的测试。
3.不适合小型,中等规模的应用程序
在一个中小型的应用程序中,强制性的使用MVC进行开发,往往会花费大量时间,并且不能体现MVC的优势,同时会使开发变得繁琐。
4.增加系统结构和实现的复杂性
对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率。
5.视图与控制器间的过于紧密的连接并且降低了视图对模型数据的访问
视图与控制器是相互分离,但却是联系紧密的部件,视图没有控制器的存在,其应用是很有限的,反之亦然,这样就妨碍了他们的独立重用。
依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。
高内聚低耦合
一个模块内各个元素的联系性高,而所有模块之间的独立性又很强。
耦合性:也称块间联系。指软件系统结构中各模块间相互联系紧密程度的一种度量。模块之间联系越紧密,其耦合性就越强,模块的独立性则越差。模块间耦合高低取决于模块间接口的复杂性、调用的方式及传递的信息。
内聚性:又称块内联系。指模块的功能强度的度量,即一个模块内部各个元素彼此结合的紧密程度的度量。若一个模块内各元素(语名之间、程序段之间)联系的越紧密,则它的内聚性就越高。
耦合性是编程中的一个判断代码模块构成质量的属性,不影响已有功能,但影响未来拓展,与之对应的是内聚性。
因此,现代程序讲究高内聚低耦合,即将功能内聚在同一模块,模块与模块间尽可能独立,互相依赖低。没有绝对没有耦合的模块组,只有尽量降低互相之间的影响。使模块越独立越好
this关键字
静态方法
语法规定:静态成员不能直接访问非静态成员。static不能访问非static方法
代码块的分类和执行顺序
基本上代码块分为三种:Static静态代码块、构造代码块、普通代码块
代码块执行顺序静态代码块——> 构造代码块 ——> 构造函数——> 普通代码块
继承中代码块执行顺序:父类静态块——>子类静态块——>父类代码块——>父类构造器——>子类代码块——>子类构造器
深入理解static
深入理解static关键字
1、static存在的主要意义
static的主要意义是在于创建独立于具体对象的域变量或者方法。以致于即使没有创建对象,也能使用属性和调用方法!
static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。
为什么说static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次。因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。
2、static的独特之处
1、被static修饰的变量或者方法是独立于该类的任何对象,也就是说,这些变量和方法不属于任何一个实例对象,而是被类的实例对象所共享。
怎么理解 “被类的实例对象所共享” 这句话呢?就是说,一个类的静态成员,它是属于大伙的【大伙指的是这个类的多个对象实例,我们都知道一个类可以创建多个实例!】,所有的类对象共享的,不像成员变量是自个的【自个指的是这个类的单个实例对象】…我觉得我已经讲的很通俗了,你明白了咩?
2、在该类被第一次加载的时候,就会去加载被static修饰的部分,而且只在类第一次使用时加载并进行初始化,注意这是第一次用就要初始化,后面根据需要是可以再次赋值的。
3、static变量值在类加载的时候分配空间,以后创建类对象的时候不会重新分配。赋值的话,是可以任意赋值的!
4、被static修饰的变量或者方法是优先于对象存在的,也就是说当一个类加载完毕之后,即便没有创建对象,也可以去访问。
3、static应用场景
因为static是被类的实例对象所共享,因此如果某个成员变量是被所有对象所共享的,那么这个成员变量就应该定义为静态变量。
因此比较常见的static应用场景有:
1、修饰成员变量
2、修饰成员方法
3、静态代码块
4、修饰类【只能修饰内部类也就是静态内部类】
5、静态导包
以上的应用场景将会在下文陆续讲到…
4、静态变量和实例变量的概念
静态变量:
static修饰的成员变量叫做静态变量【也叫做类变量】,静态变量是属于这个类,而不是属于是对象。
实例变量:
没有被static修饰的成员变量叫做实例变量,实例变量是属于这个类的实例对象。
还有一点需要注意的是:static是不允许用来修饰局部变量,不要问我问什么,因为java规定的!
5、静态变量和实例变量区别【重点常用】
静态变量:
静态变量由于不属于任何实例对象,属于类的,所以在内存中只会有一份,在类的加载过程中,JVM只为静态变量分配一次内存空间。
实例变量:
每次创建对象,都会为每个对象分配成员变量内存空间,实例变量是属于实例对象的,在内存中,创建几次对象,就有几份成员变量。
6、访问静态变量和实例变量的两种方式
我们都知道静态变量是属于这个类,而不是属于是对象,static独立于对象。
7、static静态方法
static修饰的方法也叫做静态方法,不知道各位发现咩有,其实我们最熟悉的static静态方法就是main方法了小白童鞋:喔好像真的是哦。由于对于静态方法来说是不属于任何实例对象的,this指的是当前对象,因为static静态方法不属于任何对象,所以就谈不上this了。
还有一点就是:构造方法不是静态方法!
8、static静态代码块
9、static变量与普通变量区别
static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
还有一点就是static成员变量的初始化顺序按照定义的顺序进行初始化。
10、静态内部类
静态内部类与非静态内部类之间存在一个最大的区别,我们知道非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围内,但是静态内部类却没有。没有这个引用就意味着:
1、它的创建是不需要依赖外围类的创建。
2、它不能使用任何外围类的非static成员变量和方法。
11、静态导包
静态导包格式:import static
这两个关键字连用可以指定导入某个类中的指定静态资源,并且不需要使用类名调用类中静态成员,可以直接使用类中静态成员变量和成员方法
// Math. --- 将Math中的所有静态资源导入,这时候可以直接使用里面的静态方法,而不用通过类名进行调用
// 如果只想导入单一某个静态方法,只需要将换成对应的方法名即可import static java.lang.Math.;
// 换成import static java.lang.Math.max;具有一样的效果public class Demo {public static void main(String[] args) {int max = max(1,2);System.out.println(max);}
}
静态导包在书写代码的时候确实能省一点代码,可以直接调用里面的静态成员,但是会影响代码可读性,所以开发中一般情况下不建议这么使用。
12、static注意事项
1、静态只能访问静态。
2、非静态既可以访问非静态的,也可以访问静态的。
13、final与static的藕断丝连
到这里文章本该结束了的,但是static的使用始终离不开final字眼,二者可谓藕断丝连,常常繁见,我觉得还是很有必要讲讲,那么一起来看看下面这个程序吧。
package Demo;class FinalDemo {public final double i = Math.random();public static double t = Math.random();
}public class DemoDemo {public static void main(String[] args) {FinalDemo demo1 = new FinalDemo();FinalDemo demo2 = new FinalDemo();System.out.println("final修饰的 i=" + demo1.i);System.out.println("static修饰的 t=" + demo1.t);System.out.println("final修饰的 i=" + demo2.i);System.out.println("static修饰的 t=" + demo2.t);System.out.println("t+1= "+ ++demo2.t );
// System.out.println( ++demo2.i );//编译失败}
}
运行结果:final修饰的 i=0.7282093281367935static修饰的 t=0.30720545678577604final修饰的 i=0.8106990945706758static修饰的 t=0.30720545678577604t+1= 1.307205456785776
static修饰的变量没有发生变化是因为static作用于成员变量只是用来表示保存一份副本,其不会发生变化。怎么理解这个副本呢?其实static修饰的在类加载的时候就加载完成了(初始化),而且只会加载一次也就是说初始化一次,所以不会发生变化!
至于final修饰的反而发生变化了?是不是巅覆你对final的看法?关于final详细讲解博主也准备好了一篇文章程序员你真的理解final关键字吗?
深入理解类的加载
深入理解类的加载
理解execute
executeQuery、executeUpdate 和 execute 的区别 ,DDL、DML、DCL、TCL的区别
理解HashMap
参考连接
HashMap的工作原理以及存取方法过程
HashMap的工作原理 :HashMap是基于散列法(又称哈希法hashing)的原理,使用put(key, value)存储对象到HashMap中,使用get(key)从HashMap中获取对象。当我们给put()方法传递键和值时,我们先对键调用hashCode()方法,返回的hashCode用于找到bucket(桶)位置来储存Entry对象。”HashMap是在bucket中储存键对象和值对象,作为Map.Entry。并不是仅仅只在bucket中存储值。
HashMap具体的存取过程如下:
put键值对的方法的过程是:
1、获取key ;
2、通过hash函数得到hash值;
int hash=key.hashCode(); //获取key的hashCode,这个值是一个固定的int值
3、得到桶号(一般都为hash值对桶数求模) ,也即数组下标int index=hash%Entry[].length。//获取数组下标:key的hash值对Entry数组长度进行取余
4、 存放key和value在桶内。
table[index]=Entry对象;
get值方法的过程是:
1、获取key
2、通过hash函数得到hash值
int hash=key.hashCode();
3、得到桶号(一般都为hash值对桶数求模)
int index =hash%Entry[].length;
4、比较桶的内部元素是否与key相等,若都不相等,则没有找到。
5、取出相等的记录的value。
HashMap中直接地址用hash函数生成;解决冲突,用比较函数解决。如果每个桶内部只有一个元素,那么查找的时候只有一次比较。当许多桶内没有值时,许多查询就会更快了(指查不到的时候)。
遍历数组的几种方法
数组
package For_05;import java.util.Arrays;import javax.swing.Box.Filler;public class demo_03 {
public static void main(String[] args) {int [] a = {2,8,5,3,4,7,5,2,1};int [] b = new int [] {2,8,5,3,4,7,5,2,1};int [] c = new int[6];int mid=0;
// for(int i=0,j=a.length-1;i<a.length/2;i++,j--) {
// mid=a[i];
// a[i]=a[j];
// a[j]=mid;
//
// }
// System.out.println(Arrays.toString(a));for(int i:a) {System.out.print(i);}}}/* for(int i=0;i<a.length;i++) {System.out.println(a[i]);}
//一for(int i:a) {System.out.println(i);}
//二System.out.println(
);
// 三
// demo_01.printarray(a);
//四
*/ //遍历数组/* int mid =0;for(int i=0;i<a.length -1;i++) {for(int j=0;j<a.length-1-i;j++) {if(a[j]>a[j+1]) {mid=a[j+1];
// a[j]=a[j+1];a[j+1]=a[j];a[j]=mid;}}// }System.out.println(a[i]);}System.out.println(Arrays.toString(a));
}
}/* for (int i = 0;i < a.length -1;++i){//将第一个数从头比较到最后一个数for (int j = 0;j < a.length-1-i;++j){//若是后面的数比前面的数大,就进行交换if (a[j] < a[j + 1]){int b = a[j];a[j] = a[j + 1];a[j + 1] = b;}}System.out.println(a[i]);
}
}
}*/ //数组排序/冒号排序/*
Arrays.fill(a, 3);
System.out.println(Arrays.toString(a));
//数组填充*/
//}
//}/* int sum=0;
// for(int i=0;i<a.length;i++) {//36为什么for( int i:a) { //37sum +=i;} System.out.println(sum);}
}*/ //求和
遍历集合的方法
https://blog.csdn.net/lixibin0829/article/details/79336607
Java提供了四种在集合上遍历的方法,包括循环,迭代和forEach(从Java 8开始)
before going to each kind of iteration, suppose that we have a List collection as follows:
在学习每种遍历方式之前,我们需要现有一组List集合:
public static void main(String[] args) {List<String> listNames = new ArrayList<>();listNames.add("qiuqiu");listNames.add("kaka");listNames.add("beibei");listNames.add("hutu");listNames.add("wangzai");} public static void main(String[] args) {List<String> listNames = new ArrayList<>();listNames.add("qiuqiu");listNames.add("kaka");listNames.add("beibei");listNames.add("hutu");listNames.add("wangzai");}
This list contains names of all students in a class. Note that the diamond operator <> used in the right side of the assignment:
这个list包含我们小区的所有小狗的名字。注意在语句的右边<>的使用
ArrayList<>();
这个语法从Java7开始使用,允许我们以一种更严谨的方式声明泛型的集合,因为编译器可以从左边推测出右边的参数类型(因此叫做“类型引用”)
1. 经典循环方式
这种迭代方法在编程中非常熟悉,其中计数器变量从集合中的第一个元素运行到最后一个元素
for (int i = 0; i < listNames.size(); i++) {String name = listNames.get(i);System.out.println(name);}
pros:
- 这是编程中最熟悉的构造
- 如果我们需要访问并使用计数器变量,比如打印小狗狗们的的数字顺序:1,2,3……
cons:
- 使用计数器变量要求集合必须以基于索引的形式(如ArrayList)存储元素,并且我们必须提前知道集合的大小
该集合必须提供一种通过基于索引的方式访问其元素的方法,这不是所有集合都支持的方式,例如, Set不会将元素存储为基于索引的元素。 因此这种方法不能用于所有集合。
迭代的方式
由于经典循环方式的限制,创建了使用迭代器的方式,这种方式允许我们迭代各种集合。因此你可以看到Collection接口定义了每个集合必须实现iterator()方法
在List上用迭代器遍历:
Iterator<String> itr = listNames.iterator();while (itr.hasNext()) {String name = itr.next();System.out.println(name);}
在Set上用迭代器遍历:
Set<String> set = new HashSet<>();set.add("a");set.add("b");set.add("c");set.add("d");Iterator<String> itr = set.iterator();while (itr.hasNext()) {String letter = itr.next();System.out.println(letter);}
在Map上用迭代器遍历:
Map<String, Integer> grade = new HashMap<>();grade.put("Operating System", 90);grade.put("Computer Network", 92);grade.put("Software Engineering", 90);grade.put("Oracle", 90);Iterator<String> itr = grade.keySet().iterator();while (itr.hasNext()) {String key = itr.next();Integer value = grade.get(key);System.out.println(key + "=>" + value);}
加强for循环
从Java 5开始,程序员可以使用一种更简洁的语法来遍历集合-加强for循环。
for (String s : listNames) {System.out.println(s);}
注意:
加强for循环实际上在背后使用的是迭代器。这意味着编译时Java编译器会将增强型for循环语法转换为迭代器构造。 新的语法为程序员提供了一种更方便的迭代集合的方式。
使用Lambda表达式的forEach
Java 8引入了Lambda表达式,介绍了一种遍历集合的全新方式-forEach方法
listNames.forEach(name -> System.out.println(name));
forEach方法与之前的方法最大的区别是什么?
在之前的方法中(经典for循环,迭代器和加强for循环),程序员可以控制集合是如何迭代的。迭代代码不是集合本身的一部分 - 它是由程序员编写的 - 因此称为外部迭代。
相比之下,新方法将迭代代码封装在集合本身中,因此程序员不必为迭代集合编写代码。 相反,程序员会在每次迭代中指定要做什么 - 这是最大的区别! 因此术语内部迭代:集合处理迭代本身,而程序员传递动作 - 即每次迭代需要做的事情。
集合map
java为什么要抛出异常
正如其他答案所指出的那样,throws子句只需要
checked exceptions,这是目前只存在于Java中的一个功能.
关于Java为什么检查异常的官方答案是well documented://有记录的
只有当你的API养成捕获所有异常的习惯并将它们作为适合你的抽象层的东西重新抛出时,才会发现检查异常是有用的.例如,碰巧使用磁盘或SQL后端来缓存数据的内存中对象缓存应该永远不会抛出IOException或SQLException – 相反,它应该抛出(并声明)一些用户定义的异常,如CacheFailureException或类似的异常.
防止jdbc驱动没有,数据库连接时需要类似mysql-connector-java-5.1.36-bin.jar的驱动包,否则无法连接,如果是这种错误就可以抛出异常,方便查找错误。
下面一个防止数据库访问异常,应该是为了防止数据库连接信息错误而抛出的异常,如果出错则提醒要检查数据库连接信息是否正确。
见到的方法
toUpperCase()
将所有的英文字符转换为大写字母
toLowerCase()
将所有的英文字符转换为小写字母
next()和hasnext()
参考链接
SimpleDateFormat
SimpleDateFormat设置日期格式
format()方法将日期转换为字符串
parse()方法将字符串转换为日期
获取密码框的值
String userPassword = new String(passWordField.getPassword());
.next
1、.next()方法的作用:指针指向下一条记录,有记录(有值)返回true并把记录内容存入到对应的对象中,也就是obj.next()的obj中。如果没有返回false。
2、.next()方法的应用:一般和ResultSet对象和while循环一起使用,去迭代结果集,并在循环中调用getXXX(intfieldIndex)/getXXX(String columnName)方法获取字段值。
过程:ResultSet对象具有指向其当前数据行的指针。开始,指针被置于第一行。.next()方法将指针移动到下一行,然后while循环迭代遍历ResultSet对象。
while (obj.next()) {
}
光标移动到下一行数据,有值(数据)返回true并迭代遍历,没有返回false退出循环。
.last
LAST() 函数
LAST() 函数返回指定的字段中最后一个记录的值。
提示:可使用 ORDER BY 语句对记录进行排序。
SQL LAST() 语法
SELECT LAST(column_name) FROM table_name
.getRow
不是返回行数,而是返回当前是哪一行
.berforeFirst
ResultSet.beforeFirst():将游标移到第一行前
vector动态数组的遍历
public static void main(String[] args) {Vector<String> t=new Vector<String>();t.add("F");t.add("o");t.add("r");t.add("e");t.add("v"); t.add("e");t.add("r");//第一种for (String string : t) {System.err.print(string);}//第二种t.forEach(new Consumer<String>() {@Overridepublic void accept(String t) {// TODO Auto-generated method stubSystem.out.print(t); }});//第三种for (int i = 0; i < t.size(); i++) {System.out.print(t.get(i)); }//第四种Iterator<String> it = t.iterator();while (it.hasNext()) {String string = (String) it.next();System.err.print(string);}//第五种Enumeration<String> enume = t.elements();while(enume.hasMoreElements()){System.out.print(enume.nextElement().toString());}
获取当前时间,并调整格式
通过Date类来获取当前时间 :import java.util.Date;
Date date = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(df.format(date));
idea使用教程
快捷键
\1. Ctrl + Space
完成类、方法、变量名称的自动输入,这个快捷键是我最经常使用的快捷键了,它可以完成类、方法、变量名称的自动录入,很方便
\2. Ctrl + N(Ctrl + Shift + N)
跳转到指定的java文件(其它文件)这个功能很方便,至少我不用每回都在一长串的文件列表里找寻我想要编辑的类文件和jsp文件了
\3. Ctrl + B
跳转到定义处这个就不用多说了,好象是个IDE就会提供的功能
\4. Ctrl + Alt + T
用*来围绕选中的代码行( * 包括if、while、try catch等)这个功能也很方便,把我以前要做的:①先写if-else,②然后调整代码的缩进格式,还要注意括号是否匹配了,现在用这个功能来做,省事多了(不过让我变得越来越懒了)
\5. Ctrl + Alt + B
跳转到方法实现处这个也算是很普遍的功能了,就不多说了。
\6. Ctrl + W
按一个word来进行选择操作在IDEA里的这个快捷键功能是先选择光标所在字符处的单词,然后是选择源
代码的扩展区域。举例来说,对下边这个语句java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat(“yyyy-MM-dd HH:mm”);当光标的位置在双引号内的字符串中时,会先选中这个字符串,然后是等号右边的表达式,再是整个句子。我一般都是在对代码进行重新修改的时候使用
它来选择出那些长长的复合表达式,很方便:)
\7. Shift + F1
在浏览器中显示指定的java docs,这个也应该是几乎所有的java ide都提供的功能,就不多说了。
\8. Ctrl + Q
在editor window中显示java docs这个功能很方便–因为有时仅仅是忘记了自己编写的方法中的某个参数的含义,此时又不想再起一个浏览器来查看java doc,此时这个功能的好处就体现出来了
\9. Ctrl + /
注释/反注释指定的语句,这个功能很象PB中提供的一个功能,它可以注释和反注释你所选择的语句(使用单行注释符号"//"),你也可以用Ctrl + Shift + / 来进行多行语句的注释(即使用多行注释符号"/* … */")
\10. F2/Shift + F2
跳转到下/上一个错误语句处IDEA提供了一个在错误语句之间方便的跳转的功能,你使用这个快捷键可以快捷在出错的语句之间进行跳转。
\11. Shift + F6
提供对方法、变量的重命名对IDEA提供的Refector功能我用得比较少,相比之下这个功能是我用得最多的了。对于这个功能没什么可说的了,确实很方便,赶快试一试吧。
\12. Ctrl + Alt + L
根据模板格式化选择的代码,根据模板中设定的格式来format你的java代码,不过可惜的是只对java文件有效
\13. Ctrl + Alt + I
将选中的代码进行自动缩进编排这个功能在编辑jsp文件的时候也可以工作,提供了一个对上边格式化代码功能的补充。
\14. Ctrl + Alt + O
优化import自动去除无用的import语句,蛮不错的一个功能。
\15. Ctrl + ]/[
跳转到代码块结束/开始处,这个功能vi也有,也是很常用的一个代码编辑功能了。
16.Ctrl+E
可以显示最近编辑的文件列表
17.Shift+Click
可以关闭文件
18.Ctrl+Shift+Backspace
可以跳转到上次编辑的地方
19.Ctrl+F12
可以显示当前文件的结构
20.Ctrl+F7
可以查询当前元素在当前文件中的引用,然后按F3可以选择
21.Ctrl+Shift+N
可以快速打开文件
22.Alt+Q
可以看到当前方法的声明
23.Ctrl+P
可以显示参数信息
25.Alt+Insert
可以生成构造器/Getter/Setter等
26.Ctrl+Alt+V
可以引入变量。例如把括号内的SQL赋成一个变量
27.Alt+Up and Alt+Down
可在方法间快速移动
下面的不是很有用
28.Alt+Enter
可以得到一些Intention Action,例如将”==”改为”equals()”
29.Ctrl+Shift+Alt+N
可以快速打开符号
30.Ctrl+Shift+Space
在很多时候都能够给出Smart提示
31.Alt+F3
可以快速寻找
32.Ctrl+O
可以选择父类的方法进行重写
33.Ctrl+Alt+Space
是类名自动完成
\34. Ctrl+J
Live Templates!
35.Ctrl+Shift+F7
可以高亮当前元素在当前文件中的使用
30.Ctrl+Alt+Up /Ctrl+Alt+Down
可以快速跳转搜索结果
31.Ctrl+Shift+J
可以整合两行
32.Alt+F8是计算变量值
Ctrl+D 复制上一行或复制选定
Ctrl+Alt+L 格式化代码
Alt+Shift+Insert 列编辑
Java几种消息对话框的弹出
1.showMessageDialog(只显示一个确定按钮的对话框)
普通对话框Java代码
JOptionPane.showMessageDialog(null, "普通对话框");
其中null是一个参数parentComponent,一般情况下,我们使用这个对话框,设置为null就可以了。
警示框Java代码
JOptionPane.showMessageDialog(null, "警告提示框", "Title",JOptionPane.WARNING_MESSAGE);
错误提示框Java代码
JOptionPane.showMessageDialog(null, "错误提示框", "Title",JOptionPane.ERROR_MESSAGE);
基本提示框java代码
JOptionPane.showMessageDialog(null, "最基本提示框", "Title",JOptionPane.PLAIN_MESSAGE);
2.showConfirmDialog
(确认对话框,对话框的按钮通常为:“是”、“否”、“取消”和“确认”及其组合)。
“是” “否”对话框Java代码
nt n = JOptionPane.showConfirmDialog(null, "你是否喜欢Java?", "Title",JOptionPane.YES_NO_OPTION);
3.showOptionDialog(自定义选择提示对话框)
Java代码
Object[] options ={ "喜欢", "不喜欢" }; //自定义按钮上的文字
int m = JOptionPane.showOptionDialog(null, "你喜欢这篇博客吗?", "Title",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
4.showInputDialog(下拉框或者输入框)
下拉框Java代码
Object[] options ={ "苹果", "橘子", "香蕉" };
String s = (String) JOptionPane.showInputDialog(null,"请选择你喜欢吃的水果:\n", "水果", JOptionPane.PLAIN_MESSAGE, new ImageIcon("xx.png"), options, "xx");
输入框Java代码
JOptionPane.showInputDialog(null," Please input:\n","title",JOptionPane.PLAIN_MESSAGE);
java正则的使用
参考连接
String regExp = "^1[3-9]\\d{9}$";boolean flag = phoneNumberText.matches(regExp);System.out.println(flag);
Java_Swing中关于关闭窗口的方法
1、关闭子窗口后,父窗口也跟着关闭,子窗口设置为:
setDefaultCloseOption(Jframe.Exit_ON_CLOSE);
2、只关闭子窗口,子窗口设置为:
setDefaultCloseOption(Jframe.DISPOSE_ON_CLOSE);
3、dispose()方法,如果是继承的JFrame类,直接调dispose()方法,如果是new的JFrame对象,用JFrame对象.dispose();
this.dispose();
Frame.dispose();
4、setVisible(false)方法,(该方法仅仅隐藏窗体)
this.setVisible(false)
使用dispose()和setVisible()方法,在表象上没有任何区别,它们的实质区别在于setVisible方法仅仅隐藏窗体,而dispose方法是关闭窗体,并释放一部分资源。
frame的System.exit(0)关闭方法如下:
this.addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent e) { System.exit(0);
}
}
//System.exit(0)是将你的整个虚拟机里的内容都停掉了 ,而dispose()只是关闭这个窗口
idea快捷键
一键格式化代码: Ctrl+Alt+L
全局搜索替换:ctrl+shift+r
强大的搜索功能,shift+shift (无论您想要搜啥都能找到)
ctrl+shift+R==搜索类 CTRL+N:按照类名搜索类
idea格式化代码时,注释被格式化问题
解决方案
将enable javadoc formating取消掉
String、StringBuffer和StringBuilder的区别
String
String类是不可变类,即一旦一个String对象被创建以后,包含在这个对象中的字符序列是不可改变的,直至这个对象被销毁。
这个是String类的解释,之前小咸儿看到这个情况,不能理解上述的解释,如下
String a = "123";
a = "456";
// 打印出来的a为456
System.out.println(a)
a对象的内存存储空间图
可以看出来,再次给a赋值时,并不是对原来堆中实例对象进行重新赋值,而是生成一个新的实例对象,并且指向“456”这个字符串,a则指向最新生成的实例对象,之前的实例对象仍然存在,如果没有被再次引用,则会被垃圾回收。
StringBuffer
StringBuffer对象则代表一个字符序列可变的字符串,当一个StringBuffer被创建以后,通过StringBuffer提供的append()、insert()、reverse()、setCharAt()、setLength()等方法可以改变这个字符串对象的字符序列。一旦通过StringBuffer生成了最终想要的字符串,就可以调用它的toString()方法将其转换为一个String对象。
StringBuffer b = new StringBuffer("123");
b.append("456");
// b打印结果为:123456
System.out.println(b);
在看一下b对象的内存空间图:
所以说StringBuffer对象是一个字符序列可变的字符串,它没有重新生成一个对象,而且在原来的对象中可以连接新的字符串。
StringBuilder
StringBuilder类也代表可变字符串对象。实际上,StringBuilder和StringBuffer基本相似,两个类的构造器和方法也基本相同。不同的是:StringBuffer是线程安全的,而StringBuilder则没有实现线程安全功能,所以性能略高。
StringBuffer是如何实现线程安全的呢?
StringBuffer类中实现的方法:
StringBuilder类中实现的方法:
由此可见,StringBuffer类中的方法都添加了synchronized关键字,也就是给这个方法添加了一个锁,用来保证线程安全。
如何在单个窗口打开多个Maven工程啊?
答:随便新建一个文件夹,然后将工程都扔进去,使用IDEA打开这个文件夹。
package com.zwwhnly.springbootdemo;
import java.text.SimpleDateFormat;
import java.util.Date; public class SimpleDateFormatDemo {public static void main(String[] args) {Date currentTime = new Date();System.out.println(currentTime); // Mon Feb 18 13:53:50 CST 2019SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyy-MM-dd");SimpleDateFormat simpleDateFormat3 = new SimpleDateFormat("yyyy/MM/dd");System.out.println(simpleDateFormat1.format(currentTime)); // 输出2019-02-18 13:53:50.629System.out.println(simpleDateFormat2.format(currentTime)); // 输出2019-02-18System.out.println(simpleDateFormat3.format(currentTime)); // 输出2019/02/18}}
//输入add时走这个分支else if(OPERATION_ADD.equals(in.toUpperCase())|| OPERATION_ADD.substring(0,1).equals(in.toUpperCase())|| OPERATION_ADD.equals(prenious)){//当你输入的信息与上一次相等时,执行下列代码prenious = OPERATION_ADD;
//新增女神//如果第一次进来我们就输入女神的姓名if(1==step) {System.out.println("请输入女神的姓名:");}else if(2==step) {//第二次进入,默认认为已经输入了女神的姓名,把女神的姓名存到女神类(对象里)goddess.setUser_name(in); //女神姓名已经保存,请输入女神的年龄System.out.println("请输入女神的年龄"); }else if(3==step) {goddess.setAge(Integer.valueOf(in));System.out.println("请输入女神的生日,格式:yyyy-MM-dd"); }else if(4==step) {SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");Date birthday = null;try {birthday = sf.parse(in);goddess.setBirthday(birthday);System.out.println("请输入女神的邮箱");} catch (ParseException e) {e.printStackTrace();System.out.println("你输入的格式有无误,请重新输入");step = 3;}}else if(5==step) {goddess.setEmail(in);System.out.println("请输入女神的手机号");}else if(6==step) {goddess.setMobile(in);//所有信息已经输入ok,调用action层的方法try {action.add(goddess);System.out.println("新增女神成功");} catch (Exception e) {e.printStackTrace();System.out.println("新增女神失败");}}
// System.out.println("请输入女神的姓名:");
// System.out.println("输入女神的姓名为:"+in);if(OPERATION_ADD.equals(prenious)){step++;}}//否则打印你输入的值else {System.out.println("你输入的值为:"+in);}}
连接池
mysql 数据库连接池
一.什么是数据库连接池
官方:数据库连接池是程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由程序动态的对池中的连接进行申请、使用、释放。
个人理解:创建数据库连接是一个很耗时的操作,也容易对数据库造成安全隐患。所以,在程序初始化的时候,集中创建多个数据库连接,并把他们集中管理,供程序使用,可以使用保证较快的数据库读写速度,还更加安全可靠。
二.传统的连接机制与数据库连接池的运行机制区别
传统连接:一般来说,java应用程序访问数据库的过程是:
①装载数据库驱动程序
②通过JDBC建立数据库连接
③访问数据库,执行sql语句
④断开数据库连接
使用了数据库连接池的机制:
①程序初始化时创建连接池
②使用时向连接池申请可用连接
③使用完毕,将连接返还给连接池
④程序退出,断开所有的连接,并释放资源。
三.为什么要使用连接池
假设网站一天有很大的访问量,数据库服务器就需要为每次连接创建一次数据库连接,极大浪费数据库的资源,并且造成数据库服务器的内存溢出、拓机。
数据库连接是一种关键的有限的昂贵的资源,对数据库的连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标。数据库连接池正是针对这个问题提出来的,数据库连接池负责分配,管理和释放数据库连接,它允许重复使用一个现有的数据库连接而不是重新建立一个。
数据库连接池在初始化时将建立一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的,无论这些数据库连接是否被使用,连接池都将一直保持至少这么多的连接数量,连接池的最大链接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大链接数量的时候,这些去请求将被加入到等待的队列中。
最小连接数:连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费。
最大连接数:是连接池能申请的最大连接数,如果数据库连接请求超过次数,后面的数据库连接请求将被加入到等待队列中,这会影响以后的数据库操作。
如果最小连接数和最大连接数相差很大,那么最先连接请求将会获利,之后超过最小的连接数据量的连接请求等价于建立一个新的数据库连接,不过,这些大于最小连接数的数据库连接在使用完不会马上被释放,它将会被放在连接池中等待重复使用或者在空间超过后被释放。
四.常用的开源数据库连接池
1.dbcp
①导入相关的jar包
commons-dbcp2-2.1.1.jar
commons-pools2-2.4.2.jar
commons-logging-1.2.jar
②在项目根目录增加配置文件
dbcp.properties
数据的加密、解密方式
MySQL数据加密与解密_Andrew’s Blog-CSDN博客_mysql加密解密
1.测试环境 MySQL 8.0 版本 .Net Framework 4.5.2
2.MySQL 自带的加密函数:aes_encrypt() 解密函数 aes_decrypt()
3.插入数据加密
INSERT INTO XXX VALUES(' aes_encrypt('加密的数据','密码')');
4.查询数据解密
4.查询数据解密
SELECT aes_decrypt(`列属性值`,'密码') FROM XXX;
5.注:使用aes_encrypt()加密后数据为二进制类型。取出数据的方法
一:需设置字段类型为二进制字段属性(blob类型)
二:将密文十六进制化,再存入varchar/char列。需要用到HEX()来存入,用UNHEX()取出。(未验证)
6.读取MySQL数据库的blob对象
//方法一:使用反序列化(测试未通过 异常:分析完成之前遇到流结尾)(可能是数据源本身问题)
//使用MySqlDataReader对象 获取读取的byte[]类型 blobMemoryStream ms = new MemoryStream(blob);ms.Position = 0;BinaryFormatter bFormatter = new BinaryFormatter()Object obj =bFormatter.Deserialize(ms);int[] arr = (int[])obj;ms.Close();string arrStr = "";for (int i = 0; i < arr.GetLength(0); i++){arrStr += arr[i].ToString();} //方法二:直接获取查询结果的byte[] 编码为字符串
byte[] bResult = (byte[])dtResult.Rows[0][0];
string res = System.Text.Encoding.UTF8.GetString(bResult);
级联操作
级联用于设计一对多关系的,例如一个表存放老师的信息:表A(姓名,性别,年龄),姓名为主键。还有一张表存放老师所教的班级信息:表B(姓名,班级)。他们通过姓名来级联。级联的操作有级联更新,级联删除。
启用级联后,更新一个表的主键值,系统会相应地更新所有匹配的外键值,如果在表A中将姓名为张三的记录改为李四,那么表B中的姓名为张三的所有记录也会随着改为李四。级联删除与更新相类似。如果在表A中将姓名为张三的记录删除,那么表B中的姓名为张三的所有记录也将删除。
时间戳
时区问题
不同地区 记录时区和非记录时区,mysql时区问题
.时区问题
发现读出数据库中的时间相差几个小时,这是由于数据库和系统时区差异所造成的。
需要在数据库连接串中设置时区。
serverTimezone=GMT即可解决问题,如果需要使用GMT+8时区,需要写成GMT%2B8,否则会被解析为空。
serverTimezone=GMT%2B8
连接串
jdbc:mysql://localhost:3306/mydb?serverTimezone=GMT%2B8
.乱码问题
发现读出数据库乱码问题,需要设置编码格式。
useUnicode=true
characterEncoding=utf-8
连接串
连接串
jdbc:mysql://localhost:3306/mydb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8
储存时间的问题
不要使用字符创去储存时间,原因如下:
- 字符串占据的空间太大了
- 字符串储存的时间无法使用日期相关的API来进行各种的计算和比较
- 字符串储存的日期效率比较低如果比较的话是逐个字符进行比较的
我们在进行日期格式和转换的时候,经常碰到这两种:
java.sql.Date与java.util.Date二者区别:
java.util.Date是在除了SQL语句的情况下面使用的
java.sql.Date是针对SQL语句使用的,它只包含日期而没有时间部分
二者转换:
- java.sql.Date转为java.util.Date
java.sql.Date date=new java.sql.Date(); java.util.Date d=new java.util.Date (date.getTime());
- java.util.Date转为java.sql.Date
java.util.Date utilDate=new Date();java.sql.Date sqlDate=new java.sql.Date(utilDate.getTime()); java.util.Date utilDate=new Date(); java.sql.Date sqlDate=new java.sql.Date(utilDate.getTime()); java.sql.Time sTime=new java.sql.Time(utilDate.getTime()); java.sql.Timestamp stp=new java.sql.Timestamp(utilDate.getTime());
————————————————
版权声明:本文为CSDN博主「qBegonia」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_47061482/article/details/118407393
idea编码转化
在idea中点击左上角的file—>settiongs->Editor->file Encodings
- 然后再去看我们的配置文件就是正常的汉字了
mysql 单条插入和批量插入
单条插入
import java.sql.SQLException; import java.util.List;import com.mysql.jdbc.Connection;public class OperationPaper {private static Connection connection=Connect_MySQL.getConnection();public void addNewsPaper(NewsPaper newsPaper){//增 // connection = Connect_MySQL.getConnection(); String sql="insert into papertest (id, date, title, lead_pargraph, full_text) values(?, ?, ?, ?, ?)";java.sql.PreparedStatement ptmt = null; try {ptmt = connection.prepareStatement(sql); } catch (SQLException e1) {e1.printStackTrace(); }try {ptmt.setLong(1, newsPaper.getID()); ptmt.setString(2, newsPaper.getDate()); ptmt.setString(3, newsPaper.getTitle()); ptmt.setString(4, newsPaper.getLead()); ptmt.setString(5, newsPaper.getfull()); ptmt.execute();//执行给定的SQL语句,该语句可能返回多个结果} catch (SQLException e) {e.printStackTrace(); } } public static void main(String[] args) {OperationPaper operationPaper = new OperationPaper(); List<String> listFile = SearchFile.getAllFile("E:\\huadai\\1996\\07\\21", false); // 文件列表for (String string : listFile) { NewsPaper newsPaper = new NewsPaper(string); if (newsPaper.isUseful()) operationPaper.addNewsPaper(newsPaper); // 插入数据库 } }}
插入多条语句
import java.sql.SQLException; import java.util.ArrayList; import java.util.List;import com.mysql.jdbc.Connection;public class OperaOnNewsPaper implements Cloneable{private static Connection connection=Connect_MySQL.getConnection();/*** 支持批量插入数据* @param newsPaper*/public void addNewsPaper(ArrayList<NewsPaper> listNewsPaper){//增String sql="insert into papertest (id, date, title, lead_pargraph, full_text) values(?, ?, ?, ?, ?)";java.sql.PreparedStatement ptmt = null;try {connection.setAutoCommit(false);// 关闭事务ptmt = connection.prepareStatement(sql);} catch (SQLException e2) {e2.printStackTrace();} for (NewsPaper paperaper : listNewsPaper) {try {ptmt.setLong(1, paperaper.getID());ptmt.setString(2, paperaper.getDate());ptmt.setString(3, paperaper.getTitle());ptmt.setString(4, paperaper.getLead());ptmt.setString(5, paperaper.getfull());ptmt.addBatch(); } catch (SQLException e) {e.printStackTrace();}}try {ptmt.executeBatch();//执行给定的SQL语句,该语句可能返回多个结果connection.commit();} catch (SQLException e) {e.printStackTrace();}}public static void main(String[] args) {OperaOnNewsPaper operation = new OperaOnNewsPaper();List<String> listFile = SearchFile.getAllFile("E:\\huadai\\2007", false); // 文件列表ArrayList<NewsPaper> listPaper = new ArrayList<>();int count = 0;int sizenum = 1000;for (String string : listFile) {NewsPaper newsPaper = new NewsPaper(string);if (newsPaper.isUseful()) {count++;listPaper.add(newsPaper); // 新闻列表if (count % sizenum == 0) {//System.out.println("ok");System.out.println(" " + count);operation.addNewsPaper(listPaper); //插入数据库System.out.println(count);listPaper.clear();}} }if (count %sizenum != 0) {operation.addNewsPaper(listPaper);System.out.println("zui hou ");} } }
通过实际测试,大概十万级数据批量插入要不单条插入节省10分钟左右时间。因为每次单条插入就要和数据库建立一次连接,进行一次日志更新。但是,如果批量插入过程中,批量的数据值有一条不符合格式就将导致本次批量插入整体失败,因此需要对失败情况进行处理,或者对批量插入的数据进行预处理,保证批量插入能够成功。
著名: 这两种方法的来源均为脚本之家 ,链接附上:java连接mysql数据库实现单条插入和批量插入_java_脚本之家 (jb51.net)
jtree
vector(为什么要用vector插入表格 ) setDataVector
public static List<Map<String,Object>> convertList(ResultSet rs) {// 新建一个map list集合用于存放多条查询记录List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();try {ResultSetMetaData md = rs.getMetaData();// 结果集(rs)的结构信息,比如字段数、字段名等int columnCount = md.getColumnCount();// 取得查询出来的字段个数while (rs.next()) {// 新建一个map集合 将查询出内容按照字段名:值 的键值对形式存储在map集合中Map<String,Object> rowDate = new HashMap<String,Object>();for (int i=0;i<columnCount;i++) {// 循环所有查询出字段rowDate.put(md.getColumnName(i),rs.getObject(i));// getColumnName(i) 获取第i个列名// getObject(i) 获取第i个对象的值}list.add(rowDate);// 将map放入list集合中}} catch (SQLException e) {e.printStackTrace();}finally {// 关闭连接try {if (rs!=null) {rs.close();rs=null;}} catch (SQLException e) {e.printStackTrace();}}return list;}
ResultSet
getMetaData
1、得到查询结果,一个数据集
resultSet2 = stat.executeQuery("select * from "+ table_name + " limit " + pageNum + ",500");
2、得到结果集(rs)的结构信息,比如字段数、字段名等。
2、得到结果集(rs)的结构信息,比如字段数、字段名等。
ResultSetMetaData rsmt=rs.getMetaData();
3、使用rs.getMetaData().getTableName(1))就可以返回表名
4、rs.getMetaData().getColumnCount()字段数
5、rs.getMetaData().getColumnName(i));字段名
代码查看
public void addCar() {BuyAction buyAction = new BuyAction();BuyTable b = new BuyTable();MiddleAction middleAction = new MiddleAction();//创建集合,放入选中的行List<List<Object>> result = SelectRowsUttil.selectRows(productsViewTable);for (List<Object> a : result) {try {//创建集合,查询buy表中客户已经购买的商品名称和数量放入集合中List<BuyTable> bResult = buyAction.query(User.userName, a.get(0).toString());System.out.println("第一层for循环");try {//创建一个集合,装从middle表查询到的数据//创建集合,查询middle表中商品的种类和价格List<MiddleTable> mResult = middleAction.query(a.get(0).toString());for (int i = 0; i < mResult.size(); i++) {System.out.println("第二层for循环");List<String> conBResult = new ArrayList<>();for (BuyTable c : bResult) {conBResult.add(c.getProduct_name());conBResult.add(c.getProduct_num().toString());}for (int j = 0; j < bResult.size(); j++) {System.out.println("第三层for循环");int newProductNum = bResult.get(j).getProduct_num();System.out.println(newProductNum);//如果商品存在,更新 buy表商品数量和商品总价if (conBResult.contains(a.get(0).toString())) {b.setProduct_num(newProductNum + 1);b.setProduct_name(a.get(0).toString());b.setPrice(mResult.get(i).getPrice());b.setPrice_sum(b.getPrice() * b.getProduct_num());b.setUser_name(User.userName);buyAction.updateNum(b);System.out.println("更新商品数量成功");}//如果商品存在,且is_delete=1 更新商品的数量 num==1System.out.println(bResult.get(j).getSales_date());if (conBResult.contains(a.get(0).toString()) && bResult.get(j).getIs_delete()==1) {b.setProduct_num(1);b.setProduct_name(a.get(0).toString());b.setPrice(mResult.get(i).getPrice());b.setPrice_sum(b.getPrice() * b.getProduct_num());b.setUser_name(User.userName);b.setIs_delete(0);buyAction.updateNum(b);System.out.println("更新商品数量成功");}}//如果商品不存在,增加buy表商品if (!conBResult.contains(a.get(0).toString())) {b.setUser_name(User.userName);b.setSort(mResult.get(0).getSort());b.setProduct_name(a.get(0).toString());b.setPrice(mResult.get(i).getPrice());b.setProduct_num(1);buyAction.add(b);System.out.println(User.userName + "\n" + mResult.get(0).getSort() + "\n" + a.get(0).toString() + "\n" + mResult.get(i).getPrice());System.out.println("新增商品成功");System.out.println("=================");}}} catch (SQLException e) {e.printStackTrace();}} catch (SQLException e) {e.printStackTrace();}}}//查询所有字段public List<BuyTable> query(List<Map<String,Object>> parms) throws SQLException {List<BuyTable> result = new ArrayList<BuyTable>();Connection conn = DBUtil.getconnection();StringBuilder sb = new StringBuilder();sb.append("select * from buy where 1=1 ");if (parms !=null && parms.size()>0) {for (int i=0;i<parms.size();i++) {Map<String,Object> map = parms.get(i);sb.append(" and "+map.get("name")+" "+map.get("rela")+" "+map.get("value")+" " +" or " + map.get("name1") + " " + map.get("rela1") + " " + map.get("value1") + " ");}}PreparedStatement prmt = conn.prepareStatement(sb.toString());System.out.println(sb.toString());ResultSet rs = prmt.executeQuery();BuyTable b=null;while (rs.next()) {b=new BuyTable();b.setId(rs.getInt("id"));b.setUser_name(rs.getString("user_name"));b.setSort(rs.getString("sort"));b.setProduct_name(rs.getString("product_num"));b.setPrice(rs.getInt("price"));b.setProduct_num(rs.getInt("product_num"));b.setPrice_sum(rs.getInt("price_sum"));b.setSales_date(rs.getDate("sales_date"));b.setIs_delete(rs.getInt("is_delete"));result.add(b);}return result;}
作品逻辑
middle 和 product
m.product_name=product.product_name
m增加商品 ,p表对应的也增加=====>从管理员界面汇总页操作
middle和buy
buy表增加,m表一些数量更新
String sql =" select " +" m.sort,m.product_name,m.price,m.popular_level,m.product_sum,m.sales_num,m.product_surplus,m.price_sum,p.product_date,p.`save_date`,m.is_delete" +" from" +" middle m" +" join" +" product p" +" on" +" m.`product_name` = p.`product_name";
// SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
// String textSaveDate = a.get(9).toString();
// String textProductDate = a.get(10).toString();
// Date productDate = sf.parse(textSaveDate);
// Date saveDate = sf.parse(textProductDate);
//
// p.setProduct_date(productDate);
// p.setSave_date(saveDate);
// System.out.println(a.get(2).toString());
// p.setProduct_name(a.get(2).toString());
// p.setBrand(a.get(1).toString());
//
//
// productAction.edit(p);
//
// //更新middle表
// m.setSort(a.get(0).toString());
// m.setProduct_name(a.get(2).toString());
// m.setPrice(Integer.parseInt(a.get(3).toString()));
// m.setPopular_level(Integer.parseInt(a.get(4).toString()));
// m.setPrice_sum(Integer.parseInt(a.get(5).toString()));
// m.setSales_num(0);
// m.setProduct_surplus(Integer.parseInt(a.get(7).toString()));
// m.setProduct_sum(Integer.parseInt(a.get(8).toString()));
// m.setIs_delete(0);
//
// middleAction.edit(m);
// System.out.println("商品更新成功");
// JOptionPane.showMessageDialog(null, "商品:“" + a.get(2).toString() + "”添加成功");
// }// SimpleDateFormat sf1 = new SimpleDateFormat("yyyy-MM-dd");
// try {
//
// System.out.println(value);
// valueDate = sf1.parse(value);
// System.out.println("value已转化为日期格式"+valueDate);
// } catch (ParseException e) {
// e.printStackTrace();
// }//巧妙,不用从新写sql 动态改变
// map.put("rela", "=");
// if (name.equals("product_date" )|| name.equals("save_date")) {
// map.put("name", "p." + name);
// map.put("rela", "=");
// map.put("value", "'" + valueDate + "'");
// params.add(map);
// System.out.println("valueDate");
// }else if (name.equals("brand")){
// map.put("name", "p." + name);
// map.put("value", "'" + value + "'");
// params.add(map);
// System.out.println("brand");
// } else{
// map.put("name", "m." + name);
// map.put("value", "'" + value + "'");
// params.add(map);
// System.out.println("value");
// }
考核问题总结
er图
提示
索引
时间戳
mvcc
list 实现类
java后端系统学习总结 02_数据库基础学习、jdbc基础学习、er图基础学习、数据库——(完结)相关推荐
- 什么是ER图?数据库ER图基础概念整理
前置知识 概述:数据模型的基本概念 模型就是对现实世界特征的模拟和抽象,数据模型是对现实世界数据特征的抽象.对于具体的模型人们并不陌生,如航模飞机.地图和建筑设计沙盘等都是具体的模型.最常用的数据模型 ...
- mysql er概念_数据库ER图基础概念
ER图分为实体.属性.关系三个核心部分.实体是长方形体现,而属性则是椭圆形,关系为菱形. ER图的实体(entity)即数据模型中的数据对象,例如人.学生.音乐都可以作为一个数据对象,用长方体来表示, ...
- mysql er 图_数据库ER图基础概念整理
ER图分为实体.属性.关系三个核心部分 图形表示分别是 长方形,椭圆形,菱形 一,组成部分介绍 1,实体(entity):数据模型中的数据对像,每个实体都有自己的实体成员或者说实体对象,例如学生实体包 ...
- 数据库ER图基础概念
ER图分为实体.属性.关系三个核心部分.实体是长方形体现,而属性则是椭圆形,关系为菱形. ER图的实体(entity)即数据模型中的数据对象,例如人.学生.音乐都可以作为一个数据对象,用长方体来表示, ...
- 数据库ER图基础概念整理
ER图分为实体.属性.关系三个核心部分.实体是长方形体现,而属性则是椭圆形,关系为菱形. ER图的实体(entity)即数据模型中的数据对象,例如人.学生.音乐都可以作为一个数据对象,用长方体来表示, ...
- 【数据库设计】概念设计-数据库ER图基础概念
原文链接 : http://blog.csdn.net/belen_xue/article/details/52763629 ER图分为实体.属性.关系三个核心部分.实体是长方形体现,而属性则是椭圆形 ...
- 学校计算机学院教学管理ER图,教学管理系统数据库ER图及SQL语句.doc
文档介绍: 教学管理系统 一.系统功能需求 学校教务管理系统是针对学校的大量信息处理工作而开发的管理软件,完成的主要功能如下: (1) 学生基本信息管理:能够对学生基本信息进行输入.删除.修改.学生基 ...
- 计算机学院教学管理ER图,教学管理系统数据库ER图和SQL语句.doc
.. .. 教学管理系统 一.系统功能需求 学校教务管理系统是针对学校的大量信息处理工作而开发的管理软件,完成的主要功能如下: (1) 学生基本信息管理:能够对学生基本信息进行输入.删除.修改.学生基 ...
- 实训13 使用SQLyog创建数据库和数据表,生成E-R图——MySQL数据库
EX13.1 新建一个数据库erp,并使用SQL代码创建两个表,一个商品类别表TYPE_T和一个商品表GOODS_T,表结构如下所示.生成对应的E-R图. 商品类别TYPE_T 字段名 类型 约束 说 ...
最新文章
- mac os mysql 命令_如何在Mac OS上安装“mysql”命令?
- linux命令学习之 cp(命令学习之四)
- java执行cmd命令,返回结果中文乱码问题解决
- @RequestParam和@RequestBody
- VTK:Utilities之FunctionParser
- 增量式pid调节方式有何优点_增量式pid和位置式pid相比各有什么优缺点
- java线程读取流的时候卡死,java – 线程中断没有结束阻塞调用输入流读取
- 购物商城Web开发第十天
- [WTL] 改变右击SysMenu后弹出的菜单
- IM即时通讯源码系统安卓苹果IOS双端源码介绍
- web大作业:简单的学生网页作业源码 基于html css javascript jquery实现智能分控网站
- MFC ScreenToClient坐标转换错误
- cmd: cd /D %~dp0 的含义
- 用python计算个人所得税计算器_教你使用Python实现新个税计算器
- vue 页面刷新404
- 数据库管理系统、数据库和表的关系
- 利用Python提取函数图像数据并拟合曲线
- 分享一个简易的AT变速箱(TCU)换挡逻辑控制模型
- 花了一些力气研究aircv,搞一个后台找图识图的DEMO
- 埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 L-K序列
热门文章
- Python在抖音上也火?
- 鸿蒙系统隐私空间有提示吗,如何评价有人把华为手机的隐私空间功能,被冠上渣男救星手机...
- 14.sql server数据库设计的重要性(by-朝夕)
- Win32 API - Windows 消息
- JavaScript计算文件Hash值(sha1 sha 256 md5)
- IDC知识第二弹:托管/租用物理服务器
- pushd 命令,了解一下! 一个比 cd 更高效的目录切换命令
- java上传超大文件解决方案
- 5 . 1 . 1 创建独一无二的包名
- Delivery item category determination