目录

今日事:

1、前后端分离(常见的是前端写静态页面,后端套用模板)

2、前端开发中的MVC/MVP/MVVM模式

一、数据库(MySql,Oracle,SQL Server)(基本的数据库操作语句,sql语句,存储过程,触发器)(JDBC编程)

1、sql语句——(sql结构化查询语言:structural query language)

2、MySql

3、Oracle

4、JDBC编程(Java中唯二基1的,ResultSet,rs.get(1);,PreparedStatement,ps.setFloat(1,313.0f);)


一、数据库(MySql,Oracle,SQL Server)(基本的数据库操作语句,sql语句,存储过程,触发器)(JDBC编程)

二、Java基础知识

三、中间件(基础的中间件环境部署问题)(tomcat,weblogic)

四、Java web应用程序开发(jsp,servlet,filter),接口开发

五、Java,HTML,JavaScript,Ajax,xml,css,JSON,jQuery,webservice

六、SSH,SSM(spring应用和设计模式),springboot,springcloud,微服务,MVC

七、Java多线程,高并发,同步,网络通信, JPA

八、分布式计算,数据挖掘

九、计算机网络,TCP/IP,可复用开发理念

十、plsql,navicat,maven,git,svn,redis,负载均衡

十一、OOP面向对象编程,OOD,ERP(企业资源计划),CRM(客户关系管理系统),ORM(关系型数据库)

十二、C/S,B/S,新兴技术(云计算,SaaS,区块链,大数据,人工智能等)

十三、Linux常用命令,Hadoop,dockers,dubbo

十四、测试管理工具QC,loadrunner;EXT,python,JSTL(EL,OGNL)

十五、前端框架(bootstrap,vue,node.js,webpack,爬虫,网络算法(神经网络算法))

十六、优化


今日事:

1、前后端分离(常见的是前端写静态页面,后端套用模板)

  • 程序的本质就是对数据的增删改查CRUD(create,retrieve,update,delete)
  • 前后端分离就是把数据操作和显示分离出来。前端专注做数据显示,后端专注做数据的操作。前端发送数据,后端修改
  • 后端本质是进行数据库的连接,对数据进行操作,业务分析与逻辑映射
  • 后端提供接口给前端调用,来触发后端对数据的操作

2、前端开发中的MVC/MVP/MVVM模式

MVC/MVP/MVVM都是常见的软件架构设计模式(Architectural Pattern),通过分离关注点来改进代码的组织方式

不同于设计模式(Design Pattern):只为解决某类问题而总结出的抽象方法。  一种架构模式通常使用多种设计模式

MVC:允许在不改变视图的情况下改变视图对用户输入的相应方式,用户对view的操作交给controller处理,在controller中响应view的事件,调用model的接口对数据进行操作,一旦model发生变化便通知相关视图进行更新。

  • model层:封装业务逻辑数据和对数据的处理方法(创建对象,封装数据,创建操作方法);一旦数据变化,model通知有关视图

          model和view之间使用观察者模式,view事先在model上注册,进而观察model,以便更新在model上发生变化的数据

  • view层:负责数据的显示(获取元素并渲染数据)

          view和controller之间使用了策略模式,view引入controller的实例来实现特定的响应策略(如按钮的click事件)

  • controller层:是模型视图之间的纽带,mvc将响应机制封装在controller对象中,当用户和应用产生交互,c层的事件触发器工作

缺点:业务逻辑集中在c层,使其臃肿,c与v连接紧密,复用性低,多view共用一个c困难

MVP(Model-View-Presenter):是mvc的改良,c/p业务逻辑控制,m管理数据与操作,v负责数据显示

  • mvc中v可直接访问m,mvp中不可以,而是通过为presenter提供接口,让p去更新m,再通过观察者模式更新v
  • mvp解耦v和m,完全分离视图和模型,可将v抽离做成组件,为上层操作提供一系列接口即可
  • mvp定义p和v之间的接口,用户对v的操作都转移到了p,p通知m更新后,p调用v提供的接口依据m更新视图。

缺点:在p中除业务逻辑外,还有大量v与m之间的数据同步代码,且没有数据绑定,视图过多时,p繁重且须随之改动

mvvm(Model-View-ViewModel):ViewModel即model of view视图的模型。

mvvm把view和model的同步逻辑自动化了,交给框架所提供的数据绑定功能进行负责,view显示的数据对应的是model的哪部分

  • model:数据层,类似于json数据对象,仅关注数据本身,不关心行为(格式化数据由view负责)
  • view:通过使用模板语法来声明式的将数据渲染进DOM,当viewmodel对model进行更新时,会通过数据绑定更新到 view
  • viewmodel:业务逻辑,数据绑定(双向数据绑定:类似于一个模板引擎,根据数据变更实时渲染)

数据劫持vue,发布-订阅模式knockout,backbone,脏值检查angular

简化业务与界面的依赖,解决数据频繁更新,低耦合,可重用性高

一、数据库(MySql,Oracle,SQL Server)(基本的数据库操作语句,sql语句,存储过程,触发器)(JDBC编程)

建表:先创建没有外键关联的表

1、sql语句——(sql结构化查询语言:structural query language)

sql对大小写不敏感,

句末;分号可不使用,分号是分割每条sql的标准方法,可在对服务器的相同请求中执行一条以上的语句。

