200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > 【数据库1】mysql安装 DDL/DML DQL 外键约束 多表/子查询 事务 登陆案例 预编

【数据库1】mysql安装 DDL/DML DQL 外键约束 多表/子查询 事务 登陆案例 预编

时间:2021-05-07 17:54:14

相关推荐

【数据库1】mysql安装 DDL/DML DQL 外键约束 多表/子查询 事务 登陆案例 预编

文章目录

1.mysql安装:存储:集合(内存:临时),IO流(硬盘:持久化)1.1 服务端:双击mysql-installer-community-5.6.22.0.msi1.2 客户端:命令行输入mysql -u...实际是如下安装路径的bin文件夹的mysql.exe2.DDL/DML:char不用动态变化,效率高3.DQL:select(相当于System.out)第一个但在倒数第二执行4.约束和自增长:字段约束(字段的赋值规范)/主键约束(唯一非空且一张表只有一个主键)5.单表缺点和外键约束:多从外 引出6.三种多表关系:中间表两外键:一对一(简历),一对多(员工,部门),多对多(学生,课表)7.多表查询:表..join表on7.1 外连接:左外=左表+内连接8.子查询:优先于主查询产生结果9.事务:一组操作,要么同时成功,要么同时失败10.四个接口:左java.sql包下的DCSR,右com.mysql.jdbc.Driver11.释放资源:finally,工具类封装12.JDBC事务操作:conn.setAutoCommit(false)13.登陆案例: ' " +name+ " '14.登陆案例的预编译改造:PreparedStatement,setString,executeQuery15.c3p0连接池:jdbc2.0才引进连接池,不是线程池(连接池的技术标准就是DataSource替代DriverManager)16.类加载器路径:is = classLoader.getResourceAsStream()17.druid连接池:自动ds.set18.execute/update方法:template =19.queryForXX方法:Map.Entry < String, Object > ,Map < String, Object > 两个数据类型20.query方法:获取类并反射得到方法,rowMapper作为参数传入query方法21.redis安装:加载.conf22.操作:set/get,push/pop,add/rem23.持久化策略:存文件,.aof和.rdb文件删了,数据库里数据全没了24.Jedis:java程序连接redis,拿到jedis25.案例_好友列表:json = om.25.1 前端:index.html25.2 web:FriendServlet .java25.3 service:FriendService.java25.4 dao:FriendDao.java25.5 bean:Friend.java26.总结:存储过程(PL/SQL代码集,像没有返回值的自定义函数)和函数需要用户显示调用才执行,而触发器是由一个事件来触发运行,当某个事件发生时会自动地隐式运行,不能被显示的调用。冒泡,二分查找,sql多用group by26.1 数据库优化:项目管理PMP证书,数据库DBA/OCM(Oracle Certified Master)证书26.2 数据库备份和恢复:冷热备份26.3 数据库精度:高精度数据用SQL Server数据库

1.mysql安装:存储:集合(内存:临时),IO流(硬盘:持久化)

1.1 服务端:双击mysql-installer-community-5.6.22.0.msi

mysql安装包:链接:/s/18Ctus6BLVrECZP0W-QKtfw 提取码:94s9。

上面next,execute安装后,下面开始配置。

1.2 客户端:命令行输入mysql -u…实际是如下安装路径的bin文件夹的mysql.exe

命令行java -version要配环境变量,看mysql有没有运行,只能从任务管理器看有没有mysql的进程。

win下cmd输入:完整版没有括号:mysql-h(host)127.0.0.1-P(port)3306-u(username)root-p(password)。简略版:mysql -u root -p。

可视化工具navicat链接:/s/11qAEA7yEGSIz6J9GIC_S6A 提取码:1w9n。navicat免安装链接:/s/1zanhYyyNsUXajI-czfW7KA 提取码:om5g。

2.DDL/DML:char不用动态变化,效率高

如下中间蓝框里一个数据库相当于一个excel表,紫色框里一个table相当于excel表里的一个sheet。use 数据库相当于双击打开excel表格,select查看函数返回值,desc全称description,like复制表结构,change 旧字段新字段 新类型

数据库名字不建议修改,用数据库备份改名(新建一个数据库,把原数据库数据复制过来)。mysql中utf-8中-无法识别,用utf8。ISO-8859-1用latin1。

注意(),逗号,分号。

如下数(整小)日字,oracle两个不同:number包含整小,varchar2。

选用timestamp而不用datetime,因为datetime不会自动设置时间。

int(11)默认11位不用写出来,2147483647即21亿10位,如果有负数还有最前面一位是符号位,所以一共11位

如下是表记录,select非常多,删除只是记录,表结构还在。

DDL后面不需要加from等词,D【cdat】CM【idu】Q。

如下单引号可加可不加。

如下要写两个add。

3.DQL:select(相当于System.out)第一个但在倒数第二执行

如下3中第一排序字段相同的里面再进行第二排序。

如下查询id是1或3或5的学生。

d低下降,只要有数字都比null大。

如下有英语成绩有6个,不能代表总人数,缺考没算入。

select后的第一个字段要和group by后同。

如下是select语句执行顺序,红字书写顺序必须这样。

sql只有一种情况报错:语法写错。如下索引越界不会报错。

page和count是前端传来的两个参数,count不用变。

数量(count(*))降序只要一个(limit 1)。

如下将db3数据库整个连数据备份,本质create,insert。

记住mysqldump和source。

4.约束和自增长:字段约束(字段的赋值规范)/主键约束(唯一非空且一张表只有一个主键)

如下验证主键唯一和非空,如下两个框都报错。

如下的Null列表示是否允许为空。

5.单表缺点和外键约束:多从外 引出

多表是外键约束的前提,外键约束解决下面多表的2个问题,add…多了一条线。alter table emploee dropforeign keyfk_001。

如上是在已有表添加外键,如下建表就添加(开发中常用)。

如果要删除department表的id为001即整个研发部门,需要先在employee表中删除id=001的很多记录,很麻烦。现在想要删除department的001部门时employee为001的行也一起删了,所以用外键级联操作,如下create table …中省略同上。

6.三种多表关系:中间表两外键:一对一(简历),一对多(员工,部门),多对多(学生,课表)

7.多表查询:表…join表on

CREATE DATABASE day03;USE day03;-- 创建部门表CREATE TABLE dept (id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(20));INSERT INTO dept (NAME) VALUES ('开发部'),('市场部'),('财务部');-- 创建员工表CREATE TABLE emp ( id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(10),gender CHAR(1), -- 性别salary DOUBLE, -- 工资join_date DATE, -- 入职日期dept_id INT);INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('孙悟空','男',7200,'-02-24',1);INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('猪八戒','男',3600,'-12-02',2);INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('唐僧','男',9000,'-08-08',2);INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('白骨精','女',5000,'-10-07',3);INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('蜘蛛精','女',4500,'-03-14',1);

如下要查出有用的记录需要emp.dept_id(emp外键)=dept.id(dept主键)。

因为select * ,所以将两个橙色横框拼接起来,棕色框。

7.1 外连接:左外=左表+内连接

如下注意记住左表不动。

如下第一个内连接没有销售部(销售部没有和员工表任何数据相交),第二个有销售部。

