* 测试分类:
1. 黑盒测试: 不需要写代码,给输入值,看程序是否能够输出期望的值
2. 白盒测试: 需要写代码,关注程序具体的执行流程
* Junit使用: 白盒测试
* 步骤
1. 定义一个测试类 (测试用例)
* 建议:
* 测试类名: 被测试的类名
* 包名 : xxx.xxx.xx.test cn.itcast.test
2. 定义测试方法:可以独立运行
* 建议:
* 方法名: test测试的方法名 testAdd()
* 返回值: void
* 参数列表: 空参
3. 给方法加@Test
4. 导入junit依赖环境
* 判定结果
* 红色是错误
* 绿色是正确
* 一般我们会使用断言操作来处理结果
Assert.assertEquals(期望值, 实际值);
* 补充
* @Before
* 修饰的方法会在测试方法之前被自动的执行
* @After
* 修饰的方法会在测试方法执行之后被执行
package cn.itcast.junit;
/**
* 计算器类
*/
public class Calculator {
/**
* 加法
* @param a
* @param b
* @return
*/
public int add (int a, int b) {
// int i = 3 / 0;
return a + b;
}
/**
* 减法
* @param a
* @param b
* @return
*/
public int sub (int a, int b) {
return a - b;
}
}
package cn.itcast.test;
import cn.itcast.junit.Calculator;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class CalculatorTest {
/**
* 初始化方法:
* 用于资源申请, 所有的测试方法在执行之前都会先执行该方法
*
*/
@Before
public void init () {
System.out.println("init....");
}
/**
* 释放资源的方法
* 在所有的测试方法执行完以后,都会自动执行改方法
*/
@After
public void close() {
System.out.println("close...");
}
/**
* 测试add方法
*/
@Test
public void testAdd(){
//System.out.println("我被执行了");
//1.创建计算器对象
System.out.println("testAdd....");
Calculator c = new Calculator();
//2.调用add方法
int result = c.add(1, 2);
// System.out.println(result);
//3.断言 我断言这个结果为3
Assert.assertEquals(3, result);
}
@Test
public void testSub() {
//1.创建计算器对象
Calculator c = new Calculator();
int result = c.sub(1, 2);
System.out.println("testSub....");
Assert.assertEquals(-1, result);
}
}
* 框架 : 半成品软件, 可以在框架的基础上进行软件开发,简化编码
* 反射: 将类的各个组成部分封装为其他对象,这就是反射机制
* 好处
1. 可以在程序的运行过程中,操作这些对象
2. 可以解耦, 提供程序的可扩展性
* 获取Class对象的方式
1. Class.forName("全类名" ):将字节码文件加载进入内存,返回Class对象
* 多用于配置文件,将类名定义在配置文件中,读取文件,加载类
2. 类名.class: 通过类名的属性class获取
* 多用于参数的传递
3. 对象.getClass(): getClass() 方法在Object类中定义着
* 多用于对象的获取字节码的方式
* 结论:
同一个字节码文件(*.class)在一次程序运行的过程中,只会被加载一次, 不论通过哪一种方式获取的Class对象都是同一个.
使用Class对象功能:
获取成员变量们
Field[] getFields() //获取所有public修饰的成员变量
Field getField(String name) 获取所有指定名字的public修饰的成员变量
Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符
Field getDeclaredField(String name)
获取构造方法们
获取成员方法们
Method[] getMethods()
Method getMethod(String name, 类>… parameterTypes)
Method[] getDeclaredMethods()
Method getDeclaredMethod(String name, 类>… parameterTypes)
获取类名
Field: 成员变量
package cn.itcast.reflect;
import cn.itcast.domain.Person;
import java.lang.reflect.Field;
public class ReflectDemo2 {
/**
* * 使用Class对象功能:
* * 获取功能
* 1. 获取成员变量们
* * Field[] getFields()
* * Field getField(String name)
*
* * Field[] getDeclaredFields()
* * Field getDeclaredField(String name)
*
* 2. 获取构造方法们
* * Constructor>[] getConstructors()
* * Constructor getConstructor(类>... parameterTypes)
*
* * Constructor>[] getDeclaredConstructors()
* * Constructor getDeclaredConstructor(类>... parameterTypes)
*
* 3. 获取成员方法们
* * Method[] getMethods()
* * Method getMethod(String name, 类>... parameterTypes)
*
* * Method[] getDeclaredMethods()
* * Method getDeclaredMethod(String name, 类>... parameterTypes)
*
* 4. 获取类名
* * String getName()
*/
public static void main(String[] args) throws Exception {
//0.获取Person的Class对象
Class personClass = Person.class;
/**
1. 获取成员变量们
* Field[] getFields()
* Field getField(String name)
* Field[] getDeclaredFields()
* Field getDeclaredField(String name)
*/
//1.Field[] getFields() 获取所有public修饰的成员变量
Field[] fields = personClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("----------------------");
//2. Field getField(String name)
Field a = personClass.getField("a");
//获取成员变量a的值
Person p = new Person();
Object value = a.get(p);
System.out.println(value);
//设置a的值
a.set(p, "张三");
System.out.println(p);
System.out.println("=======================");
//3. Field[] getDeclaredFields() : 获取所有的成员变量,不考虑修饰符
Field[] declaredFields = personClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
//4.Field getDeclaredField(String name)
Field d = personClass.getDeclaredField("d");
//访问私有的值,忽略访问权限修饰符的安全检查
d.setAccessible(true);//暴力反射
Object value2 = d.get(p);
System.out.println(value2);
}
}
package cn.itcast.reflect;
import cn.itcast.domain.Person;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class ReflectDemo3 {
/**
* * 使用Class对象功能:
* * 获取功能
* 1. 获取成员变量们
* * Field[] getFields()
* * Field getField(String name)
*
* * Field[] getDeclaredFields()
* * Field getDeclaredField(String name)
*
* 2. 获取构造方法们
* * Constructor>[] getConstructors()
* * Constructor getConstructor(类>... parameterTypes)
*
* * Constructor>[] getDeclaredConstructors()
* * Constructor getDeclaredConstructor(类>... parameterTypes)
*
* 3. 获取成员方法们
* * Method[] getMethods()
* * Method getMethod(String name, 类>... parameterTypes)
*
* * Method[] getDeclaredMethods()
* * Method getDeclaredMethod(String name, 类>... parameterTypes)
*
* 4. 获取类名
* * String getName()
*/
public static void main(String[] args) throws Exception {
//0.获取Person的Class对象
Class personClass = Person.class;
/**
2. 获取构造方法们
* Constructor>[] getConstructors()
* Constructor getConstructor(类>... parameterTypes)
* Constructor>[] getDeclaredConstructors()
* Constructor getDeclaredConstructor(类>... parameterTypes)
*/
//Constructor getConstructor(类>... parameterTypes)
Constructor constructor = personClass.getConstructor(String.class, int.class);
System.out.println(constructor);
//创建对象
Object person = constructor.newInstance("张三", 23);
System.out.println(person);
System.out.println("---------------");
Constructor constructor1 = personClass.getConstructor();
System.out.println(constructor);
//创建对象
Object person1 = constructor1.newInstance( );
System.out.println(person1);
System.out.println("=================");
Object o = personClass.newInstance();
System.out.println(o);
}
}
执行方法
获取方法名称
package cn.itcast.reflect;
import cn.itcast.domain.Person;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class ReflectDemo4 {
/**
* * 使用Class对象功能:
* * 获取功能
* 1. 获取成员变量们
* * Field[] getFields()
* * Field getField(String name)
*
* * Field[] getDeclaredFields()
* * Field getDeclaredField(String name)
*
* 2. 获取构造方法们
* * Constructor>[] getConstructors()
* * Constructor getConstructor(类>... parameterTypes)
*
* * Constructor>[] getDeclaredConstructors()
* * Constructor getDeclaredConstructor(类>... parameterTypes)
*
* 3. 获取成员方法们
* * Method[] getMethods()
* * Method getMethod(String name, 类>... parameterTypes)
*
* * Method[] getDeclaredMethods()
* * Method getDeclaredMethod(String name, 类>... parameterTypes)
*
* 4. 获取类名
* * String getName()
*/
public static void main(String[] args) throws Exception {
//0.获取Person的Class对象
Class personClass = Person.class;
/**
3. 获取成员方法们
* Method[] getMethods()
* Method getMethod(String name, 类>... parameterTypes)
* Method[] getDeclaredMethods()
* Method getDeclaredMethod(String name, 类>... parameterTypes)
*/
Method eat_method = personClass.getMethod("eat");
Person p = new Person();
//执行方法
eat_method.invoke(p);
Method eat_method2 = personClass.getMethod("eat", String.class);
//执行方法
eat_method2.invoke(p, "饭");
System.out.println("----------------");
//获取所有的public修饰的方法
Method[] methods = personClass.getMethods();
for (Method method : methods) {
System.out.println(method);
// method.setAccessible(true);
String name = method.getName();
System.out.println(name);
}
//获取类名
String classname = personClass.getName();
System.out.println(classname);//cn.itcast.domain.Person
}
}
package cn.itcast.reflect;
import cn.itcast.domain.Person;
import cn.itcast.domain.Student;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;
/**
* 框架类
*/
public class ReflectTest {
public static void main(String[] args) throws Exception {
//可以创建任意类的对象, 可以执行任意的方法
/*
前提: 不能改变该类的任何代码, 可以创建任意类的对象, 可以执行任意方法
*/
// Person p = new Person();
// p.eat();
// Student stu = new Student();
// stu.sleep();
//1.加载配置文件
//1.1创建Properties对象
Properties pro = new Properties();
//1.2加载配置文件,转换为一个集合(双列map)
//1.2.1获取class目录下的配置文件
ClassLoader classLoader = ReflectTest.class.getClassLoader();//获取这个类加载器
InputStream is = classLoader.getResourceAsStream("pro.properties");//用这个类加载器获取同包下的资源得到字节流
pro.load(is);
//2.获取配置文件中定义的数据
String className = pro.getProperty("className");
String methodName = pro.getProperty("methodName");
//3.加载该类进内存
Class cls = Class.forName(className);
//4.创建对象
Object obj = cls.newInstance();
//5.获取方法对象
Method method = cls.getMethod(methodName);
//6.执行方法
method.invoke(obj);
}
}
className=cn.itcast.domain.Student
methodName=sleep
概念:说明程序的,给计算机看的
注释: 用文字描述程序的,给程序员看的
定义:注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
概念描述
作用分类:
①编写文档:通过代码里标识的注解生成文档【生成文档doc文档】
② 代码分析:通过代码里标识的注解对代码进行分析【使用反射】
③编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【Override】
JDK中预定义的一些注解
自定义注解
格式
元注解
public @interface 注解名称 {
属性列表;
}
本质: 注解本质上就是一个接口, 该接口默认继承 Annotation接口
属性: 接口中的抽象方法
元注解:用于描述注解的注解
在程序中使用(解析)注解: 获取注解中定义的属性值
*getAnnotation(Class)
//其实就是在内存中生成了一个该注解接口的子类实现对象
public class ProImpl implements Pro{
public String className() {
return "cn.itcast.annotation.Demo1";
}
public String methodName() {
return "show";
}
}
* 3.调用注解中的抽象方法获取配置的属性值
package cn.itcast.annotation;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;
/**
* 框架类
*/
@Pro(className = "cn.itcast.annotation.Demo1", methodName = "show")
public class ReflectTest {
public static void main(String[] args) throws Exception {
//可以创建任意类的对象, 可以执行任意的方法
/*
前提: 不能改变该类的任何代码, 可以创建任意类的对象, 可以执行任意方法
*/
//1.解析注解
//1.1获取该类的字节码文件对象
Class<ReflectTest> reflectTestClass = ReflectTest.class;
//2.获取上边的注解对象
//其实就是在内存中生成了一个该注解接口的子类实现对象
/*
public class ProImpl implements Pro{
public String className() {
return "cn.itcast.annotation.Demo1";
}
public String methodName() {
return "show";
}
}
*/
Pro an = reflectTestClass.getAnnotation(Pro.class);
//3.调用注解对象中定义的抽象方法,获取返回值
String className = an.className();
String methodName = an.methodName();
System.out.println(className);
System.out.println(methodName);
//4.加载该类进内存
Class cls = Class.forName(className);
//5.创建对象
Object obj = cls.newInstance();
//6.获取方法对象
Method method = cls.getMethod(methodName);
//7.执行方法
method.invoke(obj);
}
}
package cn.itcast.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Check {
}
package cn.itcast.annotation;
/**
* 小明定义的计算器类
*/
public class Calculator {
//加法
@Check
public void add() {
String str = null;
str.toString();
System.out.println("1 + 0 =" + (1 + 0));
}
//减法
@Check
public void sub() {
System.out.println("1 - 0 =" + (1 - 0));
}
//乘法
@Check
public void mul() {
System.out.println("1 * 0 =" + (1 * 0));
}
//除法
@Check
public void div() {
System.out.println("1 / 0 =" + (1 / 0));
}
public void show() {
System.out.println("永无bug");
}
}
package cn.itcast.annotation;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 简单的测试框架
*
* 当主方法执行后,会自动自行被检测的所有方法(加了Check注解的方法),判断方法是否有异常,记录到文件中
*/
public class TestCheck {
public static void main(String[] args) throws IOException {
//1.创建计算器对象
Calculator c = new Calculator();
//2.获取字节码文件对象
Class cls = c.getClass();
//3.获取所有方法
Method[] methods = cls.getMethods();
int number = 0; //出现异常的次数
BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));
for (Method method : methods) {
//4.判断方法上是否有Check注解
if (method.isAnnotationPresent(Check.class)) {
//5.有,执行
try {
method.invoke(c);
} catch (Exception e) {
//6.捕获异常
//记录到文件中
number++;
bw.write(method.getName() + " 方法出异常了");
bw.newLine();
bw.write("异常的名称:" + e.getCause().getClass().getSimpleName());
bw.newLine();
bw.write("异常的原因:" + e.getCause().getMessage());
bw.newLine();
bw.write("---------------------");
bw.newLine();
}
}
}
bw.write("本次测试一共出现 " + number + " 次异常");
bw.flush();
bw.close();
}
}
1. 数据库的英文单词: DataBases 简称:DB
2. 什么是数据库
* 用于存储和管理数据的仓库
3.数据库特点
1. 持久化存储数据,数据库就是一个文件系统
2. 方便存储和管理数据
3. 使用了统一的方式操作数据库 -- SQL
4.常见的数据库软件
* 参见<>
1.安装
2.卸载
1.去MySQL的安装目录找到my.ini
* 复制 datadir=D:\Environment\mysql-5.7.19\data\
2.卸载MySQL
3.删除 datadir=D:\Environment\mysql-5.7.19\data\下的MySQL文件夹
3.配置
* MySQL服务启动
1. 计算机管理 ->服务和应用程序->服务
2. cmd -> services.msc 打开服务的窗口
3. 使用管理员打开cmd
* net stop mysql : 关闭mysql服务
* net start mysql :启动mysql服务
* MySQL登录
1. mysql -uroot -p密码
2. mysql -h127.0.0.1 -uroot -p连接目标的密码
-h后连ip127.0.0.1
密码为123456
3.mysql --host=ip --user=root --password=连接目标的密码
* MySQL退出
1. exit
2. quit
* MySQL的目录结构
1.MySQL安装目录
* 配置文件 my.ini
2.MySQL数据目录
* 几个概念
* 数据库: 文件夹
* 表: 文件
* 数据 : 文件里的数据
1. 什么是SQL?
Structured Query Language : 结构化查询语言
其实就是定义了操作所有关系型数据库的规则.每一种数据库操作的方式存在不一样的地方,称为"方言"
2. SQL通用语法
1.SQL语句可以单行或者多行书写,以分号结尾
2.可以使用空格或者缩进来增强语句的可读性
3. MySQL的数据库的 SQL语句不区分大小写,关键字建议使用大写
4. 3种注释
* 单行注释: -- 注释内容 或者 # 注释内容(MySQL特有)
* 多行注释: /* 注释 */
3.SQL分类
1.DDL 数据库定义语言
用来定义数据库对象: 数据库,表, 列等.关键字:create,drop,alter等
2.DML 数据库操作语言
用来对数据库中表的数据进行增删改.关键字: insert,delete,update等
3.DQL 数据库查询语言
用来查询数据库中表的记录(数据),关键字: select,where等
4.DCL 数据库控制语言
用来定义数据库的访问权限和安全级别,及创建用户,关键字:GRANT,REVOKE等
1. 操作数据库: CRUD
1. C(Create): 创建
* 创建数据库
* create database 数据库名称;
* 创建数据库,判断不存在
* create database if not exists 数据库名称;
* 创建数据库,并去指定字符集
* create database 数据库名称 character set 字符集名称;
* 练习: 创建db4数据库,判断是否存在,并知道字符集为gbk
* create database if not exists db4 character set gbk;
2. R(Retrieve): 查询
* 查询所有数据库的名称:
* show databases;
* 查询某个数据库的字符集: 查询某个数据库的创建语句
* show create database 数据库名称;
3. U(Update):修改
* 修改数据库的字符集
* alter database 数据库名称 character set 字符集名称;
4. D(Delete): 删除
* 删除数据库
* drop database 数据库名称;
* 判断数据库存在,存在再删除
* drop database if exists 数据库名称;
5. 使用数据库
* 查询当前正在使用的数据库名称
* select database();
* 使用数据库
* use 数据库名称;
2. 操作表
1. C(Create): 创建
1. 语法:
create table 表名(
列名1 数据类型1,
列名2 数据类型2,
...
列名n 数据类型n
);
* 注意:最后一列, 不需要加逗号(,)
* 数据库类型 :
1. int : 整数类型
* age int,
2. double: 小数类型
* score double(5,2)
3. date: 日期,只包含年月日, yyyy - MM -dd
4. datatime: 日期,包含年月日时分秒 yyyy - MM -dd HH:mm:ss
5. timestamp: 时间戳类型 包含年月日时分秒 yyyy - MM -dd HH:mm:ss
* 如果将来不给\这个字段赋值,或者赋值为null, 则默认使用当前的系统时间,来自动赋值
6. varchar : 字符串
* name varchar(20) : 姓名最大20个字符
* zhangsan 8 个字符 张三 2个字符
*
* 创建表
create table student(
id int,
name varchar(32),
age int,
score double(4,1),
birthday date,
insert_time timestamp
);
* 复制表
* create table 表名 like 被赋值的表名;
2. R(Retrieve): 查询
* 查询某个数据库中的所有表的名称
* show tables;
* 查询表结构
* desc 表名;
3. U(Update):修改
1. 修改表名
alter table 表名 rename to 新的表名;
2. 修改表的字符集
alter table 表名 character set 字符集名称 ;
3. 添加一列
alter table 表名 add 列名 数据类型;
4. 修改列名称 类型
alter table 表名 change 列名 新列名 新数据类型;
alter table 表名 modify 列名 新数据类型;
5. 删除列
alter table 表名 drop 列名;
4. D(Delete): 删除
* drop table 表名;
* drop table if exists 表名;
1. 添加数据
* 语法 :
* insert into 表名(列名1, 列名2, ..., 列n) values (值1, 值2, ..., 值n);
* 注意:
* 1. 列名和值要一一对应
* 2. 如果表名后, 不定义列名, 则默认给所有列添加值
* insert into 表名 values (值1, 值2, ..., 值n);
* 3. 除了数字类型,其他类型 需要使用引号(单双都可以)引起来
2. 删除数据
* 语法
* delete from 表名 [where 条件]
* 注意:
1. 如果不加条件, 则删除表中的所有记录
2. 如果要删除所有记录
1. delete from 表名; -- 不推荐使用, 有多少条记录就会执行多少次删除操作
2. TRUNCATE TABLE 表名; -- 推荐使用,效率更高,删除表,然后再创建一张一模一样的新表
3. 修改数据
* 语法:
* update 表名 set 列名1 = 值1, 列名2 = 值2,...[where 条件];
* 注意
1. 如果不加任何条件, 则会将表中的所有记录全部修改
* select * from 表名;
语法:
select
字段列表
from
表名列表
where
条件列表
group by
分组字段
having
分组之后的条件
order by
排序
limit
分页限定
基础查询
条件查询
, <, <=, >=, =, <>
CREATE TABLE student (
id INT, -- 编号
NAME VARCHAR(20), -- 姓名
age INT, -- 年龄
sex VARCHAR(5), -- 性别
address VARCHAR(100), -- 地址
math INT, -- 数学
english INT -- 英语
);
INSERT INTO student(id, NAME, age, sex, address, math, english) VALUES
(1, '马云', 55, '男', '杭州', 66, 78),
(2, '马化腾', 45, '女', '深圳', 98, 87),
(3, '马景涛', 55, '男', '香港', 56, 77),
(4, '柳岩', 20, '女', '湖南', 76, 65),
(5, '柳青', 20, '男', '湖南', 86, NULL),
(6, '刘德华', 57, '男', '香港', 99, 99),
(7, '马德', 22, '女', '香港', 99, 99),
(8, '德玛西亚', 18, '男', '南京', 56, 65);```
```sql
SELECT * FROM student;
-- 查询 姓名 和 年龄
SELECT
NAME, -- 姓名
age -- 年龄
FROM student; -- 学生表
SELECT * FROM student;
SELECT address FROM student;
-- 去除重复的结果集
SELECT DISTINCT address FROM student;
SELECT DISTINCT NAME, address FROM student;
-- 计算 math 和 english 的分数之和
SELECT NAME, math, english, math + english FROM student;
-- 如果 有null 参与的运算, 计算结果都为null
SELECT NAME, math, english, math + IFNULL(english, 0) FROM student;
-- 起别名
SELECT NAME, math, english, math + IFNULL(english, 0) AS 总分 FROM student;
SELECT NAME, math 数学, english 英语, math + IFNULL(english, 0) 总分 FROM student;
SELECT * FROM student;
-- 查询年龄大于20岁
SELECT * FROM student WHERE age > 20;
-- 查询年龄大于等于20岁
SELECT * FROM student WHERE age >= 20;
-- 查询年龄等于20岁
SELECT * FROM student WHERE age = 20;
-- 查询年龄不等于20岁
SELECT * FROM student WHERE age != 20;
SELECT * FROM student WHERE age <> 20;
-- 查询年龄大于等于20岁 小于等于30岁
SELECT * FROM student WHERE age >= 20 && age <= 30;
SELECT * FROM student WHERE age >= 20 AND age <= 30;
SELECT * FROM student WHERE age BETWEEN 20 AND 30;
-- 查询年龄22岁, 18岁, 25岁的信息
SELECT * FROM student WHERE age = 22 OR age = 18 OR age = 25;
SELECT * FROM student WHERE age IN (22, 18, 25);
-- 查询英语成绩为null
SELECT * FROM student WHERE english = NULL; -- 不对的, null值不能用 = (!=) 判断
SELECT * FROM student WHERE english IS NULL;
-- 查询英语成绩为null
SELECT * FROM student WHERE english IS NOT NULL;
-- 查询姓马的有哪些? like
SELECT * FROM student WHERE NAME LIKE '马%';
-- 查询姓名第二个字是化的人
SELECT * FROM student WHERE NAME LIKE "_化%";
-- 查询姓名是三个字的人
SELECT * FROM student WHERE NAME LIKE "___";
-- 查询姓名中包含德的人
SELECT * FROM student WHERE NAME LIKE "%德%";
1. 排序查询
* 语法: order by 子句
* order by 排序字段1 排序方式1, 排序字段2 排序方式2 ...
* 排序方式
* ASC: 升序,默认的.
* DESC: 降序
* 注意:
* 如果有多个排序条件,则当前边的条件值一样时,才会判断第二条件
2. 聚合函数: 将一列数据作为一个整体, 进行纵向的计算
1. count : 计算个数
1. 一般选择非空的列: 主键
2. count(*)
2. max: 计算最大值
3. min: 计算最小值
4. sum: 计算和
5. avg: 计算平均值
* 注意: 聚合函数的计算, 排除了null值
*解决方案 :
1. 选择了不包含非空的列进行计算
2. IFNULL函数
3. 分组查询
1. 语法: group by 分组字段;
2. 注意:
1. 分组之后 查询的字段: 分组字段, 聚合函数
2. where 和 having的区别
1. where 在分组之前进行限定, 如果不满足条件, 则不参与分组. having在分组之后限定,如果不满足结果,则不会被查询出来
2. where 后不可跟聚合函数, having可以进行聚合函数的判断
4. 分页查询
1. 语法: limit 开始的索引, 每页查询的条数;
2. 公式:开始的索引 = (当前的页码 - 1) * 每页显示的条数
-- 每页显示3条记录
SELECT *FROM student LIMIT 0,3; -- 第一页
SELECT *FROM student LIMIT 3,3; -- 第二页
SELECT *FROM student LIMIT 6,3; -- 第三页
3. limit 是一个MySQL"方言"
SELECT * FROM student ORDER BY math ASC; -- 默认排序方式是升序
SELECT * FROM student ORDER BY math DESC; -- 默认排序方式是升序
-- 按照属性成绩排名, 如果数学成绩一样, 则按照英语成绩排名
SELECT * FROM student ORDER BY math ASC, english DESC;
SELECT COUNT(NAME) FROM student;
SELECT COUNT(IFNULL(english, 0)) FROM student;
SELECT MAX(math) FROM student;
SELECT MIN(math) FROM student;
SELECT SUM(math) FROM student;
SELECT AVG(math) FROM student;
SELECT * FROM student;
-- 按照性别分组, 分别查询男, 女同学的平均分
SELECT sex, AVG(math) FROM student GROUP BY sex;
-- 按照性别分组, 分别查询男, 女同学的平均分, 人数
SELECT sex, AVG(math), COUNT(id) FROM student GROUP BY sex;
-- 按照性别分组, 分别查询男, 女同学的平均分, 人数, 分数低于70分的不参与分组
SELECT sex, AVG(math), COUNT(id) FROM student WHERE math > 70 GROUP BY sex ;
-- 按照性别分组, 分别查询男, 女同学的平均分, 人数, 分数低于70分的不参与分组, 分组之后, 人数要大于2
SELECT sex, AVG(math), COUNT(id) FROM student WHERE math > 70 GROUP BY sex HAVING COUNT(id) > 2;
SELECT sex, AVG(math), COUNT(id) 人数 FROM student WHERE math > 70 GROUP BY sex HAVING 人数 > 2;
-- 每页显示3条记录
SELECT *FROM student LIMIT 0,3; -- 第一页
SELECT *FROM student LIMIT 3,3; -- 第二页
SELECT *FROM student LIMIT 6,3; -- 第三页
-- 公式:开始的索引 = (当前的页码 - 1) * 每页显示的条数
* 概念: 对表中数据进行限定, 保证数据的正确性, 有效性和完整性.
* 分类:
1. 主键约束 : primary key
2. 非空约束 : not null
3. 唯一约束 : unique
4. 外键约束 : foreign key
CREATE TABLE stu(
id INT,
NAME VARCHAR(20) NOT NULL -- name为非空
);
ALTER TABLE stu MODIFY NAME VARCHAR(20) NOT NULL;
ALTER TABLE stu MODIFY NAME VARCHAR(20);
-- 创建表添加非空约束
CREATE TABLE stu(
id INT,
NAME VARCHAR(20) NOT NULL -- name为非空
);
SELECT *FROM stu;
-- 删除name 的非空约束
ALTER TABLE stu MODIFY NAME VARCHAR(20);
-- 创建表完后, 添加非空约束
ALTER TABLE stu MODIFY NAME VARCHAR(20) NOT NULL;
INSERT INTO stu(id, NAME) VALUES(1, "张三丰");
INSERT INTO stu(id, NAME) VALUES(2,NULL), (3,"ss");
CREATE TABLE stu(
id INT,
phone_number VARCHAR(20) UNIQUE -- 手机号
);
3. 删除唯一约束
ALTER TABLE stu DROP INDEX phone_number;
ALTER TABLE stu MODIFY phone_number VARCHAR(20) UNIQUE;
DROP TABLE stu;
-- 在创建表时候添加
CREATE TABLE stu(
id INT,
phone_number VARCHAR(20) UNIQUE -- 手机号
);
SELECT * FROM stu;
INSERT INTO stu(id, phone_number) VALUES(1, "13812345678");
INSERT INTO stu(id, phone_number) VALUES(2, "13812345679");
-- 在表创建完后, 添加唯一约束
ALTER TABLE stu MODIFY phone_number VARCHAR(20) UNIQUE;
-- 删除唯一约束
ALTER TABLE stu DROP INDEX phone_number;
create table stu(
id int primary key, -- 给id添加主键约束
name varchar(20)
);
-- 错误 alter table stu modify id int;
ALTER TABLE stu DROP PRIMARY KEY;
ALTER TABLE stu MODIFY id INT PRIMARY KEY;
create table stu(
id int primary key auto_increment, -- 给id添加主键约束
name varchar(20)
);
ALTER TABLE stu MODIFY id INT;
ALTER TABLE stu MODIFY id INT AUTO_INCREMENT;
create table 表名(
...
外键列
constraint 外键名称 foreign key (外键列名称) references 主表名称(主表列名称)
);
2. 删除外键
ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;
3. 创建表之后,添加外键
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称)
级联操作
语法 : ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称) ON UPDATE CASCADE ON DELETE CASCADE;
分类 :
分类
1. 一对一 (了解):
* 如 : 人和身份证
* 分析 : 一个人只有一个身份证, 一个身份证只能对应一个人
2. 一对多(多对一) :
* 如: 部门和员工
* 分析: 一个部门有多个员工, 一个员工只能对应一个部门
3. 多对多:
* 如: 学生和课程
* 分析: 一个学生可以选择很多门课程, 一个课程也可以被很多学生选择
实现关系 :
多对多:
一对一(了解)
– 把中间表的两个字段合起来作为联合主键
概念 : 设计数据库时,需要遵循的一些规范, 要遵循后边的范式要求, 必须先遵循前边的所有范式要求
设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。
关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。
分类 :
1. 第一范式(1NF): 每一列都是不可分割的原子数据项
2. 第二范式(2NF): 在1NF的基础上,非码属性必须完全依赖于候选码(在1NF基础上消除非主属性对主码的部分函数依赖)
* 几个概念:
1. 函数依赖 : A---> B,如果通过A属性(属性组)的值. 可以确定唯一B属性的值,则称B依赖于A
例如: 学号 ---> 姓名 (学号, 课程名称) ---> 分数
2. 完全函数依赖 :A--->B, 如果 A 是一个属性组, 则 B 属性值得确定需要依赖于A属性组中所有的属性值
例如:(学号, 课程名称) --->分数
3. 部分函数依赖:A--->B, 如果 A 是一个属性组, 则 B 属性值得确定只需要依赖于A属性组中某一些值即可
例如:(学号, 课程名称) --->姓名
4. 传递函数依赖 : A ---> B, B --->C ,如果通过A属性(属性组)的值,可以确定唯一B属性的值,在通过B属性(属性组)的值可以确定唯一C属性的值,则称C传递函数依赖A
例如; 学号 --->系名, 系名 --- >系主任
5. 码: 如果在一张表中,一个属性或者属性组, 被其他所有属性所完全依赖,则称这个属性(属性值)为该表的码
例如: 该表中码为:(学号,课程名称)
* 主属性:码属性组中的所有属性
* 非主属性:除过码属性组的属性
3. 第三范式(3NF): 在2NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖)![在这里插入图片描述](https://img-blog.csdnimg.cn/318df73ba31d4caa88f90bcf029e293b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5YGa5Liq56yo576K,size_20,color_FFFFFF,t_70,g_se,x_16)
命令行:
图形化工具:
* 查询语法 :
select
列名列表
from
表名列表
where......
* 准备sql
# 创建部门表
ALTER TABLE dept CHARACTER SET utf8;
CREATE TABLE dept(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20)
);
SELECT * FROM dept;
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,
FOREIGN KEY (dept_id) REFERENCES dept(id) -- 外键, 关联部门表(部门表的主键)
);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('孙悟空','男',7200,'2013-02-24',1);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('猪八戒','男',3600,'2010-12-02',2);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('唐僧','男',9000,'2008-08-08',2);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('白骨精','女',5000,'2015-10-07',3);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('蜘蛛精','女',4500,'2011-03-14',1);
笛卡尔积
多表查询的分类
内连接查询
SELECT
t1.name, -- 员工表的姓名
t1.`gender`, -- 员工表的性别
t2.`name` -- 部门表的姓名
FROM
emp t1,
dept t2
WHERE
t1.`dept_id` = t2.`id`
SELECT * FROM emp INNER JOIN dept ON emp.`dept_id` = dept.`id`;
SELECT * FROM emp JOIN dept ON emp.`dept_id` = dept.`id`;
外连接查询
左外连接
右外连接
SELECT t1.*, t2.`name` FROM emp t1 LEFT JOIN dept t2 ON t1.`dept_id` = t2.`id`;
SELECT t1.*, t2.`name` FROM emp t1 RIGHT JOIN dept t2 ON t1.`dept_id` = t2.`id`;
SELECT t1.*, t2.`name` FROM dept t2 RIGHT JOIN emp t1 ON t1.`dept_id` = t2.`id`;
子查询:
-- 查询工资最高的员工信息
-- 1. 查询最高的工资是多少 9000
SELECT MAX(salary) FROM emp;
-- 2. 查询员工信息, 并且工资等于9000的
SELECT * FROM emp WHERE emp.`salary` = 9000;
-- 一条SQL就完这个操作. 子查询
SELECT * FROM emp WHERE emp.`salary` = (SELECT MAX(salary) FROM emp);
-- 查询员工工资小于平均工资的人
SELECT * FROM emp WHERE emp.`salary` < (SELECT AVG(salary) FROM emp);
SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部';
SELECT * FROM emp WHERE dept_id = 3 OR dept_id = 2;
SELECT * FROM emp WHERE dept_id IN (3,2);
-- 子查询
SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部');
子查询可以作为一张虚拟表
– 查询员工的入职日期2011-11-11日之后的员工信息和部门信息
-- 查询员工的入职日期2011-11-11日之后的员工信息和部门信息
-- 子查询
SELECT * FROM emp WHERE emp.`join_date` > '2011-11-11';
SELECT * FROM dept t1, (SELECT * FROM emp WHERE emp.`join_date` > '2011-11-11') t2
WHERE t1.`id` = t2.dept_id;
-- 普通内连接
SELECT * FROM emp t1, dept t2 WHERE t1.`dept_id` = t2.`id` AND t1.`join_date` > '2011-11-11';
#多表查询练习
#创建练习用表
-- 部门表
CREATE TABLE dept(
id INT PRIMARY KEY, -- 部门ID
dname VARCHAR(50), -- 部门名称
loc VARCHAR(50) -- 部门地址
);
-- 添加4个部门
INSERT INTO dept VALUES
( 10, '研发部', '北京' ),
( 20, '学工部', '上海' ),
( 30, '销售部', '广州' ),
( 40, '财务部', '深圳' );
-- 职务表,职务名称,植物描述
CREATE TABLE job(
id INT PRIMARY KEY, -- 职务ID
jname VARCHAR(20), -- 职务名称
descripition VARCHAR(50) -- 职责
);
-- 添加4个职务
INSERT INTO job VALUES
(1,'董事长','管理整个公司,接单'),
(2,'经理','管理部门员工'),
(3,'销售员','向客人推销产品'),
(4,'文员','使用办公软件');
-- 工资等级表
CREATE TABLE salarygrade(
grade INT PRIMARY KEY, -- 级别
losalary INT, -- 最低工资
hisalary INT -- 最高工资
);
-- 添加工资信息
INSERT INTO salarygrade VALUES
(1,7000,12000),
(2,12000,14000),
(3,14000,20010),
(4,20010,30010),
(5,30010,99990);
-- 员工表
CREATE TABLE emp(
id INT PRIMARY KEY, -- 员工ID
ename VARCHAR(50), -- 员工姓名
job_id INT, -- 职务id
mgr INT, -- 上级领导
joindate DATE, -- 入职日期
salary DECIMAL(7,2), -- 工资
bonus DECIMAL(7,2), -- 奖金
dept_id INT, -- 所在部门编号
FOREIGN KEY(job_id) REFERENCES job(id), -- 职务ID外连接
FOREIGN KEY(dept_id) REFERENCES dept(id) -- 部门ID外连接
);
-- 添加员工信息
INSERT INTO emp VALUES
(1001,'孙悟空',4,1004,'2000-12-17',8000.00,NULL,20),
(1002,'卢俊义',3,1006,'2001-02-20',16000.00,3000.00,30),
(100,'林冲',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,'2007-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,'2007-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);
-- 需求:
-- 1. 查询所有员工信息, 查询员工编号,员工姓名, 工资, 职务名称, 职务描述
/*
分析 :
1.查询员工编号,员工姓名, 需要查询emp表, 工资, 职务名称, 职务描述 需要查询job表
2.查询的条件 emp.jobid = job.id
*/
SELECT
t1.`id`, -- 员工编号
t1.`ename`, -- 员工姓名
t1.`salary`, -- 工资
t2.`jname`, -- 职务名称
t2.`descripition` -- 职务描述
FROM
emp t1,
job t2
WHERE
t1.`job_id` = t2.`id`;
-- 2. 查询员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置
/*
分析 :
1.查询员工编号,员工姓名, 需要查询emp表, 工资, 职务名称, 职务描述 需要查询job表 部门名称,部门位置 需要查询dept表
2.查询的条件 emp.job_id = job.id and emp.dept_id = dept.id
*/
SELECT
t1.`id`, -- 员工编号
t1.`ename`, -- 员工姓名
t1.`salary`, -- 工资
t2.`jname`, -- 职务名称
t2.`descripition`, -- 职务描述
t3.`dname`,
t3.`loc`
FROM
emp t1,
job t2,
dept t3
WHERE
t1.`job_id` = t2.`id`
AND t1.`dept_id` = t3.`id`;
-- 3.查询员工姓名,工资,工资等级
/*
分析:
1. 员工姓名, 工资 emp 工资等级 salarygrade
2. 条件 emp.salary >= salarygrade.losalary and emp.salary <= salarygrade.hisalary
emp.salary BETWEEN salarygrade.losalary and salarygrade.hisalary
*/
SELECT
t1.`ename`,
t1.`salary`,
t2.`grade`
FROM
emp t1,
salarygrade t2
WHERE
t1.`salary` BETWEEN t2.`losalary` AND t2.`hisalary`;
-- 4.查询员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级
/*
分析:
1. 员工姓名, 工资 emp, 职务名称, 职务描述 job, 部门名称,部门位置, dept, 工资等级 salarygrade
2. 条件: 查询的条件 emp.job_id = job.id and emp.dept_id = dept.id and emp.salary BETWEEN salarygrade.losalary and salarygrade.hisalary
*/
SELECT
t1.`ename`,
t1.`salary`,
t2.`jname`,
t2.`descripition`,
t3.`dname`,
t3.`loc`,
t4.`grade`
FROM
emp t1, job t2, dept t3, salarygrade t4
WHERE
t1.`job_id` = t2.`id`
AND t1.`dept_id` = t3.`id`
AND t1.`salary` BETWEEN t4.`losalary` AND t4.`hisalary`;
-- 5.查询出部门编号,部门名称,部门位置,部门人数
/*
分析:
1.部门编号,部门名称,部门位置 dept表, 部门人数 emp表
2.分组查询,按照 emp.dept_id 完成分组,查询count(id)
3.使用子查询将第二部的查询结果和dept表进行关联查询
*/
SELECT
t1.`id`, t1.`dname`, t1.`loc`, t2.total
FROM
dept t1,
(SELECT
dept_id, COUNT(id) total
FROM
emp
GROUP BY dept_id) t2
WHERE t1.`id` = t2.`dept_id`;
-- 6. 查询处所有员工的姓名及其直接上级的姓名,没有领导的员工也需要查询
/*
分析:
1.查询所有员工的姓名 emp,直接上级的姓名 emp
*emp表的id 和 mgr 是自关联的
2. 条件 emp.id = emp.mgr
3. 查询左表的所有数据, 和交集数据
*使用左外连接查询
*/
/*
select
t1.`ename`,
t1.`mgr`,
t2.`id`,
t2.`ename`
from emp t1, emp t2
where t1.`mgr` = t2.`id`;
*/
SELECT
t1.`ename`,
t1.`mgr`,
t2.`id`,
t2.`ename`
FROM
emp t1
LEFT JOIN
emp t2
ON
t1.`mgr` = t2.`id`;
事务的基本特征
概念:
操作:
事务的四大特征
事务的隔离级别(了解)
概念: 多个事务之间隔离的, 相互独立的, 但是如果多个事务操作同一批数据,则会引发一些问题, 设置不同的隔离级别就可以解决这些问题
存在问题:
1. 脏读: 一个事务, 读取到另一个事务中没有提交的数据
2. 不可重复读(虚读): 在同一个事务中,两次读取到的数据不一样
3. 幻读: 一个事务操作(DML)数据表中所有记录, 另一个事务添加了一条数据, 则第一个事务查询不到自己的修改.
(事务在插入已经检查过不存在的记录时,惊奇的发现这些数据已经存在了,之前的检测获取到的数据如同鬼影一般。)
隔离级别 :
1. read uncommitted : 读未提交
* 产生的问题 : 脏读,不可重复读,幻读
2. read committed : 读已提交 (Oracle默认)
* 产生的问题 : 不可重复读,幻读
3. repeatable read : 可重复读 (MySQL默认)
* 产生的问题 : 幻读
4. serializable : 串行化 (把表加锁, 同时只能一个去访问操作)
* 可以解决所有的问题
* 注意 :隔离级别从小到大安全性越来越高,但是效率越来越低
* 数据库查询隔离级别 :
* select @@tx_isolation;
* 数据库设置隔离级别 :
* set global transaction isolation level 级别字符串;
SQL 分类:
1. DDL : 操作数据库和表
2. DML : 增删改表中的数据
3. DQL : 查询表中的数据
4. DCL : 管理用户,授权
DBA : 数据库管理员
DCL : 管理用户,授权
管理用户
添加用户 :
删除用户
修改用户密码
SET PASSWORD FOR ‘用户名’@‘主机名’ = PASSWORD(‘新密码’);
SET PASSWORD FOR ‘lisi’@‘localhost’ = PASSWORD(‘123’);
查询用户
– 1.切换到mysql 数据库
USE mysql;
– 2. 查询user表
SHOW TABLES;
DESC USER;
SELECT * FROM USER;
* 通配符 : % 表示可以在任意主机使用用户登录数据库
权限管理:
查询权限:
– 查询权限
SHOW GRANTS FOR ‘用户名’@‘主机名’;
SHOW GRANTS FOR ‘lisi’@‘localhost’;
SHOW GRANTS FOR 'root'@'localhost';
SHOW GRANTS FOR 'root'@'%';
授予权限:
– 授予权限
grant 权限列表 on 数据库.表名 to ‘用户名’@‘主机名’;
– 给root用户授予所有权限,在任意数据库任意表上
GRANT ALL ON . TO ‘root’@’%’;
收回权限:
– 撤销权限:
REVOKE 权限列表 ON 数据库.表名 FROM ‘用户名’@‘主机名’;
REVOKE SELECT,DELETE,UPDATE ON db3.account FROM ‘lisi’@‘localhost’;
package cn.itcast.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
/**
* JDBC快速入门
*/
public class JdbcDemo1 {
public static void main(String[] args) throws Exception {
//1.导入驱动jar包
//2.注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 将字节码文件加载进入内存,返回Class对象,
// 多用于配置文件,将类名定义在配置文件中,读取文件,加载类
//3.获取数据库的连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3?useSSL=false", "root", "123456");
//4.定义sql语句
String sql = "update account set balance = 500 where id = 1";
//5.获取执行sql的对象 Statement
Statement stmt = conn.createStatement();
//6.执行方法
int count = stmt.executeUpdate(sql);
//7.处理结果
System.out.println(count);
//8.释放资源
stmt.close();
conn.close();
}
}
DriverManager : 驱动管理对象
Connection : 数据库连接的对象
1. 功能 :
1. 获取执行的对象
* Statement createStatement()
* PreparedStatement prepareStatement(String sql)
2. 管理事务:
* 开启事务 : void setAutoCommit(boolean autoCommit) : 调用改方法设置参数为false, 即开启事务
* 提交事务 : void commit()
* 回滚事务 : void rollback()
Statement : 执行sql的对象
1. 执行sql
1. boolean execute(String sql) : 可以执行任意的sql 了解
2. int executeUpdate(String sql) : 执行DML(insert, update, delete)语句, DDL(create, alter, drop)语句
* 返回值 : 影响的行数 , 可以通过这个影响的行数判断DML语句是否执行成功 返回值>0的则执行成功, 反之, 则失败
3. ResultSet executeQuery(String sql) :执行DQL(select)语句
2. 练习
1. account表 添加一条记录
2. account表 修改记录
3. account表 删除一条记录
ResultSet : 结果集对象, 封装查询结果
boolean next() : 游标向下移动一行, 判断当前行是否最后一行末尾(是否有数据), 如果是, 则返回false, 如果不是则返true
getXxx(参数) : 获取数据
注意 :
* 使用步骤
1. 游标向下移动一行
2. 判断是否有数据
3. 获取数据
```java
//6.处理结果
//6.1 让光标向下移动一行
//循环判断游标是否是最后一行末尾
while (rs.next()) {
//6.2 获取数据
int id = rs.getInt(1);
String name = rs.getString("name");
double balance = rs.getDouble(3);
System.out.println(id + "---" + name + "---" + balance);
}
```
* 练习 :
* 定义一个方法, 查询emp表的数据, 将其封装为 对象,然后装载集合, 返回.
1. 定义Emp类
2. 定义方法 Public List findAll() {}
3. 实现方法 select * from emp;
PreparedStatement :执行sql的对象
SQL注入问题 : 在拼接sql时, 有一些sql的特殊关键字参与字符串的拼接, 会造成安全性问题
解决sql注入问题 :使用 PreparedStatement 对象解决SQL注入问题
预编译的SQL :参数使用?作为占位符
步骤 :
1. 导入驱动jar包 mysql-connector-java-5.1.47-bin.jar
1. 复制 mysql-connector-java-5.1.47-bin.jar 到项目的libs目录下
2. 右键 —> Add As Library
2. 注册驱动
3. 获取数据库连接对象 Connection
4. 定义sql
* 注意 :SQL的参数使用?作为占位符 , 如: select * from user where username = ?’ and password = ?
*
5. 获取执行sql语句的对象 PreparedStatement Connection.PreparedStatement(String sql)
6. 给?赋值:
* 方法 : setXxx(参数1, 参数2)
* 参数1 : ? 的位置编号 从1开始
* 参数2 : ? 的值
7. 执行sql , 接受返回结果 ,不需要传递sql语句
8. 处理结果
9. 释放资源
注意 : 后期都会使用PreparedStatement 来 完成增删改查的所有操作
package cn.itcast.jdbc;
import cn.itcast.util.JDBCUtils;
import java.sql.*;
import java.util.Scanner;
/**
* * 练习
* * 需求 :
* 1. 通过键盘录入用户名和密码
* 2. 判断用户是否登录成功
*/
public class JDBCDemo9 {
public static void main(String[] args) {
//1.键盘录入,接受用户名和密码
Scanner in = new Scanner(System.in);
System.out.println("请输入用户名: ");
String username = in.nextLine();
System.out.println("请输入密码: ");
String password = in.nextLine();
//2.调用方法
boolean flag = new JDBCDemo9().login2(username, password);
//3.判断结果, 输出不同语句
if (flag) {
//登录成功
System.out.println("登录成功!");
} else {
//登录失败
System.out.println("用户名或密码错误!");
}
}
/**
* 登录方法一, 使用Statement实现
* @param username
* @param password
* @return
*/
public boolean login(String username, String password) {
if (username == null || password == null) {
return false;
}
// 连接数据库判断是否登录成功
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
//1.获取连接
conn = JDBCUtils.getConnection();
//2.定义sql
String sql = "select * from user where username = '" + username + "' and password = '"+ password + "' ";
System.out.println(sql);
//3.获取执行sql的对象
stmt = conn.createStatement();
//4.执行查询
rs = stmt.executeQuery(sql);
//5.判断
/*if (rs.next()) { // 如果有下一行,则返回true
return true;
} else {
return false;
}*/
return rs.next();// 如果有下一行,则返回true
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(rs, stmt, conn);
}
return false;
}
/**
* 登录方法二,使用PreparedStatement 实现
* @param username
* @param password
* @return
*/
public boolean login2(String username, String password) {
if (username == null || password == null) {
return false;
}
// 连接数据库判断是否登录成功
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
//1.获取连接
conn = JDBCUtils.getConnection();
//2.定义sql
String sql = "select * from user where username = ? and password = ?";
//3.获取执行sql的对象
pstmt = conn.prepareStatement(sql);
//给? 赋值
pstmt.setString(1, username);
pstmt.setString(2, password);
//4.执行查询,不需要传递sql
rs = pstmt.executeQuery();
//5.判断
/*if (rs.next()) { // 如果有下一行,则返回true
return true;
} else {
return false;
}*/
return rs.next();// 如果有下一行,则返回true
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(rs, pstmt, conn);
}
return false;
}
}
* 目的 : 简化书写
* 分析 :
1. 注册驱动也抽取
2. 抽取一个方法获取连接对象
* 需求:不想传递参数(麻烦), 还得保证工具类的通用性
* 解决:配置文件
jdbc.properties
url =
user =
password =
3. 抽取一个方法释放资源
package cn.itcast.util;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;
/**
* JDBC 工具类
*/
public class JDBCUtils {
private static String url;
private static String user;
private static String password;
private static String driver;
/**
* 文件的读取, 只需要读取一次即可拿到这些值, 使用静态代码块来完成
*/
static {
try {
//读取资源文件, 获取值.
//1. 创建Properties集合类
Properties pro = new Properties();
//获取src路径下的文件的方式 ---> ClassLoader 类加载器
//类加载器可以把字节码文件加载进内存
//而且可以获取src路径下的资源路径
ClassLoader classLoader = JDBCUtils.class.getClassLoader();
URL res = classLoader.getResource("jdbc.properties");
//统一资源定位符
String path = res.getPath();
//获取字符串路径
System.out.println(path);
// /E:/Java_Project/itcast/out/production/day04_jdbc/jdbc.properties
//2.加载文件
//pro.load(new FileReader("E:\\Java_Project\\itcast\\day04_jdbc\\src\\jdbc.properties"));
pro.load(new FileReader(path));
//3.获取数据, 赋值
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
//4.注册驱动
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取连接
* @return 连接对象
*/
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, user, password);
}
/**
* 释放资源
* @param stmt
* @param conn
*/
public static void close(Statement stmt, Connection conn) {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 释放资源重载
* @param rs
* @param stmt
* @param conn
*/
public static void close(ResultSet rs, Statement stmt, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
/**
* 演示JDBC工具类
* @return
*/
public List<Emp> findAll2() {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
List<Emp> list = null;
try {
/*//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
conn = DriverManager.getConnection("jdbc:mysql:///db3?useSSL=false", "root", "123456");*/
conn = JDBCUtils.getConnection();
//3.定义sql
String sql = "select * from emp";
//4.获取执行sql的对象
stmt = conn.createStatement();
//5.执行sql
rs = stmt.executeQuery(sql);
//6.遍历结果集,封装对象,装载结合
Emp emp = null;
list = new ArrayList<Emp>();
while (rs.next()) {
//获取数据
int id = rs.getInt("id");
String ename = rs.getString("ename");
int job_id = rs.getInt("job_id");
int mgr = rs.getInt("mgr");
Date joindate = rs.getDate("joindate");
double salary = rs.getDouble("salary");
double bonus = rs.getDouble("bonus");
int dept_id = rs.getInt("dept_id");
//创建emp对象,并赋值
emp = new Emp();
emp.setId(id);
emp.setEname(ename);
emp.setJob_id(job_id);
emp.setMgr(mgr);
emp.setJoindate(joindate);
emp.setSalary(salary);
emp.setBonus(bonus);
emp.setDept_id(dept_id);
//装载集合
list.add(emp);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
/*if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}*/
JDBCUtils.close(rs, stmt, conn);
}
return list;
}
CREATE DATABASE db4;
CREATE TABLE USER(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(32),
PASSWORD VARCHAR(32)
);
SELECT * FROM USER;
INSERT INTO USER VALUES(NULL, 'zhangsan', '123'),(NULL, 'lisi', '234');
package cn.itcast.jdbc;
import cn.itcast.util.JDBCUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
/**
* * 练习
* * 需求 :
* 1. 通过键盘录入用户名和密码
* 2. 判断用户是否登录成功
*/
public class JDBCDemo9 {
public static void main(String[] args) {
//1.键盘录入,接受用户名和密码
Scanner in = new Scanner(System.in);
System.out.println("请输入用户名: ");
String username = in.nextLine();
System.out.println("请输入密码: ");
String password = in.nextLine();
//2.调用方法
boolean flag = new JDBCDemo9().login(username, password);
//3.判断结果, 输出不同语句
if (flag) {
//登录成功
System.out.println("登录成功");
} else {
//登录失败
System.out.println("用户名或密码错误!");
}
}
/**
*
*/
public boolean login(String username, String password) {
if (username == null || password == null) {
return false;
}
// 连接数据库判断是否登录成功
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
//1.获取连接
conn = JDBCUtils.getConnection();
//2.定义sql
String sql = "select * from user where username = '" + username + "' and password = '"+ password + "' ";
//3.获取执行sql的对象
stmt = conn.createStatement();
//4.执行查询
rs = stmt.executeQuery(sql);
//5.判断
/*if (rs.next()) { // 如果有下一行,则返回true
return true;
} else {
return false;
}*/
return rs.next();// 如果有下一行,则返回true
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(rs, stmt, conn);
}
return false;
}
}
package cn.itcast.jdbc;
import cn.itcast.util.JDBCUtils;
import java.sql.*;
import java.util.Scanner;
/**
* * 练习
* * 需求 :
* 1. 通过键盘录入用户名和密码
* 2. 判断用户是否登录成功
*/
public class JDBCDemo9 {
public static void main(String[] args) {
//1.键盘录入,接受用户名和密码
Scanner in = new Scanner(System.in);
System.out.println("请输入用户名: ");
String username = in.nextLine();
System.out.println("请输入密码: ");
String password = in.nextLine();
//2.调用方法
boolean flag = new JDBCDemo9().login2(username, password);
//3.判断结果, 输出不同语句
if (flag) {
//登录成功
System.out.println("登录成功!");
} else {
//登录失败
System.out.println("用户名或密码错误!");
}
}
/**
* 登录方法一, 使用Statement实现
* @param username
* @param password
* @return
*/
public boolean login(String username, String password) {
if (username == null || password == null) {
return false;
}
// 连接数据库判断是否登录成功
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
//1.获取连接
conn = JDBCUtils.getConnection();
//2.定义sql
String sql = "select * from user where username = '" + username + "' and password = '"+ password + "' ";
System.out.println(sql);
//3.获取执行sql的对象
stmt = conn.createStatement();
//4.执行查询
rs = stmt.executeQuery(sql);
//5.判断
/*if (rs.next()) { // 如果有下一行,则返回true
return true;
} else {
return false;
}*/
return rs.next();// 如果有下一行,则返回true
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(rs, stmt, conn);
}
return false;
}
/**
* 登录方法二,使用PreparedStatement 实现
* @param username
* @param password
* @return
*/
public boolean login2(String username, String password) {
if (username == null || password == null) {
return false;
}
// 连接数据库判断是否登录成功
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
//1.获取连接
conn = JDBCUtils.getConnection();
//2.定义sql
String sql = "select * from user where username = ? and password = ?";
//3.获取执行sql的对象
pstmt = conn.prepareStatement(sql);
//给? 赋值
pstmt.setString(1, username);
pstmt.setString(2, password);
//4.执行查询,不需要传递sql
rs = pstmt.executeQuery();
//5.判断
/*if (rs.next()) { // 如果有下一行,则返回true
return true;
} else {
return false;
}*/
return rs.next();// 如果有下一行,则返回true
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(rs, pstmt, conn);
}
return false;
}
}
开启事务
提交事务
回滚事务
1. 概念 :其实就是一个容器 (集合), 存放数据库连接的容器
当系统初始化好后, 容器被创建, 容器中会申请一些连接对象,当用户来访问数据库时,从容器获取连接对象,用户访问完之后,会将连接对象归还给容器.
2. 好处 :
1. 节约资源
2. 用户访问高效
3. 实现 :
1. 标准接口 :DataSource javax.sql 包下的
1. 方法 :
* 获取连接 : getConnection()
* 归还连接 : Connection.close() .如果连接对象Connection是从连接池中获取的, 那么调用Connection.close()方法,则不会再关闭连接了,而是归还连接
2.
2. 一般我们不去实现它, 有数据库厂商来实现
1. C3P0 : 数据库连接池技术
2. Druid: 数据库连接池实现技术, 由阿里巴巴提供的
4. C3P0 : 数据库连接池技术
* 步骤
1. 导入jar包(两个) c3p0-0.9.5.2.jar 和 mchange-commons-java-0.2.12.jar
* 不要忘记导入数据库的驱动jar包 : mysql-connector-java-5.1.37-bin.jar
2. 定义配置文件 :
* 名称 : c3p0.properties or c3p0-config.xml
* 路径 : 直接将文件放在src目录下即可.
3. 创建核心对象 数据库连接池对象 ComboPooledDatasource
4. 获取连接 ;getConnection
package cn.itcast.datasource.c3p0;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
/**
* c3p0的演示
*/
public class C3P0Demo1 {
public static void main(String[] args) throws SQLException {
//1.创建数据库连接池对象
DataSource ds = new ComboPooledDataSource();
//2.获取连接对象
Connection conn = ds.getConnection();
//3.打印
System.out.println(conn);
}
}
package cn.itcast.datasource.c3p0;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.junit.Test;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
/**
* c3p0的演示
*/
public class C3P0Demo2 {
public static void main(String[] args) throws SQLException {
//1.创建数据库连接池对象, 使用默认配置
DataSource ds = new ComboPooledDataSource();
//2.获取连接对象
for (int i = 1; i <= 11; i++) {
Connection conn = ds.getConnection();
System.out.println(i + ":" + conn);
if (i == 5) {
conn.close();//归还连接到连接池中
}
}
//testNamedConfig();
}
public static void testNamedConfig() throws SQLException {
//1.1 获取DataSource, 使用指定名称的配置
DataSource ds = new ComboPooledDataSource("otherc3p0");
//2.获取连接对象
for (int i = 1; i <= 10; i++) {
Connection conn = ds.getConnection();
System.out.println(i + ":" + conn);
}
}
}
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driverproperty>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/db4property>
<property name="user">rootproperty>
<property name="password">123456property>
<property name="initialPoolSize">5property>
<property name="maxPoolSize">10property>
<property name="checkoutTimeout">3000property>
default-config>
<named-config name="otherc3p0">
<property name="driverClass">com.mysql.jdbc.Driverproperty>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/db4property>
<property name="user">rootproperty>
<property name="password">123456property>
<property name="initialPoolSize">5property>
<property name="maxPoolSize">8property>
<property name="checkoutTimeout">1000property>
named-config>
c3p0-config>
package cn.itcast.utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* Druid连接池的工具类
*/
public class JDBCUtils {
//1.定义成员变量 DataSource
private static DataSource ds;
static {
try {
//1.加载配置文件
Properties pro = new Properties();
pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
//2.获取DataSource
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取连接
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
/**
* 释放资源
* @param stmt
* @param conn
*/
public static void close(Statement stmt, Connection conn) {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();//归还连接
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 释放连接
* @param rs
* @param stmt
* @param conn
*/
public static void close(ResultSet rs, Statement stmt, Connection conn) {
/*if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}*/
close(stmt, conn);
if (conn != null) {
try {
conn.close();//归还连接
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 返回连接池
* @return
*/
public static DataSource getDataSource() {
return ds;
}
}
package cn.itcast.datasource.druid;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
/**
* Druid演示
*/
public class DruidDemo1 {
public static void main(String[] args) throws Exception {
//1.导入jar包
//2.定义配置文件
//3.加载配置文件
Properties pro = new Properties();
InputStream is = DruidDemo1.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
//4.获取连接池对象
DataSource ds = DruidDataSourceFactory.createDataSource(pro);
//5.获取连接
Connection conn = ds.getConnection();
System.out.println(conn);
}
}
package cn.itcast.datasource.druid;
import cn.itcast.utils.JDBCUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* 使用新的工具类
*/
public class DruidDemo2 {
public static void main(String[] args) {
/**
* 完成添加操作 :给account表添加一条记录
*/
Connection conn = null;
PreparedStatement pstmt = null;
try {
//1.获取连接
conn = JDBCUtils.getConnection();
//2.定义sql
String sql = "insert into account values(null, ? , ?)";
//3.获取pstmt对象
pstmt = conn.prepareStatement(sql);
//4.给?赋值
pstmt.setString(1, "王五");
pstmt.setDouble(2, 3000);
//5. 执行sql
int count = pstmt.executeUpdate();
System.out.println(count);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(pstmt, conn);
}
}
}
导入jar包
创建JdbcTemplate 对象, 依赖源DataSource
调用JdbcTemplate 的方法来完成CRUD操作
package cn.itcast.datasource.jdbcTemplate;
import cn.itcast.datasource.domain.Emp;
import cn.itcast.utils.JDBCUtils;
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.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
public class JdbcTemplateDemo2 {
//Junit单元测试, 可以退让方法独立执行
//1.获取JDBCTemplate对象
private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
/**
* 1. 修改 1 号数据的 salary为 10000
*/
@Test
public void test1() {
//2.定义sql
String sql = "update emp set salary = 10000 where id = 1001";
//3.执行sql
int count = template.update(sql);
System.out.println(count);
}
/**
* 2. 添加一条数据
*/
@Test
public void test2() {
//2.定义sql
String sql = "insert into emp(id, ename, dept_id) values(?, ?, ?)";
//3.执行sql
int count = template.update(sql, 1015, "郭靖", 10);
System.out.println(count);
}
/**
* 3.删除刚刚添加的记录
*/
@Test
public void test3() {
//2.定义sql
String sql = "delete from emp where id = ?";
//3.执行sql
int count = template.update(sql, 1015);
System.out.println(count);
}
/**
* 4. 查询id 为 1001的所有的记录, 将其封装为Map集合
* 注意:这个方法查询的结果集长度只能是 1
*/
@Test
public void test4() {
String sql = "select * from emp where id = ?";
Map<String, Object> map = template.queryForMap(sql, 1001);
System.out.println(map);
//{id=1001, ename=孙悟空, job_id=4, mgr=1004, joindate=2000-12-17, salary=10000.00, bonus=null, dept_id=20}
}
/**
* 5. 查询所有记录, 将其封装为List
*/
@Test
public void test5() {
String sql = "select * from emp";
List<Map<String, Object>> list = template.queryForList(sql);
for (Map<String, Object> stringObjectMap : list) {
System.out.println(stringObjectMap);
}
}
/**
* 6. 查询所有记录, 将其封装为Emp对象的List集合
*/
@Test
public void test6_1() {
String sql = "select * from emp";
List<Emp> list = template.query(sql, new RowMapper<Emp>() {
@Override
public Emp mapRow(ResultSet rs, int i) throws SQLException {
Emp emp = new Emp();
int id = rs.getInt("id");
String ename = rs.getString("ename");
int job_id = rs.getInt("job_id");
int mgr = rs.getInt("mgr");
Date joindate = rs.getDate("joindate");
double salary = rs.getDouble("salary");
double bonus = rs.getDouble("bonus");
int dept_id = rs.getInt("dept_id");
emp.setId(id);
emp.setEname(ename);
emp.setJob_id(job_id);
emp.setMgr(mgr);
emp.setJoindate(joindate);
emp.setSalary(salary);
emp.setBonus(bonus);
emp.setDept_id(dept_id);
return emp;
}
});
for (Emp emp : list) {
System.out.println(emp);
}
}
/**
* 6. 查询所有记录, 将其封装为Emp对象的List集合
*/
@Test
public void test6_2() {
String sql = "select * from emp";
List<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class));
for (Emp emp : list) {
System.out.println(emp);
}
}
/**
* 7.查询总记录数
*/
@Test
public void test7() {
String sql = "select count(id) from emp";
Long total = template.queryForObject(sql, Long.class);
System.out.println(total);
}
}
JavaWeb :
软件架构 :
资源分类 :
1. 静态资源 :
* 使用静态网页开发技术发布的资源
* 特点 :
* 所有用户访问, 得到的结果是一样的
* 如 : 文本, 图片, 音频, 视频, HTML, CSS, JavaScript
* 如果用户请求的是静态资源, 那么服务器会直接将静态资源发送给浏览器, 浏览器中内置了静态资源的解析引擎, 可以展示静态资源们
2. 动态资源 :
* 使用动态网页技术发布的资源
* 特点 :
* 所有用户访问, 得到的结果可能不一样
* 如: jsp/servlet,php,asp...
* 如果用户请求的是动态资源,那么服务器会执行动态资源,转换为静态资源,再发送给浏览器
我们要学习动态资源, 必须先学习静态资源!
静态资源 :
1. 概念 : 最基础的网页开发语言
* Hyper Text Markup Language 超文本标记语言
* 超文本 :
* 超文本是用超链接的方法, 将各种不同空间的文字信息组织在一起的网状文本
* 标记语言 :
* 由标签构成的语言 <标签名称>( <标签>标签>) 如 html, xml
* 标记语言不是编程语言
html文档后缀名 .html 或者 .htm
标签分为
标签可以嵌套:
需要正确嵌套,不能你中有我,我中有你
错误 :
正确 :
在开始标签中可以定义属性,属性是由键值对构成,值需要用引号(单双都可)引起来
html的标签不区分大小写,但是建议使用小写
<html>
<head>
<title>titletitle>
head>
<body>
<font color = 'red'>Hello worldfont><br/>
<font color = 'green'>Hello worldfont>
body>
html>
文件标签: 构成html的最基本标签
文本标签: 和文本有关的标签
注释 :
: 段落标签
: 换行标签
: 字体加粗
: 字体斜体
: 字体标签
属性定义 :
图片标签: 和图片有关的标签
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图片标签title>
head>
<body>
<img src="./image/jingxuan_2.jpg" align="right" alt="古镇" width="500" height="500"/>
<img src="./image/jiangwai_1.jpg">
<img src="../image/jiangwai_1.jpg">
body>
html>
4. 列表标签:
* 有序列表 :
* ol
* li
* 无序列表 :
* ul
* li
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>列表标签title>
head>
<body>
早上起床干的事情
<ol type="1" start="5">
<li>睁眼li>
<li>看手机li>
<li>穿衣服li>
<li>洗漱li>
ol>
早上起床干的事情
<ul type="disc">
<li>睁眼li>
<li>看手机li>
<li>穿衣服li>
<li>洗漱li>
ul>
早上起床干的事情
<ul type="square">
<li>睁眼li>
<li>看手机li>
<li>穿衣服li>
<li>洗漱li>
ul>
早上起床干的事情
<ul type="circle">
<li>睁眼li>
<li>看手机li>
<li>穿衣服li>
<li>洗漱li>
ul>
body>
html>
5. 链接标签:
* a : 定义一个超链接
* 属性 :
* href : 指定访问资源的 URL(统一资源定位符)
* target : 指定打开资源的一个方式
* _self : 默认值 , 在当前页面打卡开
* _blank : 在空白页面打开
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>链接标签title>
head>
<body>
<a href="http://www.itcast.cn">点我a>
<br>
<a href="http://www.itcast.cn" target="_self">点我a>
<br>
<a href="http://www.itcast.cn" target="_blank">点我a>
<br>
<a href = "./5_列表标签.html">列表标签a>
<br>
<a href = "mailto:[email protected]">联系我们a>
<br>
<a href="http://www.itcast.cn"><img src="image/jiangxuan_1.jpg">a>
body>
html>
6. div 和 span 块标签 :
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>块标签title>
head>
<body>
<span>黑马程序员span>
<span>传智播客span>
<hr>
<div>黑马程序员div>
<div>传智播客div>
body>
html>
7. 语义化标签 ; html5中为了提高程序的可读性, 提供了一些标签
1.
2.