sql使用单引号来环绕文本值,数值不需要

  • DML:数据操作语言(insert into,delete,update,select)
  • DDL:数据定义语言(create database/table/index,alter database/table,drop database/table/index
  • 去除列中的重复值:select distinct name from student;
  • <>不等于!=           between  and/or(可通过括号组合使用)               like
  • order by子句:用于根据指定的列对结果集进行排序,默认为asc升序,降序为desc
  • insert into 表(列1,列2...) values(值1,值2...);(插入数据)
  • update 表  set 列1=值1,列2=值2 where id=1;(修改数据)
  • delete from 表 where id=1;    delete from 表;     delete * from 表;
  • SQL top:规定要返回的记录的数目。 

MySQL——select * from tableName limit number(数量);        Oracle——select * from tableName where rownum <= number;

  • select top 2 * from tableName;(选取头两条)    select top 50 percent * from tableName;(选取50%的记录)
  • select * from student where name (not) like 'wl%' / '%wl' / '%wl%';(like操作符用于where子句中搜索列中的指定模式)
  • (通配符):%替代一个或多个字符,  _仅替代一个字符,  [charlist]字符列中的任一字符,  ><[^charlist] / [!charlist](不)

'[ALN]%'  以A,L,N开头,    '[!ALN]'  不以其开头

in操作符允许在where子句中规定多个值       select * from student where name in ('a','b')

between ... and选取介于两个值之间的数据范围。(可以是数值,文本,日期等)     范围之外not between ... and

列/表别名: (as) alias

SQL join :(用于根据两个或多个表中的列之间的关系,从这些表中查询数据。

  • select * from a inner join b on a.id = b.id order by a.id;(inner join内连接,表中至少一个匹配返回行)
  • select * from a left outer join b on a.id = b.id order by a.id;(left join左外连接,从左表返回所有行,即使右表中无匹             配行)
  • (right outer join右外连接,从右表返回所有行)
  • (full outer join全外连接,从左右表返回所有行)

union:合并两个或多个select语句的结果集,(union内部的select语句须有相同数量的列,列数据类型相似,列顺序相同)

             默认union选取不同的值(去重复),允许重复请用union all

select into从一个表中选取数据,插入到另一个表中,常用于创建表的备份文件或用于对记录进行存档

select * into s3 in 'backup.mdb' from s1 inner join s2 on s1.id = s2.id;(从一个以上的表中选取数据插入到另一个库的表中)

后端mysql怎么设置前端传后端页面 前端 后端 数据库_数据

SQL Constraints(约束)可在创建表时规定约束(create table),或在表创建之后(alter table)

  • not null非空, 
  • unique约束唯一标识数据库表中的每条记录 unique(id)——MySQL      unique——Oracle/SQL server/MS Access

           多个列定义:constraint a unique(id,name)

表定义后创建unique约束:alter table student add unique(id);     alter table student add constraint a unique(id,name);

撤销unique约束:alter table student drop index a;——MySQL ,    alter table student drop constraint a;——SQL server/Oracle/

  • primary key:约束唯一标识数据库表中的每条记录,必须包含唯一值,主键列不能包含null值,每个表有且仅有一个主键。

      primary key(id)——MySQL,    primary key——Oracle/SQL server/MS Access

      为多个列定义:constraint pk_pid primary key (id,name);

      表已存在后创建:alter table student add primary key(id); 

             重命名且为多个列定义:alter table student add constraint pk_pid primary key(id,name);(须把主键声明为not null)

      撤销:alter table student drop primary key;——MySQL,   alter table student drop constraint pk_pid;——SQL server/Oracle

  • foreign key:(一个表中的外键指向另一个表中的主键),用于预防破坏表之间连接的动作,防止非法数据插入外键列。

    foreign key(id_p) references person(id_p)——MySQL,  id_p int foreign key references person(id_p)——Oracle/SQL server

    命名外键约束:contraint fk_p_s foreign key(id_p) references person(id_p),

    表已存在创建:alter table student add  foreign key(id_p) references person(id_p)

    重命名:alter table student add constraint fk_p_s foreign key(id_p) references person(id_p)

    撤销:alter table student drop foreign key fk_p_s——MySQL,  alter table student drop constraint fk_p_s——Oracle/SQL se

  • check检查约束:用于限制列中值的范围。(列只允许特定的值,表中会在特定的列中对值进行限制)

      check (id_p>0)——MySQL,  id_p int not null check(id_p>0)——SQL server/Oracle/MS Access

      命名check约束及为多个列定义约束:constraint chk_p check(id_p>0 and city='zz')

      表已存在创建:alter table person add check(id_p>0);

             命名check约束,多个列:alter table person add contraint chk_p check(id_p>0 and city='zz');

      撤销:alter table person drop check chk_p;——MySQL,  alter table person drop constraint chk_p;——Oracle/SQL server

  • default:向列中插入默认值。(可使用类似getdate()这样的函数,default插入系统值) orderDate date default getdate(),

    表已存在创建:alter table person alter city set default 'sh';——MySQL,  alter table person alter column city set default 'sh';

    撤销:alter table person alter city drop default;——MySQL,  alter table person alter column city drop default;——Oracle/

create index:在表中创建索引。(在不读取整个表时,索引使数据库应用程序更快地查找数据)(看不到,能加速搜索/查询)

注释:更新一个包含索引的表需要比更新一个没有索引的表更多的时间,这是由于索引本身也需要更新。因此,理想的做法是仅仅在常常被搜索的列(以及表)上面创建索引。

create (unique) index 索引名 on person (需要索引的列1,列2 [desc]);       

unique唯一的索引意味着两个行不能拥有相同的索引值。          desc降序索引某个列的值,             可以有多个列

drop:删除索引,表,数据库

drop database 数据库名;     drop table  表名;      truncate table 表名;(仅删除数据,结构不变)

drop index 索引名;——Oracle。          alter table person drop index 索引名;——MySQL。

alter:用于在已有的表中添加,修改或删除列。

alter table person add 列名 列类型;     alter table person drop column 列名;     alter table person alter column 列名 列类型;

auto_increment:自动增长(在新纪录插入表时生成一个唯一的数字)(默认值为1)——MySQL

      让auto_increment 序列以其他值起始:alter table person auto_increment = 100;——MySQL

在Oracle中需先创建序列sequence:    create sequence 名    minvalue 1    start with 1      increment by 1     cache 10

insert into person (id_p,name,city) values(名.nextval,'hjj','zz');

view:视图,可视化的表。(是基于sql语句结果集的可视化的表),(向用户精确的提交我们希望提交的数据)

创建视图:选取表中所有单位价格高于平均单位价格的数据

create view [products above average price] as select * from product where price>(select avg(price) from product);

select * from [projects above average price]   where name='wl';

视图来自于另一个视图中选取的数据:

create view [a from b] as select distinct name,sum(price) as aprice from [b from c] group by name;

更新视图:

create/replace view [products above average price] as select * from products where price>(select avg(price) from product);

撤销视图:

drop view [products above average price]

SQL Date:(若希望使查询简单且易维护,请不要在日期中使用时间部分)

MySQL——date:yyyy-mm-dd,      datetime:yyyy-mm-dd hh:mm:ss,      timestamp yyyy-mm-dd hh:mm:ss    year:yyyy或yy

后端mysql怎么设置前端传后端页面 前端 后端 数据库_MySQL_02

SQL null:null值是遗漏的未知数据。默认表列可以存放null值。(null与0是不等价的),(用作未知的或不适用的值的占位符)

测试null值,使用is null 或is not null               select * from student name is (not) null

null数据运算处理:select name ,price1*(p1+ifnull(p2,0)) from student;——MySQL(或是使用coalesce(p2,0)处理)

                               nvl(p2,0)——Oracle,     isnull(p2,0)——SQL server/MS Access

MySQL数据类型:三种主要的是文本,数字和日期/时间类型。

后端mysql怎么设置前端传后端页面 前端 后端 数据库_MySQL_03

后端mysql怎么设置前端传后端页面 前端 后端 数据库_数据_04

后端mysql怎么设置前端传后端页面 前端 后端 数据库_SQL_05

SQL函数function:(sql拥有很多可用于计数和计算的内建函数),(函数类型:aggregate function,scalar function)

在分组聚合操作中,在查询列时,除了聚合函数运算外,其他表达式必须包含在group by子句中

使用GROUP BY进行分组查询时应注意如下问题: (1)GROUP BY子句中的列名只能是FROM子句所列表的列名,不能是列的别名。 (2)使用GROUP BY子句后,SELECT子句的目标列表达式所涉及的列必须满足:要么在GROUP BY子句中,要么在在某个统计函数中。 (3)如果分组后还要求按一定的条件对这些组进行筛选,最终只输出满足指定条件的组,则可以使用HAVING短语指定筛选条件。

(按姓名分组)查询同名的人有多少个:select name count(*) from student order by name;        张三,2         李四,1  

列分组:select 列1,列2 from student order by 列1,列2

分组聚合:(男女生平均年龄)select sex,avg(age) as avgAge from student group by sex;

                  (男女生人数)select sex,count(sex) as 人数 from student group by sex;

SELECT Customer,OrderDate,SUM(OrderPrice) FROM Orders  GROUP BY Customer,OrderDate

与having子句:对分组筛选后的结果再次筛选(having子句中可包含聚合函数)

(按性别分组,求平均年龄,并查平均年龄大于21的数据)select avg(age),sex from student group by sex having avg(age)>21

与order by:select 学号,avg(成绩) as 平均成绩 from grade group by 学号 order by 平均成绩;

aggregate合计函数:操作面向一系列的值,返回一个单一的值。

avg(column),count(column),count(*),first(column),last(column),max(column),min(column),sum(column)

count(distinct column)

scalar标量函数:操作面向单一值,并返回一个基于输入值的单一值。

后端mysql怎么设置前端传后端页面 前端 后端 数据库_后端mysql怎么设置前端传后端页面_06

SELECT Customer,SUM(OrderPrice) FROM Orders
WHERE Customer='Bush' OR Customer='Adams'
GROUP BY Customer
HAVING SUM(OrderPrice)>1500

mid():从文本字段中提取字符。  mid(name,1,[length])    ucase(),   lcase(),   len(),   

round():把数值字段舍入为指定的小数位数。  round(price,2)         

now():          select * now() as selTime from student;

format():对字段的显示进行格式化        select *  format(now(),'yyyy-mm-dd') as selTime from student;

后端mysql怎么设置前端传后端页面 前端 后端 数据库_数据_07

2、MySql

create database databaseName;(创建数据库)

use databaseName;(使用数据库)

drop table if exists tableName;(删除表)

create table tableName(id int(11) not null auto_increment comment 'id',...)engine=innodb comment 'table' default=utf8;(建表)

constraint fk_关联表名_本表名 foreign key(外键字段) references 关联表(id);     //外键关联

insert into tableName values(1,'qq',2);(插入数据)

select count(*),* from tableName limit start,count;(分页查询)

update tableName set password=121 where id=1;(修改数据)

delete from tableName where id=1;(删除数据)

"ser/bin/mysqldump.exe" -uroot -padmin -hlocalhost -p3306 test(备份的数据库名) -r d:\test.sql(备份后的文件);(mysql备份)

"ser/bin/mysql.ext" -uroot -padmin test < d:\test.sql;(MySQL还原)

MySql——innodb         MySQL5.7默认innodb;(有简单的方式)

(某个表:show table status from 数据库名;(查看表类型),alter table hero engine = innodb;(修改表类型)

检查是否开启innodb:   show variables like 'have_%';    在结果中的have_innodb,如果显示为YES,即表示启动了。 如果是NO或者DISABLED表示未启动。如果不存在也表示未启动。

首先执行命令停止MySQL     net stop mysql;

定位到D:\tools\MYSQL\mysql-5.1.57-win32\data 目录下,找到这3个文件    ib_logfile0        ib_logfile1          ibdata1备份后删除

在配置文件中添加     打开文件:D:\tools\MYSQL\mysql-5.1.57-win32\my.ini    添加一行     default-storage-engine=InnoDB

启动MySQL      net start;                 再检测:    show variables like 'have_%';

MySQL修改密码:

使用当前密码进入MySQL    "...\mysql.exe" -uroot -padmin;                    mysql -hlocalhost -uroot -padmin;

修改:    set password for root@localhost = password('121');

装卸:

控制面板--装卸,删除C盘MySQL目录(C:\Program Files\MySQL),删除my.ini在C:\WINDOWS目录下,

运行注册表:win+r   regedit

删除key1:HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Eventlog\Application\MySQL

删除key2:HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Services\Eventlog\Application \MySQL

                  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\MySQL

删除ProgramData下的文件:C:\ProgramData\MySQL Server 5.5(默认隐藏)    

                                              C:\Documents and Settings\All Users\Application Data\MySQL(XP和win7对应的文件)

3、Oracle

服务器安装:默认安装(非中文,非空格)      管理员密码一般输入sys              CTRL+F8执行sql语句

客户端安装:pl-sql developer。      登录:sys/sys   orcl      connect as sysdba(navicat连接时,注意将角色改为sysdba

序列号:  KF46-6HV4-2UAC-YYEB-R82Y-6JB4-JVNH-WH     QWLJ-S6UT-WC93-5XW7-WK3Q-F7KA-SBEU-XL

字符串连接符:    select last_name || ' ' || first_name '姓名' from student;(别名as可选,单引多引可选)

条件限定:distinct,<>不等于,between ... and,IN(值1,值2),like(%,_)        逻辑条件:and,or,not

查询所在部门为null的员工,即该员工暂时还未分配工作部门:select * from hr.employees where department_id is null

排序查询:order by         关联查询:left join 表关联,on指定关联字段。

统计函数:count,max,min,avg        分组查询:group by。       having对分组函数进行条件判断。

select avg(salary),e.department_id,e.first_name  from hr.employees e group by e.department_id,e.first_name
having avg(salary)>4200

子查询:同时执行多条sql语句(将一条sql语句的查询结果作为条件来执行另一条sql语句)

Oracle使用rownum进行分页查询: 

查出薪水最高的5-10条数据:

select e2.* from (select rownum r , e1.* from (select e.* from hr e order by e.salary) e1)e2 where e2.r>=5 and e2.r<=10;

Oracle表字段类型:varchar和varchar2的区别,两种都是变长的,对于汉字(unicode)的处理有区别:
varchar如果放的是英文和数字,就用一个字节存放,如果是汉字(unicode),就用两个字节
varchar2 统一使用两个字节,                             一般都直接使用varchar2,使用varchar很少了

插入数据:insert into table() values(); commit;(提交这一次插入行为,否则数据库不生效)

Oracle序列:sequence,通常被用来作为id插入到表中。

创建: create sequence hero_seq     increment by 1     start with 1       maxvalue 999999     cache 10

使用: select hero_seq.nextval from dual(获取hero_seq下个值)   select hero_seq.currval from dual(获取hero_seq当前值)

插入:insert into hero (id,name,hp,mp,damage,armor) values(hero_seq.nextval,'炸弹人',450,200,45,3);(作为id插入表中)

修改字段:update hero set damage =46,armor = 5 where id=3;

删除数据:delete from hero where id=1;(删除操作是可以回滚的,只要在提交之前,进行回滚就可把删除的数据还原)

                  truncate table hero;(truncate比delete更快,更彻底,不能回复,不能回滚:删除表里所有记录)

alter修改表结构:  alter table hero add (kills number);(增加新列)    alter table hero modify(name varchar2(300));(修改列)

                               alter table hero drop column kills;(删除列:执行删除需要权限)

删除表:drop table hero;(不能回滚)

约束:unique,not null,primary key,foreign key

给约束命名:constraint uk_hero(表名)_name(字段名) unique (name);

给已存在的表增加约束:alter table hero add constraint pk_hero_id primary key (id)

删除约束:alter table hero drop constraint uk_hero_name

外键约束:constraint fk_killer_hero foreign key (killerid) references hero(id),          (击杀次数)

                  constraint fk_killed_hero foreign key (killedid) references hero(id)          (被击杀次数)

Oracle视图:    create view herosimple as ( select id, name from hero )    select * from herosimple;

创建用户:登录plsql——左边菜单,选择users右键new——用户信息,对象权限,角色权限,系统权限——apply应用

                  登录验证是否创建成功:身份改为normal即可(这样使用fzy身份创建的表,才可以通过jdbc访问)

 

后端mysql怎么设置前端传后端页面 前端 后端 数据库_SQL_08

若遇到超出表空间限额,则执行sql:alter user bigsword quota unlimited on users;

plsql远程连接:E:\oracle11g\product\11.2.0\dbhome_1\NETWORK\ADMIN下的tnsnames.ora配置文件修改

参考   https://jingyan.baidu.com/article/b0b63dbfcd34834a4930704a.html

4、JDBC编程(Java中唯二基1的,ResultSet,rs.get(1);,PreparedStatement,ps.setFloat(1,313.0f);)

 JDBC:(Java DataBase Connection) 是通过JAVA访问数据库 

导入驱动连接jar包(右键project->property->java build path->libaries->add external jars)

package jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBC {

	//导包步骤:右键project->property->java build path->libaries->add external jars
	//import的都是java.sql.*;
	public static void main(String[] args) {
		Connection c = null;
		Statement st = null;
		try {
			/*
			 * 1、初始化驱动:若忘记则会抛出ClassNotFoundException
			 * Class.forName是把这个类加载到JVM中,加载的时候,就会执行其中的静态初始化块,完成驱动的初始化的相关工作
			 */
			Class.forName("com.mysql.jdbc.Driver");
			/*
			 * 2.建立与数据库的连接
			 * 需要ip,端口号,数据库名,编码方式,账号,密码
			 * 若有误会抛出SQLException
			 */
			c =DriverManager.getConnection(
					"jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8","root","123456"
					);
			/*
			 * 3、创建执行SQL语句的Statement对象
			 * 根据连接创建sql执行对象
			 */
			st = c.createStatement();
			/*
			 * 4、准备sql语句(字符串要用单引号)
			 */
			String sql = 
					"insert into user1 values"
					+ "(null,"+"'fzy'"+","+"'fzy111'"+","+"'22'"+")";
			/*
			 * 5、s.execute()执行sql语句。
			 */
			st.execute(sql);
			
			
		} catch (ClassNotFoundException e) {
			// TODO: handle exception
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally{
			/*
			 * 6、数据库的连接是有限资源,操作结束后,关闭。(采用就近原则)
			 */
			if(st != null)
				try {
					st.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			if(c != null)
				try {
					c.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		}
	}
}

使用try-with-resource的方式自动关闭连接(jdk7特性)  (关闭流方式)  Connection和Statement都实现了AutoCloseable接口

package jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * try-with-resource关闭流方式
 * @author fzywhy
 *
 */
public class JDBCtry {

	public static void main(String[] args) {
		
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		try (
			Connection c = 
DriverManager.getConnection("jdbc:mysql://172.0.0.1:3306/test?characterEncoding=UTF-8","root","123456");
			Statement st = c.createStatement();
		)
		{
			String sql = "insert into user1 values(null,"+"'fzy'"+","+"'fzy111'"+","+"'22'"+")";
			st.execute(sql);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}

查询st.executeQuery(sql);

package jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBCselect {

public static void main(String[] args) {
		
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		try (
			Connection c = 
DriverManager.getConnection("jdbc:mysql://172.0.0.1:3306/test?characterEncoding=UTF-8","root","123456");
			Statement st = c.createStatement();
		)
		{
//			String sql = "insert into user1 values(null,"+"'fzy'"+","+"'fzy111'"+","+"'22'"+")";
//			st.execute(sql);
			/*
			 * st.executeQuery(sql)执行sql查询语句
			 */
			String sql = "select * from user1";
			//执行查询语句,并把结果集合返回给ResultSet
			ResultSet rs = st.executeQuery(sql);
			while(rs.next()) {
				int id = rs.getInt("id");//可使用字段名
				String username = rs.getString(2);//也可使用字段的顺序下标
				String password = rs.getString(3);
				String perms = rs.getString("perms");
				System.out.printf("%d\t%s\t%s\t%s\n", id,username,password,perms);
			}
			//statement关闭的时候,自动关闭ResultSet
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}

判断账号密码是否正确:

package jdbc;
   
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
   
public class TestJDBC {
    public static void main(String[] args) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
 
        try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
                "root", "admin");
                Statement s = c.createStatement();
                 
                ) {
            String name = "dashen";
            //正确的密码是:thisispassword
            String password = "thisispassword1";
   
            String sql = "select * from user where name = '" + name +"' and password = '" + password+"'";
              
            // 执行查询语句,并把结果集返回给ResultSet
            ResultSet rs = s.executeQuery(sql);
              
            if(rs.next())
                System.out.println("账号密码正确");
            else
                System.out.println("账号密码错误");
             
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
   
    }
}

获取总数:

package jdbc;
 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
 
public class TestJDBC {
    public static void main(String[] args) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
 
        try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
                "root", "admin"); Statement s = c.createStatement();) {
 
            String sql = "select count(*) from hero";
 
            ResultSet rs = s.executeQuery(sql);
            int total = 0;
            while (rs.next()) {
                total = rs.getInt(1);
            }
 
            System.out.println("表Hero中总共有:" + total+" 条数据");
 
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
 
    }
}

分页查询:

package how;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
   
public class TestJDBC {
    public static void main(String[] args) {
        list(0,6);
    }
    public static void list(int start, int count){
        //进制转化
        int cf=0;
        int index=0;
        int w=start;
        while(w!=0){ 
            w/=10;
            int wei=start%10;
            index+=(Math.pow(2, cf)*wei);
            cf++;
        }
        index+=1;
        //执行sql语句
        String sql="select * from hero limit "+index+","+count;
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try(Connection c = DriverManager.getConnection(
                 "jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");  
              Statement s = c.createStatement();){
             ResultSet rs = s.executeQuery(sql);
             while (rs.next()) {
                 int id = rs.getInt("id");
                 String name = rs.getString(2);
                 float hp = rs.getFloat("hp");
                 int damage = rs.getInt(4);
                 System.out.printf("%d\t%s\t%f\t%d%n", id, name, hp, damage);
             }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

预编译PreparedStatement:(优点:1、使用参数设置,不需字符串拼接,可读性和维护性好,不易犯错。

                                                            2、性能更优:有预编译机制,性能更快。数据库对带?的sql进行预编译,每次执行,只需要传输参数到数据库端即可。  比较:网络传输量比statement小;数据库不需要再进行编译,响应更快。

                                                            3、防止SQL注入式攻击(字符串拼接where条件恒成立),PreparedStatement使用参数设置)

package jdbc;
    
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
    
public class TestJDBC {
    public static void main(String[] args) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
  
        String sql = "insert into hero values(null,?,?,?)";
        try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");
            // 根据sql语句创建PreparedStatement
            PreparedStatement ps = c.prepareStatement(sql);
        ) {
             
            // 设置参数
            ps.setString(1, "提莫");
            ps.setFloat(2, 313.0f);
            ps.setInt(3, 50);
            // 执行
            ps.execute();
  
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    
    }
}

execute与executeUpdate都可以执行增删改

不同点:execute可执行查询语句,通过getResultSet取出结果集;executeUpdate不能执行查询语句

              execute返回Boolean类型,true表示执行的是select,false表示执行的是增删改

              executeUpdate返回的是int,表示有多少条数据受到了影响。

获取自增长id:

PreparedStatement ps = c.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);//确保会返回自增长id

ResultSet rs = ps.getGeneratedKeys();    if(rs.next){int id = rs.getInt(1);}

获取表的元数据:

元数据:和数据库服务器相关的数据(egg:数据库版本,哪些表,哪些字段,字段类型)

package jdbc;
  
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
  
public class TestJDBC {
  
    public static void main(String[] args) throws Exception {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
 
        try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");) {
  
            // 查看数据库层面的元数据
            // 即数据库服务器版本,驱动版本,都有哪些数据库等等
  
            DatabaseMetaData dbmd = c.getMetaData();
  
            // 获取数据库服务器产品名称
            System.out.println("数据库产品名称:\t"+dbmd.getDatabaseProductName());
            // 获取数据库服务器产品版本号
            System.out.println("数据库产品版本:\t"+dbmd.getDatabaseProductVersion());
            // 获取数据库服务器用作类别和表名之间的分隔符 如test.user
            System.out.println("数据库和表分隔符:\t"+dbmd.getCatalogSeparator());
            // 获取驱动版本
            System.out.println("驱动版本:\t"+dbmd.getDriverVersion());
  
            System.out.println("可用的数据库列表:");
            // 获取数据库名称
            ResultSet rs = dbmd.getCatalogs();
  
            while (rs.next()) {
                System.out.println("数据库名称:\t"+rs.getString(1));
            }
  
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
  
    }
}

JDBC事务提交:保护数据的完整性,安全性和正确性。

表类型必须是innodb:show table status from 数据库名;        alter table hero engine = innodb;

在事务中的多个操作,要么都成功,要么都失败。

package jdbc;
  
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
  
public class TestJDBC {
    public static void main(String[] args) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
 
        try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");
            Statement s = c.createStatement();) {
  
            // 有事务的前提下
            // 在事务中的多个操作,要么都成功,要么都失败
  
            c.setAutoCommit(false);
  
            // 加血的SQL
            String sql1 = "update hero set hp = hp +1 where id = 22";
            s.execute(sql1);
  
            // 减血的SQL
            // 不小心写错写成了 updata(而非update)
  
            String sql2 = "updata hero set hp = hp -1 where id = 22";
            s.execute(sql2);
  
            // 手动提交
            c.commit();
  
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
  
    }
}

JDBC:ORM=Object Relationship Database Mapping  对象和关系数据库的映射(一个对象,对应数据库里的一条记录)

package how;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
   
 
public class TestJDBC {
    
    public static Hero get(int id) {
        Hero hero = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
  
        try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");
            Statement s = c.createStatement();) {
  
            String sql = "select * from hero where id = " + id;
    
            ResultSet rs = s.executeQuery(sql);
    
            // 因为id是唯一的,ResultSet最多只能有一条记录
            // 所以使用if代替while
            if (rs.next()) {
                hero = new Hero();
                String name = rs.getString(2);
                float hp = rs.getFloat("hp");
                int damage = rs.getInt(4);
                hero.name = name;
                hero.hp = hp;
                hero.damage = damage;
                hero.id = id;
            }
    
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return hero;
    
    }
    //把一个Hero对象插入到数据库中
    public static void add(Hero h){
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
  
        try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");
            Statement s = c.createStatement();){
            String name=h.name;
            float hp=h.hp;
            int damage=h.damage;
            //int id=h.id;
            //这里id可以让它自动生成,如果自己定义的话,要判断该id是否被占用
            String sql="insert into hero values(null,"+"'"+name+"',"+hp+","+damage+")";
            s.execute(sql);
        }catch(SQLException e){
            e.printStackTrace();
        }
    }
    //把这个Hero对象对应的数据删除掉
    public static void delete(Hero h){
        try{
            Class.forName("com.mysql.jdbc.Driver");
        }catch(ClassNotFoundException e){
            e.printStackTrace();
        }
         
        try(Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");
                Statement s = c.createStatement();){
            int id=h.id;
            String sql = "delete from hero where id ="+id;
            s.execute(sql);
        }catch(SQLException e){
            e.printStackTrace();
        }       
    }
    //更新这条Hero对象
    public static void update(Hero h){
        try{
            Class.forName("com.mysql.jdbc.Driver");
        }catch(ClassNotFoundException e){
            e.printStackTrace();
        }
         
        try(Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");
                Statement s = c.createStatement();){
            String name=h.name;
            float hp=h.hp;
            int damage=h.damage;
            int id=h.id;
            String sql = "update hero set name = '"+name+"',hp="+hp+",damage="+damage+" where id = "+id;
            s.execute(sql);
        }catch(SQLException e){
            e.printStackTrace();
        }
    }
    //把所有的Hero数据查询出来,转换为Hero对象后,放在一个集合中返回
    public static List<Hero> list(){
        try{
            Class.forName("com.mysql.jdbc.Driver");
        }catch(ClassNotFoundException e){
            e.printStackTrace();
        }
         
        try(Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");
                Statement s = c.createStatement();){
            String sql = "select * from hero";
            ResultSet rs = s.executeQuery(sql);
            List<Hero> l=new ArrayList<>();
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString(2);
                float hp = rs.getFloat("hp");
                int damage = rs.getInt(4);
                Hero h= new Hero();
                h.id=id;
                h.name=name;
                h.hp=hp;
                h.damage=damage;
                l.add(h);
            }
            return l;
        }catch(SQLException e){
            e.printStackTrace();
        }
        return null;
    }
    public static void main(String[] args) {
            
        Hero h = get(107);
        System.out.println(h.name);
        Hero h1=new Hero();
        h1.damage=55;
        h1.hp=305;
        h1.id=3;
        h1.name="守望者";
        add(h1);
        delete(h);
        Hero h2=new Hero();
        h2.damage=55;
        h2.hp=305;
        h2.id=3;
        h2.name="逝去者";
        update(h2);
        List<Hero> l=list();              
        System.out.println(l.size());
    }
}

JDBC:DAO=Data Access Object数据访问对象

DAO接口:

package jdbc;
  
import java.util.List;
 
import charactor.Hero;
  
public interface DAO{
    //增加
    public void add(Hero hero);
    //修改
    public void update(Hero hero);
    //删除
    public void delete(int id);
    //获取
    public Hero get(int id);
    //查询
    public List<Hero> list();
    //分页查询
    public List<Hero> list(int start, int count);
}

HeroDao类实现dao接口并实现接口方法:(把数据库相关的操作都封装在这个类里面,其他地方看不到JDBC的代码)

package jdbc;
  
import java.sql.Connection;
 
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
  
import charactor.Hero;
  
public class HeroDAO implements DAO{
    //把驱动的初始化放在了此类的构造方法中(初始化驱动只需要执行一次)
    public HeroDAO() {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    //所有的数据库操作都需要先拿到一个数据库连接,有变化可只在此处更改(易维护,更简洁)
    public Connection getConnection() throws SQLException {
        return DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8", "root",
                "admin");
    }
  
    public int getTotal() {
        int total = 0;
        try (Connection c = getConnection(); Statement s = c.createStatement();) {
  
            String sql = "select count(*) from hero";
  
            ResultSet rs = s.executeQuery(sql);
            while (rs.next()) {
                total = rs.getInt(1);
            }
  
            System.out.println("total:" + total);
  
        } catch (SQLException e) {
  
            e.printStackTrace();
        }
        return total;
    }
  
    public void add(Hero hero) {
  
        String sql = "insert into hero values(null,?,?,?)";
        try (Connection c = getConnection(); PreparedStatement ps = c.prepareStatement(sql);) {
  
            ps.setString(1, hero.name);
            ps.setFloat(2, hero.hp);
            ps.setInt(3, hero.damage);
  
            ps.execute();
  
            ResultSet rs = ps.getGeneratedKeys();
            if (rs.next()) {
                int id = rs.getInt(1);
                hero.id = id;
            }
        } catch (SQLException e) {
  
            e.printStackTrace();
        }
    }
  
    public void update(Hero hero) {
  
        String sql = "update hero set name= ?, hp = ? , damage = ? where id = ?";
        try (Connection c = getConnection(); PreparedStatement ps = c.prepareStatement(sql);) {
  
            ps.setString(1, hero.name);
            ps.setFloat(2, hero.hp);
            ps.setInt(3, hero.damage);
            ps.setInt(4, hero.id);
  
            ps.execute();
  
        } catch (SQLException e) {
  
            e.printStackTrace();
        }
  
    }
  
    public void delete(int id) {
  
        try (Connection c = getConnection(); Statement s = c.createStatement();) {
  
            String sql = "delete from hero where id = " + id;
  
            s.execute(sql);
  
        } catch (SQLException e) {
  
            e.printStackTrace();
        }
    }
  
    public Hero get(int id) {
        Hero hero = null;
  
        try (Connection c = getConnection(); Statement s = c.createStatement();) {
  
            String sql = "select * from hero where id = " + id;
  
            ResultSet rs = s.executeQuery(sql);
  
            if (rs.next()) {
                hero = new Hero();
                String name = rs.getString(2);
                float hp = rs.getFloat("hp");
                int damage = rs.getInt(4);
                hero.name = name;
                hero.hp = hp;
                hero.damage = damage;
                hero.id = id;
            }
  
        } catch (SQLException e) {
  
            e.printStackTrace();
        }
        return hero;
    }
  
    public List<Hero> list() {
        return list(0, Short.MAX_VALUE);
    }
  
    public List<Hero> list(int start, int count) {
        List<Hero> heros = new ArrayList<Hero>();
  
        String sql = "select * from hero order by id desc limit ?,? ";
  
        try (Connection c = getConnection(); PreparedStatement ps = c.prepareStatement(sql);) {
  
            ps.setInt(1, start);
            ps.setInt(2, count);
  
            ResultSet rs = ps.executeQuery();
  
            while (rs.next()) {
                Hero hero = new Hero();
                int id = rs.getInt(1);
                String name = rs.getString(2);
                float hp = rs.getFloat("hp");
                int damage = rs.getInt(4);
                hero.id = id;
                hero.name = name;
                hero.hp = hp;
                hero.damage = damage;
                heros.add(hero);
            }
        } catch (SQLException e) {
  
            e.printStackTrace();
        }
        return heros;
    }
  
}

JDBC数据库连接池:(与线程池类似,但实现思路不一样)

每个数据库操作都需要创建一个连接,创建连接和关闭连接都比较消耗时间,多线程并发时会比较卡顿。

且一个数据库同时支持的连接总数是有限的,多线程并发量很大时,数据库连接总数就会消耗光,后续线程发起的DB连接失败。

连接池原理:在使用之前,创建好一定数量的连接,线程需要时向连接池借用连接,使用完毕后归还,供下一个或其他线程使用,多线程并发,连接池中的连接被借用完毕,其他线程会临时等待,直到有连接被归还,再继续使用,整个过程,连接不会被关闭,不断的被循环使用。

package jdbc;
  
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
  
public class ConnectionPool {
  
    List<Connection> cs = new ArrayList<Connection>();
  
    int size;
  
    //ConnectionPool() 构造方法约定了这个连接池一共有多少连接
    public ConnectionPool(int size) {
        this.size = size;
        init();
    }
    /*
     * 在init() 初始化方法中,创建了size条连接。 注意,这里不能使用try-with-resource这种自动关 
     * 闭连接的方式,因为连接恰恰需要保持不关闭状态,供后续循环使用
     */
    public void init() {
          
        //这里恰恰不能使用try-with-resource的方式,因为这些连接都需要是"活"的,不要被自动关闭了
        try {
            Class.forName("com.mysql.jdbc.Driver");
            for (int i = 0; i < size; i++) {
                Connection c = DriverManager
                        .getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8", "root", "admin");
  
                cs.add(c);
  
            }
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    //getConnection, 判断是否为空,如果是空的就wait等待,否则就借用一条连接出去
    public synchronized Connection getConnection() {
        while (cs.isEmpty()) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        Connection c = cs.remove(0);
        return c;
    }
    /*
     * returnConnection, 在使用完毕后,归还这个连接到连接池,并且在归还完毕后,调用 
     * notifyAll,通知那些等待的线程,有新的连接可以借用了。
     */
    public synchronized void returnConnection(Connection c) {
        cs.add(c);
        this.notifyAll();
    }
  
}

测试数据库连接池:

package jdbc;
  
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
 
import jdbc.ConnectionPool;
   
public class TestConnectionPool {
   
    public static void main(String[] args) {
        ConnectionPool cp = new ConnectionPool(3);
        for (int i = 0; i < 100; i++) {
            new WorkingThread("working thread" + i, cp).start();
        }
   
    }
}
   
class WorkingThread extends Thread {
    private ConnectionPool cp;
   
    public WorkingThread(String name, ConnectionPool cp) {
        super(name);
        this.cp = cp;
    }
   
    public void run() {
        Connection c = cp.getConnection();
        System.out.println(this.getName()+ ":\t 获取了一根连接,并开始工作"  );
        try (Statement st = c.createStatement()){
             
            //模拟时耗1秒的数据库SQL语句
            Thread.sleep(1000);
            st.execute("select * from hero");
   
        } catch (SQLException | InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        cp.returnConnection(c);
    }
}