union all不去重,左外连接+右外连接。

8.子查询:优先于主查询产生结果

如下执行两句sql,要连接两次数据库,子查询一般要写在()里。

如下1,2是dept_id,可以把in换成= any

如下第一行和第二行效果相同。

如下两个select等价。

如下还是写上面的题目,如果用内连接,沙僧会没有,左外或右外连接都可以。

如下将上面的id1列去除(即将dept表的id列去除不显示)。

on比where先执行。

-- 11111111111111111111111111111111111111111111111111111111111111111部门表CREATE TABLE dept (id INT PRIMARY KEY PRIMARY KEY, -- 部门iddname VARCHAR(50), -- 部门名称loc VARCHAR(50) -- 部门位置);-- 添加4个部门INSERT INTO dept(id,dname,loc) VALUES (10,'教研部','北京'),(20,'学工部','上海'),(30,'销售部','广州'),(40,'财务部','深圳');-- 1111111111111111111111111111111111111111111111111111111职务表,职务名称,职务描述CREATE TABLE job (id INT PRIMARY KEY,jname VARCHAR(20),description VARCHAR(50));-- 添加4个职务INSERT INTO job (id, jname, description) VALUES(1, '董事长', '管理整个公司,接单'),(2, '经理', '管理部门员工'),(3, '销售员', '向客人推销产品'),(4, '文员', '使用办公软件');-- 11111111111111111111111111111111111111111111111111111111111111111111员工表CREATE TABLE emp (id INT PRIMARY KEY, -- 员工idename VARCHAR(50), -- 员工姓名job_id INT, -- 职务idmgr INT , -- 上级领导joindate DATE, -- 入职日期salary DECIMAL(7,2), -- 工资bonus DECIMAL(7,2), -- 奖金dept_id INT, -- 所在部门编号CONSTRAINT emp_jobid_ref_job_id_fk FOREIGN KEY (job_id) REFERENCES job (id),CONSTRAINT emp_deptid_ref_dept_id_fk FOREIGN KEY (dept_id) REFERENCES dept (id));-- 添加员工INSERT INTO emp(id,ename,job_id,mgr,joindate,salary,bonus,dept_id) VALUES (1001,'孙悟空',4,1004,'2000-12-17','8000.00',NULL,20),(1002,'卢俊义',3,1006,'2001-02-20','16000.00','3000.00',30),(1003,'林冲',3,1006,'2001-02-22','12500.00','5000.00',30),(1004,'唐僧',2,1009,'2001-04-02','29750.00',NULL,20),(1005,'李逵',4,1006,'2001-09-28','12500.00','14000.00',30),(1006,'宋江',2,1009,'2001-05-01','28500.00',NULL,30),(1007,'刘备',2,1009,'2001-09-01','24500.00',NULL,10),(1008,'猪八戒',4,1004,'-04-19','30000.00',NULL,20),(1009,'罗贯中',1,NULL,'2001-11-17','50000.00',NULL,10),(1010,'吴用',3,1006,'2001-09-08','15000.00','0.00',30),(1011,'沙僧',4,1004,'-05-23','11000.00',NULL,20),(1012,'李逵',4,1006,'2001-12-03','9500.00',NULL,30),(1013,'小白龙',4,1004,'2001-12-03','30000.00',NULL,20),(1014,'关羽',4,1007,'2002-01-23','13000.00',NULL,10);-- 1111111111111111111111111111111111111111111111111111111111111111工资等级表CREATE TABLE salarygrade (grade INT PRIMARY KEY,losalary INT,hisalary INT);-- 添加5个工资等级INSERT INTO salarygrade(grade,losalary,hisalary) VALUES (1,7000,12000),(2,1,14000),(3,14010,20000),(4,20010,30000),(5,30010,99990);

如下以dept为主体,分组后再进行count聚合。

因为d.id是主键唯一,所以用group by d.id,效果如下。

坑1:如上财务部没人也需要写0,所以如下用外连,如下第一个sql产生效果同上面第一个,就多了财务部一行。

count(*)是整行记录。

9.事务:一组操作,要么同时成功,要么同时失败

如下若在执行一次sql前执行一次start transaction,若不commit,刷新数据库不显示。

10.四个接口:左java.sql包下的DCSR,右com.mysql.jdbc.Driver

如下jdbc是父类引用。

如下mchange. .和c3p0. .一起。第一个导入的是mysql-connector…。

如下代码第一行new Driver()是导入com.mysql.jdbc(用mysql实现好的,就是上面导入的mysql-connector..jar包)而不是java.sql(自己不会重写抽象方法)下,参数是接口类型需要传入接口的实现类对象即new Driver()。

registerDriver相当于set方法,get获取的是mysql.Driver.connect方法返回的Connection类即com.mysql.jdbc.JDBC4Connection(有mysql.的都是导入的jar包)。

加载DriverManager这个类用到打破双亲类加载:DriverManager是jdk自带的类,DriverManager类使用的是bootstrap引用类加载器。数据库是用户类用bootstrap加载不合适,所以DriverManager去加载h2的Driver需要把当前引用类加载器替换为当前系统或当前线程的应用app类加载器。

package com.itheima01.jdbc;import com.mysql.jdbc.Driver;import java.sql.*;public class JdbcDemo {public static void main(String[] args) throws SQLException, ClassNotFoundException, IllegalAccessException, InstantiationException {//1. 注册驱动 (注意: 导入的mysql的驱动)/** A. 查看mysql.Driver源码: 点new Driver()中Driver看源码* 发现static 代码块里 已经注册了驱动 -> 驱动自注册 相当于set一次就行* 带来问题: 外部的注册没有意义(重复注册)* * 解决: 保证mysql.Driver类被加载(静态代码块就会执行),如下两种方案:*1. 创建对象*2. 反射:a. 节省内存* b. 跟驱动包的关联只剩一个字符串:"com.mysql.jdbc.Driver"*待会将字符串写入配置文件,只要改配置文件就行 就会跟 mysql驱动包的彻底解耦 *///111111111111111111111111111111111111111111111111111111111111111111111111111111111111// DriverManager.registerDriver(new Driver()); //这行重复注册,下行new了就会加载 源码里的静态代码块,所以这行=下行//new Driver(); // Class对象 + 普通实例 //只要用了这个类,这个类就会被加载内存中方法区 //自动导包// new Driver()的内存消耗等价于下面两行: 其实只需要calss对象,不需要实例 // Class<?> clazz = Class.forName("com.mysql.jdbc.Driver"); //获取这个类的class对象// Object obj = clazz.newInstance(); //利用class对象调用其空参构造来创建一个实例Class.forName("com.mysql.jdbc.Driver"); //获取Class对象,没有普通实例,因为普通实例没有意义 //用反射,com.mysql.jdbc.Driver这个类也会被加载//111111111111111111111111111111111111111111111111111111111111111111111111111111111111//2. 获取连接/** 只要涉及两个软件通信 : 网络三要素(必要非充分:一定要,但是有它们三不一定够如多了资源位置)* 1. 协议 : jdbc:mysql (主协议:子协议)* 2. ip : 数据库所在的计算机(自己:localhost或127.0.0.1)* 3. port : mysql数据库3306* 资源位置: 数据仓库的名称* * 协议://ip:port/资源位置* :443*/// String url = "jdbc:mysql://localhost:3306/day03"; //day03是数据库String url = "jdbc:mysql:///day03"; //ip:localhost port:3306 可以省略String user = "root";String pwd = "1234";Connection conn = DriverManager.getConnection(url, user, pwd);System.out.println("conn:" + conn); //引用类型打印地址//1111111111111111111111111111111111111111111111111111111111111111111111111111111111//3. 创建执行sql的语句对象/** Connection 接口的一些方法* <1>. Statement createStatement(); 创建执行sql的语句对象,相当于创建一个流* <2>. PreparedStatement prepareStatement(sql); 创建一个预编译sql的语句对象* <3>. 事务操作相关*/Statement statement = conn.createStatement();System.out.println("statement:" + statement);//11111111111111111111111111111111111111111111111111111111111111111111111111111111111//4. 执行sql,返回结果/** Statetment 接口的api* 1. ResultSet statement.executeQuery(sql);* 执行的查询语句 : DQL* 返回的查询结果: 结果集* * 2. int executeUpdate(sql) :* 执行的增删改语句: DML* 返回的结果: 被影响的行数* * 3. boolean execute(sql); -> 不需要掌握,知道即可*万能 : DDL等 如create成功或失败是和异常相关,和返回值无关*返回值: 非查询语句返回false,查询语句返回true*/String sql = "select * from emp";ResultSet resultSet = statement.executeQuery(sql);//11111111111111111111111111111111111111111111111111111111111111111111111111111111111 //5. 处理结果while(resultSet.next()){String name = resultSet.getString("name"); // String id = resultSet.getString("id"); //也可以,java程序以外的所有数据对java来说都是字符串int id = resultSet.getInt("id"); //底层先调用getString再parse intSystem.out.println(id+ ":" + name);}//11111111111111111111111111111111111111111111111111111111111111111111111111111111111//6. 释放资源resultSet.close();statement.close();conn.close();}}

resultset不是返回一行数据,而是带有id=…。因为返回一行数据如 11孙悟空男,不知道怎么解析。

如下hasNext和next区别。

11.释放资源:finally,工具类封装

package com.itheima04.release;import com.itheima05.utils.JdbcUtil;import java.io.Closeable;import java.io.IOException;import java.sql.*;public class ReleaseDemo {public static void main(String[] args) {ResultSet resultSet = null;Statement statement = null;Connection conn = null;try {/*Class.forName("com.mysql.jdbc.Driver");String url = "jdbc:mysql://localhost:3306/day03";String user = "root";String pwd = "1234";conn = DriverManager.getConnection(url, user, pwd);*/conn = JdbcUtil.getConnection(); //查询要获取连接,getConnection方法调用多遍,所以getConnection方法不写try catch,查询提示 查询失败,删除提示 删除失败,封装时不知道是查询还是删除,不好提示,所以往外抛。conn = JdbcUtil.getConnection(); //增删改也要获取连接//1111111111111111111111111111111111111111111111111111111111111111111111111 statement = conn.createStatement();String sql = "select * from emp"; resultSet = statement.executeQuery(sql); while(resultSet.next()){String name = resultSet.getString("name");System.out.println(name);}} catch (Exception e) {e.printStackTrace();} finally{/* if(resultSet != null){try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if(statement != null){try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if(conn != null){try {conn.close();} catch (SQLException e) {e.printStackTrace();}}*/// closeIo(resultSet,statement,conn);JdbcUtil.release(conn,statement,resultSet);}}//1111111111111111111111111111111111111111111111111111111111111111111111private static void closeIo(AutoCloseable... ios) {//AutoCloseable接口位于java.lang包下,不用导包for (AutoCloseable io : ios) {if(io != null){try {io.close();} catch (Exception e) {e.printStackTrace();}}}}}

package com.itheima05.utils;import java.sql.*;/*** 工具类: 0. 拥有很多 工具方法(重复的代码封装) 的类* 命名规范: utils 包 -> xxUtil 类 (xx : 某个模块的名称)*Objects,Arrays,Collections...(JDK提供的)* *1. 一般工具类中方法是静态的,不用实例化,节省内存* * 2. 封装方法的步骤* 1. 先把要把封装的代码写出来*2. 观察不断重复的部分* 3. 定义方法,然后直接复制过来* 4. 设置参数和返回值* * 注意点: 1. 扩展性 : 不要导入mysql包中的类, 要导入java包中的类(这样换成oracle也可用)*2. 工具类中的异常一般是往外抛 : 一般异常是要在业务中处理*/public class JdbcUtil {static{try {Class.forName("com.mysql.jdbc.Driver");} catch (ClassNotFoundException e) {e.printStackTrace();}}//1111111111111111111111111111111111111111111111111111111111111111111111111111111public static Connection getConnection() throws SQLException {//此方法会被多次调用,注册驱动只需要一次 -> 所以用静态代码块 如上// Class.forName("com.mysql.jdbc.Driver");String url = "jdbc:mysql://localhost:3306/day03";String user = "root";String pwd = "1234";Connection conn = DriverManager.getConnection(url, user, pwd);return conn;}//1111111111111111111111111111111111111111111111111111111111111111111111111111111/*** 文档注释: a. 写在类上面 : 描述类的用途* b. 写在方法上面 : 描述方法的用途 (返回值,参数)*/public static void release(Connection conn, Statement statement, ResultSet resultSet){//java.sql.Connectionif(resultSet != null){try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if(statement != null){try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if(conn != null){try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}}

如下改进上面工具类。

/** 问题: 驱动,url,用户名和密码等信息 是有可能会变的, 变动频率比较低* 1. 如果不变,直接写死在代码中* 2. 变,但是频率高 : 一般设置成参数* 3. 变,但是频率不高: 放在配置文件* 1. 解耦 : 信息要改变的话,只要改配置文件,代码不用改,程序不需要重新编译和部署* 2. 代码简化 : 无需调用的时候传参了*/

//jdbc.properties文件,每个月改一次 //文件里没有关键字,也没有双引号,本来就是字符串driverName = com.mysql.jdbc.Driverurl = jdbc:mysql://localhost:3306/day03user = rootpwd = 1234

package com.itheima05.utils;import java.io.FileInputStream;import java.sql.*;import java.util.Properties;public class JdbcUtil02 {static String driverName;static String url;static String user;static String pwd;static{try {Properties p = new Properties();p.load(new FileInputStream("src/jdbc.properties"));driverName = p.getProperty("driverName");url = p.getProperty("url");user = p.getProperty("user");pwd = p.getProperty("pwd");Class.forName(driverName);} catch (Exception e) {e.printStackTrace();}} //1111111111111111111111111111111111111111111111111111111111111111111111111111111111public static Connection getConnection() throws SQLException {Connection conn = DriverManager.getConnection(url, user, pwd);return conn;}//11111111111111111111111111111111111111111111111111111111111111111111111111111111111 public static void release(Connection conn, Statement statement, ResultSet resultSet){if(resultSet != null){try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if(statement != null){try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if(conn != null){try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}}

12.JDBC事务操作:conn.setAutoCommit(false)

package com.itheima01.transaction;import com.itheima.utils.JdbcUtil;import java.sql.Connection;import java.sql.SQLException;import java.sql.Statement;import java.util.Scanner;// JDBC : 写一个转账案例public class Demo {public static void main(String[] args) {System.out.println("请输入转出的账户:"); Scanner sc = new Scanner(System.in); // 控制台: 模拟页面String outUser = sc.nextLine();System.out.println("请输入转入的账户:");String inUser = sc.nextLine(); System.out.println("请输入转账的金额:");double money = sc.nextDouble();//sql里面最好写单引号 , 1000和jack改为 两个双引和两个+号//String sql1 = "update account set money = money-1000 where name = 'jack'";String sql1 = "update account set money = money-"+money+" where name = '"+outUser+"'";String sql2 = "update account set money = money+"+money+" where name = '"+inUser+"'";//11111111111111111111111111111111111111111111111111111111111111111111111111111111111111Connection conn = null;try {/** 事务操作: Connection* 1. setAutoCommit(false); 开启事务* 2. commit(); 提交事务* 3. rollback(); 事务回滚* 注意点: 在事务中, 开启事务的连接才具有手动提交事务的功能* 一组操作都必须要同一个 连接conn 要执行*/ conn = JdbcUtil.getConnection(); //访问数据库,try外面定义conn// Connection conn2 = JdbcUtil.getConnection(); conn.setAutoCommit(false); //开启事务,禁止自动提交 Statement statement = conn.createStatement(); statement.executeUpdate(sql1); //转出 // int i = 1/0; // ArithmeticException 算术异常 模拟银行爆炸Statement statement2 = conn.createStatement(); statement2.executeUpdate(sql2); //转入//1111111111111111111111111111111111111111111111111111111111111111111111111111111111111 mit(); //提交事务(和事务回滚只有其一执行) System.out.println("转账成功~~");} catch (Exception e) {// 注意: 提升异常级别(用于捕获算术异常)e.printStackTrace();if(conn != null){//Connection conn放外面,这边访问的到try {conn.rollback(); //事务回滚} catch (SQLException e1) {e1.printStackTrace();}}System.out.println("转账失败");}}}

13.登陆案例: ’ " +name+ " ’

package com.itheima02.login;import com.itheima.utils.JdbcUtil;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.Scanner;/*前提: 用户能够登录,说明已经注册过了注册成功的时候, 程序会把用户的信息保存到数据库* 登录案例: 逻辑: 请输入用户名和密码(用户)* 我们: 校验数据库* sql : select * from account where name = ? and pwd = ?; (name用户名唯一)* 预测结果: 1. 0条 : 用户名不存在或密码错误* 2. 1条 : 登录成功*/public class LoginDemo {public static void main(String[] args) throws SQLException {System.out.println("请输入用户名:");Scanner sc = new Scanner(System.in);String name = sc.nextLine(); System.out.println("请输入密码:");String pwd = sc.nextLine();String sql = "select * from account where name = '"+name+"' and pwd = '"+pwd+"'";System.out.println(sql); //将参数(上面键盘输入)直接拼接进sql//1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111Connection conn = JdbcUtil.getConnection();Statement statement = conn.createStatement(); ResultSet resultSet = statement.executeQuery(sql); //将sql发送给数据库去处理if(resultSet.next()){//有一条则为trueSystem.out.println("登录成功~~");}else{System.out.println("用户名不存在或密码错误");}}}

根据(用户名和密码)或(1=1永真)为条件查询数据库,what可以随便写。

14.登陆案例的预编译改造:PreparedStatement,setString,executeQuery

预编译知道了sql的语法结构了,已经把关键字认全了,后面再包含关键字or就不认了(当成字符串处理),可以防止sql注入

package com.itheima02.login;import com.itheima.utils.JdbcUtil;import java.sql.*;import java.util.Scanner;public class LoginDemo02 {public static void main(String[] args) throws SQLException {System.out.println("请输入用户名:");Scanner sc = new Scanner(System.in);String name = sc.nextLine(); System.out.println("请输入密码:");String pwd = sc.nextLine();// 1. 改造sql String sql = "select * from account where name = ? and pwd = ?";System.out.println(sql);Connection conn = JdbcUtil.getConnection();// 2. 预编译sql // PreparedStatement 是 Statement的子接口PreparedStatement statement = conn.prepareStatement(sql);// 3. 设置参数// setString(int parameterIndex, String x)// parameterIndex : sql中的?的索引(从1开始,从左开始) // String x: 参数statement.setString(1,name);statement.setString(2,pwd);// 4. 传参执行ResultSet resultSet = statement.executeQuery();if(resultSet.next()){System.out.println("登录成功~~");}else{System.out.println("用户名不存在或密码错误");}}}

如下手动在数据库中增加一行。

package com.itheima03.prepare;import com.itheima.utils.JdbcUtil;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.SQLException;import java.sql.Statement;/** 预编译的好处: 1. 防止sql注入* 2. 阅读性强(sql)* 3. 批量处理sql,效率高 (节省了sql重复编译过程)*/public class PrepareDemo {public static void main(String[] args) throws SQLException {// method01(); //用预编译,如下不用预编译String name = "ww";int money = 200;String sql1 = "insert into account values(null,'"+name+"',"+money+",null)";String name2 = "www";int money2 = 2002;String sql2 = "insert into account values(null,'"+name2+"',"+money2+",null)";Connection conn = JdbcUtil.getConnection();Statement statement = conn.createStatement(); //不用预编译statement.executeUpdate(sql1);// 编译+运行statement.executeUpdate(sql2);//编译+运行,和上行一共两次编译 statement.close();conn.close();}//1111111111111111111111111111111111111111111111111111111111111111111111111private static void method01() throws SQLException {String sql = "insert into account values(null,?,?,null)"; Connection conn = JdbcUtil.getConnection();PreparedStatement pstm = conn.prepareStatement(sql); pstm.setString(1,"zs");pstm.setDouble(2,1000);pstm.executeUpdate();//运行pstm.setString(1,"ls");pstm.setDouble(2,2000);pstm.executeUpdate();//运行 pstm.close();conn.close();}}

15.c3p0连接池:jdbc2.0才引进连接池,不是线程池(连接池的技术标准就是DataSource替代DriverManager)

package com.itheima04.c3p0;import com.mchange.boPooledDataSource;import java.beans.PropertyVetoException;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;public class C3p0Demo {public static void main(String[] args) throws PropertyVetoException, SQLException {// method01(); //这行方法和下面xml文件无关/** 配置文件方式 : 默认情况下, c3p0将会在 类加载器路径(在当前的工程下, src路径)下*寻找一个名为c3p0-config.xml 配置文件(xml文件是复杂的Properties文件,也是key-value)* * 套路: 1. 在src下创建名为c3p0-config.xml配置文件(内容直接复制)* 2. 创建ComboPooledDataSource核心类*/ComboPooledDataSource cpds = new ComboPooledDataSource(); //1. 底层自动会去类加载器路径(写代码:src下) 去寻找一个名为c3p0-config.xml 配置文件// 2. 自动解析: 读取xml中配置信息 , 设置给c3p0即cpds String sql = "select * from account"; // 同下面 Connection conn = cpds.getConnection(); PreparedStatement pstm = conn.prepareStatement(sql);ResultSet resultSet = pstm.executeQuery();while(resultSet.next()){String name = resultSet.getString("name");System.out.println(name + "--");}conn.close();// 将连接还给连接池cpds.close(); // 销毁}//111111111111111111111111111111111111111111111111111111111111111111111111111111111111111private static void method01() throws PropertyVetoException, SQLException {// 如下硬编码: 用代码来实现参数的设置。一般不用硬编码,用配置文件ComboPooledDataSource cpds = new ComboPooledDataSource();//ComboPooledDataSource是DataSource实现类cpds.setDriverClass( "com.mysql.jdbc.Driver"); //需要mysql-connector-java-x.x.x-bin.jarcpds.setJdbcUrl( "jdbc:mysql://localhost:3306/day05" );cpds.setUser("root");cpds.setPassword("1234");String sql = "select * from account"; Connection conn = cpds.getConnection(); PreparedStatement pstm = conn.prepareStatement(sql);ResultSet resultSet = pstm.executeQuery();while(resultSet.next()){String name = resultSet.getString("name");System.out.println(name); //System.err.println(name);//红色}conn.close();// 将连接还给连接池cpds.close(); // 销毁}}

//c3p0-config.xml<c3p0-config> <default-config> <!-- 使用默认的配置读取连接池对象 --><!-- 如下连接参数 --> <property name="driverClass">com.mysql.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql://localhost:3306/day05</property><property name="user">root</property><property name="password">1234</property><!-- 如下连接池参数 --><!--initialPoolSize : 初始化连接数 3maxPoolSize: 最大连接数 5checkoutTimeout : 连接超时时间 2000ms(默认10s,访问数超过最大连接数, 有人必须要等,2秒连不上给个提示或报错) maxIdleTime :最大的闲置时间,连接超过maxIdleTime没人使用闲置就销毁maxPoolSize中连接,留到minPoolSize中数量,因为费内存--><property name="initialPoolSize">3</property><property name="maxPoolSize">5</property><property name="minPoolSize">2</property><property name="checkoutTimeout">2000</property><property name="maxIdleTime">1000</property></default-config><!--111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111--><named-config name="xx"><!-- 连接参数 --><property name="driverClass">com.mysql.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql://localhost:3306/beitai</property><property name="user">root</property><property name="password">root</property><!-- 连接池参数 --><property name="initialPoolSize">5</property><property name="maxPoolSize">15</property><property name="checkoutTimeout">2000</property><property name="maxIdleTime">1000</property></named-config></c3p0-config>

16.类加载器路径:is = classLoader.getResourceAsStream()

package com.itheima04.c3p0;import org.junit.Test;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.util.Properties;public class ParseDemo {@Testpublic void method01() throws IOException {Properties p = new Properties(); //Properties就是一个map p.load(new FileInputStream("src/jdbc.properties")); //相对路径:当前工程src下String url = p.getProperty("url"); //.properties文件中有url=...System.out.println(url);} @Testpublic void method02() throws IOException {/**1. 类加载器 classloader 【底层: 输入流】* 作用: 将 .class文件(硬盘) 加载进内存(兼职把jdbc.properties加载进来)。* *2. classloader怎么知道.class文件在哪里?* classloader有个默认加载路径:out路径下项目名路径(src和out/production/项目名路径里文件全一样)。* * 相比method01,一般用method02更通用,因为每个工程都会有类加载器路径,但是每个工程的相对路径不一定是当前工程src下。* 如web阶段main方法不在项目里,每个项目的入口是main方法,main方法在tomcat里,* 所以工程的相对路径会变,但是类加载器的路径不变,一直指向.class文件路径。*/ClassLoader classLoader = ParseDemo.class.getClassLoader(); //利用当前类获取类加载器路径InputStream is = classLoader.getResourceAsStream("jdbc.properties"); //获取资源转成流 //此时类加载器工作的路径: out/production/jdbc-day05【即类加载器路径】,所以不用写src/jdbc.propertiesProperties p = new Properties();p.load(is);String url = p.getProperty("url");System.out.println(url + "-2");}}

如下是url + “-2”。

package com.itheima04.c3p0;import com.mchange.boPooledDataSource;import java.sql.Connection;import java.sql.SQLException;//c3p0-config.xml验证public class C3p0Demo02 {public static void main(String[] args) throws SQLException {ComboPooledDataSource ds = new ComboPooledDataSource(); //使用默认配置即c3p0-config.xml中<default-config> // ComboPooledDataSource ds = new ComboPooledDataSource("xx"); //使用命名配置即c3p0-config.xml中<named-config name="xx"> //备胎项目用。for (int i = 0; i < 6; i++) {//循环模拟: 有几多个用户Connection conn = ds.getConnection();System.out.println(conn); //没有下面close的话,5个连接6个人拿超过2s,会发生timed out报错if(i == 3){//i=3打印了下又还给连接池,所以i=3打印了两次。 conn.close(); //验证了确实连接还给连接池}}}}

5个连接6个人拿是不够的。如下最后@2d…打印了2次并且没有发生timed out连接超时错误。

17.druid连接池:自动ds.set

package com.itheima05.druid;import com.alibaba.druid.pool.DruidDataSource;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;import java.io.IOException;import java.io.InputStream;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.Properties;public class DruidDemo {public static void main(String[] args) throws Exception {// method01(); //如下配置文件的方式InputStream is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");Properties p = new Properties();p.load(is); DataSource ds = DruidDataSourceFactory.createDataSource(p); //自动解析.properties文件String sql = "select * from account"; Connection conn = ds.getConnection(); //获取连接PreparedStatement pstm = conn.prepareStatement(sql);ResultSet resultSet = pstm.executeQuery();while(resultSet.next()){String name = resultSet.getString("name");System.out.println(name + "-++");}conn.close(); //将连接还给连接池}//111111111111111111111111111111111111111111111111111111111111111111111111private static void method01() throws SQLException {DruidDataSource ds = new DruidDataSource();ds.setDriverClassName("com.mysql.jdbc.Driver");ds.setUrl("jdbc:mysql:///day05");ds.setUsername("root");ds.setPassword("1234");String sql = "select * from account";Connection conn = ds.getConnection(); PreparedStatement pstm = conn.prepareStatement(sql);ResultSet resultSet = pstm.executeQuery();while(resultSet.next()){String name = resultSet.getString("name");System.out.println(name + "--");}conn.close();// 将连接还给连接池// ds.close(); // 销毁 //实际开发服务器不关,连接池不会销毁}}

//druid.properties文件,如下key固定写法driverClassName=com.mysql.jdbc.Driverurl=jdbc:mysql:///day05username=rootpassword=1234

封装druid连接池工具类:ds = DruidDataSourceFactory。File-New-Project-Java。

package com.itheima.utils;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;import java.io.InputStream;import java.sql.Connection;import java.sql.SQLException;import java.util.Properties;public class JdbcUtil {private static DataSource ds; //下面getConn()也能访问到static{//静态代码块只运行一次try {Properties p = new Properties();InputStream is = JdbcUtil.class.getClassLoader().getResourceAsStream("druid.properties"); p.load(is); ds = DruidDataSourceFactory.createDataSource(p); //DataSource ds = 移到最上面了} catch (Exception e) {e.printStackTrace();}}public static DataSource getDs() {//属性私有化后提供对外公开的方法return ds;}public static Connection getConn() throws SQLException {// Connection connection = ds.getConnection();// return connection;return ds.getConnection(); //等同上面两行}public static void release(AutoCloseable... ios){for (AutoCloseable io : ios) {if(io != null){try {io.close();} catch (Exception e) {e.printStackTrace();}}}}}

package com.itheima.utils;import org.junit.Test;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;//测试上面JdbcUtil类public class TestDemo {@Testpublic void method01() throws SQLException {String sql = "select * from account"; Connection conn = JdbcUtil.getConn();PreparedStatement pstm = conn.prepareStatement(sql);ResultSet resultSet = pstm.executeQuery();while(resultSet.next()){String name = resultSet.getString("name");System.out.println(name);}JdbcUtil.release(resultSet,pstm,conn); //注意: conn的close是将连接还给连接池}}

如下是数据库中name这一列,不是.properties文件的key。

18.execute/update方法:template =

package com.itheima01.template;import com.itheima.utils.JdbcUtil;import org.junit.Test;import org.springframework.jdbc.core.JdbcTemplate;import javax.sql.DataSource;/** JdbcTemplate:是spring的框架的一部分,spring框架是工具箱。作用: 简化jdbc代码编写* 使用:1. 数据库的操作:DCMQ* 2. 核心类: JdbcTemplate。构造方法:JdbcTemplate(DataSource ds)*核心方法: A. void execute : 理论上可以执行任意sql,适合执行DDL,因为void无返回值* B. int update : 适合执行DML* C. 多种多样 query : 适合执行DQL,返回多种多样*/public class TemplateDemo01 {@Testpublic void execute(){String sql = "create table student(id int primary key auto_increment,name varchar(20),age int)";DataSource ds = JdbcUtil.getDs(); //拿到连接池JdbcTemplate template = new JdbcTemplate(ds); template.execute(sql); //无返回值System.out.println("执行结束");}@Testpublic void update01(){String sql = "insert into student values(null,?,?),(null,?,?)";JdbcTemplate template = new JdbcTemplate(JdbcUtil.getDs());/** int update(String sql, Object... args)* Object... args:* 1. Object原因是参数类型是不确定的 -> Object* 2. ... 原因是参数个数不确定* 返回值: 被影响的行数*/int count = template.update(sql, "zs", 18, "ls", 19);System.out.println(count); //2}@Testpublic void update02(){String sql = "update student set age = ? where id = ?";JdbcTemplate template = new JdbcTemplate(JdbcUtil.getDs()); Object[] args = {99,1}; //可变参数本质是数组int update = template.update(sql, args); System.out.println(update);}}

19.queryForXX方法:Map.Entry < String, Object > ,Map < String, Object > 两个数据类型

一行map是一个对象,query方法用的是多个对象这个。

package com.itheima01.template;import com.itheima.utils.JdbcUtil;import org.junit.Test;import org.springframework.dao.DataAccessException;import org.springframework.jdbc.core.JdbcTemplate;import java.util.List;import java.util.Map;import java.util.Set;/** C. 多种多样 query : 适合执行DQL* 1. queryForXX : XX表示返回值类型* a. queryForObject* b. queryForMap* c. queryForList* 2. query(RowMapper 行映射器)*/public class TemplateDemo02 {JdbcTemplate template = new JdbcTemplate(JdbcUtil.getDs());@Testpublic void queryForObject01(){String sql = "select count(*) from student";/** <T> T queryForObject(String sql, Class<T> requiredType)*requiredType : 返回值类型 -> Class对象**EmptyResultDataAccessException : 空结果异常* 查询不到任何数据,会报这个错*/Integer count = template.queryForObject(sql, Integer.class);System.out.println(count);}@Testpublic void queryForObject02(){String sql = "select name from student where id = ?";String s = null;try {s = template.queryForObject(sql, String.class,3); //3传入上面?} catch (DataAccessException e) {e.printStackTrace();System.out.println("查询不到任何结果");}System.out.println(s);}@Testpublic void queryForMap(){String sql = "select * from student where id = ?";Map<String, Object> map = template.queryForMap(sql, 1);// System.out.println(map); //{id=1,name=zs,age=99}Set<Map.Entry<String, Object>> entrySet = map.entrySet();for (Map.Entry<String, Object> entry : entrySet) {//一条String key = entry.getKey();Object value = entry.getValue();System.out.println(key + "=" + value); //竖着打印id=1 name=zs age=99}}@Testpublic void queryForList(){String sql = "select * from student";List<Map<String, Object>> list = template.queryForList(sql); for (Map<String, Object> map : list) {System.out.println(map); //{id=1,name=zs,age=99} 换行 {id=2,name=ls,age=19}}}}

20.query方法:获取类并反射得到方法,rowMapper作为参数传入query方法

package com.itheima01.template;/** JavaBean三要素(必须要有):*1. private属性,属性名和表中字段名是一致的!!! 都是引用类型(因为数据库中空为null,不是0)* 2. public get set方法* 3. public 空参构造*/public class Student {private Integer id;private String name;private Integer age;@Overridepublic String toString() {return "Student{" +"id=" + id +", name='" + name + '\'' +", age=" + age +'}';}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}}

package com.itheima01.template;import com.itheima.utils.JdbcUtil;import org.junit.Test;import org.springframework.jdbc.core.BeanPropertyRowMapper;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.jdbc.core.RowMapper;import java.sql.ResultSet;import java.sql.SQLException;import java.util.List;public class TemplateDemo03 {JdbcTemplate template = new JdbcTemplate(JdbcUtil.getDs());@Testpublic void query01(){String sql = "select * from student"; /** List<T> query(String sql, RowMapper<T> rm)* RowMapper : 行映射器 (接口)。方法参数中有接口类型, 那么调用的时候必须传入接口的实现类对象*/RowMapper<Student> rowMapper = new RowMapper<Student>() {/** 如下Student mapRow(ResultSet resultSet, int i) 映射行: resultSet转换为Student * 1. resultSet: 结果集(每行)* 2. i: 当前的行索引(没什么用)*/@Overridepublic Student mapRow(ResultSet resultSet, int i) throws SQLException {String name = resultSet.getString("name");int id = resultSet.getInt("id");int age = resultSet.getInt("age");Student s = new Student();s.setId(id);s.setName(name);s.setAge(age);System.out.println(i);return s;}}; //RowMapper行映射器 像 动态代理中 InvocationHandler,mapRow方法像invoke方法List<Student> list = template.query(sql, rowMapper);System.out.println(list); //打印出,list里是student类//[Student{id=1,name='zs',age=99},Student{id=2,name='ls',age=19}]}@Testpublic void query02(){String sql = "select * from student";/*BeanPropertyRowMapper: 类1. RowMapper接口的实现类2. BeanPropertyRowMapper(xx.class); 返回值的泛型*//** BeanPropertyRowMapper (底层反射),思路如下:* 1. 实现RowMapper接口* 2. 重写mapRow方法 : 每行ResultSet -> javaBean*1. 获取结果集中的数据* 知道结果集有哪些字段 -> 结果集元数据* 值 = resultSet.get(字段);* id值 = id* * 2. 设置到javabean中去 (需要传参: Student.class)* clazz = Student.class //获取类* Student s = clazz.newInstance(); // javabean规范: 默认调用空参构造* // Student s = new Student(); //等同于上面两行**//并不知道Student对象有哪些方法,通过反射如下* setIdMethod = clazz.getMethod("setId",int.class); * * //怎么知道Student对象中有setId方法呢?* //因为javabean规范 : 必有set方法。额外要求:set+名字(必须要和表中的字段名一致)* setIdMethod.invoke(s,id值);*/RowMapper<Student> rowMapper = new BeanPropertyRowMapper<>(Student.class);List<Student> list = template.query(sql, rowMapper);System.out.println(list); //打印出同query01()}}

21.redis安装:加载.conf

朋友圈数据缓存在手机内存,视频大量弹幕即海量数据先缓存再写入关系型数据库。如下两个存储文件第一次用是没有的。蓝横线是上一行的快捷方式,右击属性最后加上空格x.conf文件路径。Mysql默认3306端口,tomcat默认8080端口。

Nosql产品如下:Redis(c写的)劣势是value类型有5种,没有固定结构。HBase数据库分布式像二叉树查询效率高,数据不断添加,所以扩展性强。MongoDB像杂物袋,分门别类没必要。

redis-cli.exe命令行客户端不好用,用图形化客户端redis-desktop-manager-0.7.6.15.exe:链接:/s/1iJZcnSbRsejUgTlfxu_EKQ 提取码:f8ym 。Add New Connection如下:

redis服务器软件关了, 没有reload就不会保存。redis安装后默认有16个仓库,默认使用db0,用select换数据库。

22.操作:set/get,push/pop,add/rem

如下list重索序,不需要知道集合长度,遍历只要0到-1索引。

如下理解score是分数可重复。

23.持久化策略:存文件,.aof和.rdb文件删了,数据库里数据全没了

RDB(粗略):每次都保存全部数据,所以保存慢,因为是二进制,所以读取快。如0-15分钟操作2次,拍1次照保存硬盘。但15-27分钟又操作2次(只符合save 900 1策略),这时redis崩溃了,15-30分钟才拍照保存,所以丢失了2条数据。所以不频繁操作会丢数据。

AOF(细):写日志不是把整张照记录起来,而是记录一步(保存快),读取慢因为要从头看到尾才能把整个过程联系起来。AOF只能三者选其一,不像RDB三个策略都在线(默认开启),AOF是RDB(会丢数据)的补丁。在redis_windows.conf修改appendonly为yes,所以之前将redis_windows.conf文件名添加到快捷方式的目标中。

如下场景:一分钟6*2000=12000次(此时RDB符合save 60 10000,拍一次照,剩下20秒来不及拍,因为太频繁拍照会卡)。为什么先用RDB?因为读取快。

24.Jedis:java程序连接redis,拿到jedis

如下放入web/WEB-INF/lib并右击add as library。

package com.itheima01.jedis;import org.junit.Test;import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisPool;import redis.clients.jedis.JedisPoolConfig;public class JedisDemo {@Testpublic void method01(){String host = "127.0.0.1"; int port = 6379;Jedis jedis = new Jedis(host, port); // 1. 创建连接,不用连接池 jedis.set("book","thinking"); // 2. 访问redisjedis.hset("student","name","zs"); jedis.close(); // 3. 关闭连接System.out.println("测试");}@Testpublic void method02(){String host = "127.0.0.1";int port = 6379;JedisPoolConfig config = new JedisPoolConfig(); //连接池config.setMaxTotal(5); //最大连接数config.setMaxWaitMillis(2000); // 最长等待时间config.setMaxIdle(2); // 最大空闲数:最多允许两个连接不干活,超过两个会被回收掉,达到释放内存目的JedisPool pool = new JedisPool(config, host, port); //1. 初始化连接池 Jedis jedis = pool.getResource(); //2. 获取连接 String book = jedis.get("book"); //3. 访问redisSystem.out.println(book); //thinkingjedis.close(); //4. 将连接还给连接池pool.close(); // 销毁连接池,一般只有应用关闭时才用,释放内存}@Testpublic void method03(){//测试封装的框架Jedis jedis = JedisUtil.getResource();String book = jedis.get("book");System.out.println(book + "-------");jedis.close();}}

package com.itheima01.jedis;import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisPool;import redis.clients.jedis.JedisPoolConfig;import java.io.IOException;import java.io.InputStream;import java.util.Properties;import java.util.ResourceBundle;public class JedisUtil {private static JedisPool pool;/* static{String host = "127.0.0.1";int port = 6379;JedisPoolConfig config = new JedisPoolConfig();config.setMaxTotal(5); //最大连接数config.setMaxWaitMillis(2000); // 最长等待时间config.setMaxIdle(2); // 最大空闲数pool = new JedisPool(config, host, port);}*///如下用jedis.properties替代如上 /*static{Properties p = new Properties();InputStream is = JedisUtil.class.getClassLoader().getResourceAsStream("jedis.properties");try { p.load(is);String host = p.getProperty("host");Integer port = Integer.parseInt(p.getProperty("port"));Integer maxTotal = Integer.parseInt(p.getProperty("maxTotal"));Integer maxWaitMillis = Integer.parseInt(p.getProperty("maxWaitMillis"));Integer maxIdle = Integer.parseInt(p.getProperty("maxIdle")); //如下同上面JedisPoolConfig config = new JedisPoolConfig();config.setMaxTotal(maxTotal); //最大连接数config.setMaxWaitMillis(maxWaitMillis); // 最长等待时间config.setMaxIdle(maxIdle); // 最大空闲数pool = new JedisPool(config, host, port);} catch (IOException e) { //输入流有异常e.printStackTrace();}}*///如下可替代如上 static{/** ResourceBundle : 资源堆,用来替代Properties成为properties文件专属解析类* 1. 底层: 类加载器 -> 文件必须放在src下* 2. 只能加载properties文件 -> 文件的后缀名.properties不要写。*/ResourceBundle bundle = ResourceBundle.getBundle("jedis");String host = bundle.getString("host");Integer port = Integer.parseInt(bundle.getString("port"));Integer maxTotal = Integer.parseInt(bundle.getString("maxTotal"));Integer maxWaitMillis = Integer.parseInt(bundle.getString("maxWaitMillis"));Integer maxIdle = Integer.parseInt(bundle.getString("maxIdle"));//如下同上面JedisPoolConfig config = new JedisPoolConfig();config.setMaxTotal(maxTotal); //最大连接数config.setMaxWaitMillis(maxWaitMillis); // 最长等待时间config.setMaxIdle(maxIdle); // 最大空闲数pool = new JedisPool(config, host, port);}public static Jedis getResource(){Jedis jedis = pool.getResource();return jedis;}}

//jedis.properties文件 host = 127.0.0.1port = 6379maxTotal = 5maxWaitMillis = 2000maxIdle = 2

25.案例_好友列表:json = om.

25.1 前端:index.html

//index.html<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><script src="js/jquery-3.3.1.min.js"></script><script>$(function () {//页面加载事件$.get("/FriendServlet","",function (data) {//data// console.log(data)var content = ""$(data).each(function (index,element) {content += "<li>" + element.name + "</li>"})$("#myid").html(content) //因为<li>是html},"json")})</script></head><!--111111111111111111111111111111111111111111111111111111111111--><body><ul id="myid"></ul></body></html>

如下就是index.html效果。

25.2 web:FriendServlet .java

package com.heima.example.web;import com.heima.example.service.FriendService;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;@WebServlet(urlPatterns = "/FriendServlet")public class FriendServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {FriendService service = new FriendService(); //调用service层代码String json = service.findAllFriend();response.setContentType("text/html;charset=utf-8");response.getWriter().print(json);}}

25.3 service:FriendService.java

package com.heima.example.service;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.ObjectMapper;import com.heima.example.bean.Friend;import com.heima.example.dao.FriendDao;import com.itheima01.jedis.JedisUtil;import .apache.bcel.internal.generic.NEW;import redis.clients.jedis.Jedis;import java.util.List;/** service层: 业务逻辑 + 缓存 cache* 缓存弊端: 数据不更新 (查询走缓存,如果执行增删改, 重新查询数据库,更新缓存)* 如上括号里的更新缓存也会存在缓存延迟的情况(如朋友圈删除动态有时也能看见)* 朋友圈不是实时同步,如果实时同步对服务器来说压力大。好友列表的在线状态是实时同步的,用心跳长连接。*/public class FriendService {//service文件夹下//选中再ctrl + shift + u转为大写,"example_friend_list"变量改了,全局FRIEND_LIST_CACHE常量不用改public static final String FRIEND_LIST_CACHE = "example_friend_list"; public String findAllFriend() throws JsonProcessingException {Jedis jedis = JedisUtil.getResource();String json = jedis.get(FRIEND_LIST_CACHE); //直接从缓存里取if(json == null){//就从mysql数据库中取 FriendDao dao = new FriendDao();List<Friend> list = dao.findAll();ObjectMapper om = new ObjectMapper();json = om.writeValueAsString(list); //list转换为json jedis.set(FRIEND_LIST_CACHE,json); //记得往缓存里放一份json即字符串System.out.println("从mysql中查");}else{System.out.println("从redis中查");}jedis.close(); //记得还给连接池,不然5个用完就崩了return json;}}

25.4 dao:FriendDao.java

package com.heima.example.dao;import com.heima.example.bean.Friend;import com.heima.example.utils.JdbcUtil;import org.springframework.jdbc.core.BeanPropertyRowMapper;import org.springframework.jdbc.core.JdbcTemplate;import java.util.List;public class FriendDao {//Dao文件夹下public List<Friend> findAll() {String sql = "select * from user";JdbcTemplate template = JdbcUtil.getTemplate();List<Friend> list = template.query(sql, new BeanPropertyRowMapper<>(Friend.class));return list;}}

25.5 bean:Friend.java

package com.heima.example.bean;public class Friend {//bean文件夹下private Integer id;private String name;private String password;@Overridepublic String toString() {return "Friend{" +"id=" + id +", name='" + name + '\'' +", password='" + password + '\'' +'}';} public Integer getId() {return id;} public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}}

如下刷新浏览器index.html页面。

26.总结:存储过程(PL/SQL代码集,像没有返回值的自定义函数)和函数需要用户显示调用才执行,而触发器是由一个事件来触发运行,当某个事件发生时会自动地隐式运行,不能被显示的调用。冒泡,二分查找,sql多用group by

26.1 数据库优化:项目管理PMP证书,数据库DBA/OCM(Oracle Certified Master)证书

1.数据库开启缓存,还要避免缓存失效如下第一行:

3.小结果集适合建索引。如果占表超过50%不适合建索引,因为数据量达到一定量后会走全表扫描:原因是mysql内部有一个优化器进行最优策略即聚集索引和非聚集索引查询原理,数据量太大会先走非聚集索引,然后才走聚集索引获取数据。太频繁加个redis。

4.有limit 1,查到一行就不继续往下走。

5.数据库创建完一次连接后会永久处于连接状态,已经永久连接了,apache还给数据库不断发连接,给数据库增加了压力,大公司会解决这个。

6.myISAM适合大数据量查询,因为进行update时会进行表锁,这时候读表都是无效的,必须等插入操作完成。innoDB与myISAM相反,且支持B树索引,ACID(事务原子性,一致性,,,),行锁。

7.大量insert或delete时会把表整个锁起来,导致大量web服务器请求过来进不去表,导致宕机,所以用limit进行拆分。

8.不同数据类型占用硬盘空间不一样,如果占用硬盘空间小且紧凑,这样硬盘数据读写快。

9.字段长度统一,数据库计算偏移量轻松。从前端查出来的数据会多出来一些空格,用trim去除空格再封装进对象。

10.报错:该对象属性不为null或mysql查询数据为null…,用’空格’。数据库一字段查出赋值到java对象上,如果字段为null会报空指针异常。

11.enum速度比varchar快。

12.不管任何方式查询表,最终都会通过主键定位到数据,建立主键会有效提高性能。id主键多用int速度比varchar快。

14.避免使用rand(),order by rand()把数据库累死。

15.两个字段类型不一致,索引建不上。

26.2 数据库备份和恢复:冷热备份

1.冷备份:适用于myisam引擎,不适用于innoDB引擎:关闭mysql,如下或可以点进book文件夹里将.frm(表结构)和.MYD(表数据)和.MYI(表索引)文件拷贝出来,这三个组合到一起就是一张表,恢复的时候只需把你copy出来的这些文件再重新粘贴回去即可。

2.热备份:执行mysql安装目录下的bin/里面的这个mysqldump.exe工具。mysqldump是工具 -u是用户名 -p是密码 -A是全部的意思 -d是表结构 -t是表数据>是重定向的意思>右边是需要输出的路径和文件名。

2.1 全备份:mysqldump -uroot -p123456 -A > /back/backdb.sql

2.2 备份指定库命令:mysqldump -uroot -p123456 db1,db2 > /back/backdb.sql

2.3 备份指定表命令:mysqldump -uroot -p123456 db1 tb1 tb2, db2 tb2> /back/backdb.sql

2.4 备份表结构命令:mysqldump -uroot -p123456 -A -d > /back/backdb.sql

2.5 备份表数据命令:mysqldump -uroot -p123456 -A -t > /back/backdb.sql

2.6 恢复:source命令在执行时会显示详细信息,能看到执行到哪出错了:source /back/backdb.sql

数据库界面化工具(sqlyog navicat)也可以备份,但是从来没用过,数据量太大用增量备份xtrabackup。

26.3 数据库精度:高精度数据用SQL Server数据库

float(8,6)小数点前面占2位,小数点后面占6位。

【数据库1】mysql安装 DDL/DML DQL 外键约束 多表/子查询 事务 登陆案例 预编译 连接池 jdbcTemplate方法 redis安装 操作 持久化 Jedis 总结

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。