Java工程师培训课(十五【新的领域】)

夜光序言:

越是漂亮的女孩子,越是会骗人,但是也不排除例外,这需要辩证思考,我们身为男子,那自然笑对苦难,笑对分手之类的不愉快之事,顺其自然,人生只有一次,得之淡然,失之坦然~

正文:Jsp基础,入门简单,深入难,乃万物之常理

2.1 简介

Jsp,全称 Java Server Page java服务页面,能提供java服务的页面

 

jsp vs html

html: 由html标签组成的,输出静态内容。

jsp: 可以写html标签,还可以java代码。

2.2 特点

1)既可以写html代码,也可以写java代码

2)jsp页面需要交给tomcat服务器运行!!!  

2.3 Jsp运行的目录

tomcat的work目录,这个目录下存放jsp页面运行过程中产生的临时文件。

 

2.4 体验jsp页面如何编写和运行

向浏览器输出当前的系统时间

如何访问jsp页面?

直接通过浏览器访问即可!!(把当前html页面访问)

 

2.5 Jsp页面如何被tomcat服务器运行

第一次访问jsp:

1)tomcat服务器把jsp页面翻译成java源文件。(01.hello.jsp  -》  _01_hello_jsp.java)

2)tomcat服务器把java源文件编译成class文件。_01_hello_jsp.java -> _01_hello_jsp.class

3)读取class文件,创建类对象。_01_hello_jsp

4)执行类中的方法。_01_hello_jsp类的方法

 

第n次访问jsp:

4)执行类中的方法。_01_hello_jsp类的方法

直接走第4个步骤

 

注意

修改了jsp页面时,重新走翻译和编译的过程。

 

问题:运行的class类是什么类?

public final class _01_hello_jsp extends org.apache.jasper.runtime.HttpJspBase

 

public abstract class org.apache.jasper.runtime.HttpJspBase extends javax.servlet.http.HttpServlet implements javax.servlet.jsp.HttpJspPage {

 

我们的jsp的源文件是一个servlet!

结论: jsp就是一个servlet!!!!

 

servlet的技术可以用在jsp上。

 

servlet的生命周期:

构造方法:

init方法:

service方法

destory方法

jsp的生命周期

翻译(java文件)

编译(class文件)

构造方法

_jspInit方法

_jspService方法

_jspDestroy方法

 

3 Jsp语法

3.1 Jsp模板

Jsp页面的html代码就是模块

3.2 Jsp表达式

语法: <%=变量或表达式%>

作用: 向浏览器输出变量的值或表达式技术的结构

注意:

1)原理是使用out.print()方法向浏览器输出内容

3.3 Jsp脚本

语法:<% java语句  %>

作用: 执行java语句

原理: 脚本就是原封不动地翻译到java文件的_jspServcice方法中执行。

3.4 Jsp声明

语法:<%! 变量或方法   %>

作用:用于声明变量或方法

原理: 声明的变量是成员变量,声明的方法是成员方法

注意:

1)不要声明和翻译后的java文件相同的方法名

2)jsp脚本不能声明方法

3.5 Jsp注释

语法: <%-- jsp注释 --%>

作用: 注释jsp页面内容

注意:

html的注释会被翻译和执行,而jsp的注释不会被翻译和执行。

 

4 Jsp的三大指令

语法: <%@ 指令  %>

4.1 taglib指令

暂时不学,在jsp标签时学习

4.2 include指令

作用:用于包含其他页面

 

<%--包含头部页面 --%>

  <%@ include file="/common/header.jsp"%>

 

 原理:

直接把包含与被包含页面的内容先合并在一起,然后翻译成一个java源文件,最后编译执行。(先合并再翻译)

(源码包含,也叫做静态包含)

4.3 page指令

作用:告诉浏览器如何翻译jsp文件

 

<%@ page 

language="java"    -- 使用什么语言来翻译jsp文件

import="java.util.*" --导包。导入多个使用逗号

jsp文件的编码相关的:

pageEncoding="utf-8" -- 使用什么编码翻译jsp文件

contentType="text/html; charset=utf-8" --服务器发送给浏览器的数据类型和内容编码格式

异常页面相关的:

errorPage="/common/error.jsp"  -- 指定jsp错误处理页面

isErrorPage="true"  --指定当前页面为错误处理页面,如果是错误处理页面,就可以使用exception内置对象,使用exception对象可以查询错误信息。

配置全局的错误处理页面

      在web.xml文件中配置:

<!-- 配置全局的错误处理页面 -->

<error-page>

<error-code>404</error-code>

<location>/common/404.html</location>

</error-page>

<error-page>

<error-code>500</error-code>

<location>/common/500.jsp</location>

</error-page>

 

session="true"  -- 是否打开session功能,true:打开,false:关闭

buffer="8kb" -- jsp页面的缓存区大小

isELIgnored="false" --是否忽略EL表达式。true:忽略。false:不忽略。

%>

 

 

5 Jsp的最佳实践

servlet技术: 使用java语言开发动态网页。功能:写java代码,输出html代码

jsp技术: 使用java语言开发动态网页。功能:写java代码,输出html代码

 

分工问题:

servlet技术: 写java代码(写普通java类)

jsp技术: 输出html代码(类似于html页面)

 

项目中涉及的功能:

1)接收参数信息    (servlet做)

2)执行业务逻辑(CURD)  ( servlet做 )

3)返回结果,输出结果  (jsp做)

4)跳转页面            (servlet做)

 

 

案例:

显示用户信息

1)查询用户数据(servlet)

List<User>  list

  把用户数据保存到域对象,发送到jsp页面

 

2)显示用户数据 (jsp)

 

6 Jsp的内置对象

6.1 简介

在jsp开发有些对象使用频率比较高,(例如:requesst,respone,session,servletcontext。。。)如果每次要使用这些对象都自己去获取对象才能使用,会显示太麻烦了。jsp把这些对象都创建或获取好了,我们开发者之间使用这些对象即可!!!这些对象就叫做内置对象。

 

6.2 9大内置对象

jsp对象名       类型

 request      HttpServletRequest   请求对象

response      HttpServletResponse  响应对象   

 config       ServletConfig        配置对象

application    ServletContext      servlet上下文对象     

session       HttpSession          会话对象

exception     Throwable            异常信息对象

page           Object      代表jsp文件翻译后的java类

out           JspWriter     代表输出对象,response.getWriter() PrintWriter

   相当于带缓存功能的PrintWriter

pageContext   PageContext    代表jsp的上下文对象

 

    6.3 out对象

out对象的类型JspWriter类,相当于带缓存功能的PrintWriter类

 

6.4 pageContext对象

   作用:

1)通过pageContext对象获取其他8个内置对象

场景:使用自定义标签的时候

 

2)作为域对象使用

2.1 保存到page域

  pageContet.setAttribute("name",Object);

2.2 保存到其他域

pageContext.setAttribute("name,Object,PageContext.PAGE_SCOPE)

PAGE_SCOPE

REQUEST_SCOPE

SESSION_SCOPE

APPLICATION_SCOPE

2.3 获取page域

pageContext.getAttribute("name")

2.4 从其他域中获取

pageContext.getAttribute("name,PageContext.PAGE_SCOPE)

PAGE_SCOPE

REQUEST_SCOPE

SESSION_SCOPE

APPLICATION_SCOPE

2.5 自动搜索四个域数据

pageContext.findAttribute("name")

7 jsp的四个域对象

  request域: HttpServletREquest

 application域: ServletContext

 session域: HttpSession

 page域: PageContext

7.1 域对象的作用

共享数据,保存数据,获取数据

7.2 域对象的方法

setAttribute()

getAttribute()

removeAttribute()

7.3 域的作用范围

从小到大:

page域: 在同一个jsp页面中数据有效!

request域: 在同一个请求中数据有效的!

session域: 在同一个会话中数据有效的!

application域: 在同一个网站中数据有效的!

 

 

总结:

jsp基础

1)jsp执行原理(翻译+编译+servlet)

2)  jsp语法 (jsp表达式+jsp脚本+jsp声明)

3)jsp的三大指令(include指令+page指令)

4)jsp的9个内置对象

(out对象+pageContext对象)

5)jsp的最佳实践

servlet+jsp

 

夜光:作业:

改造现有的servlet+dom4j的通讯录版本

改为: servlet+jsp+dom4j的通讯录版本

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1 Jsp基础

1.1 什么是JSP?

JSP,Java Server Page    Java服务页面

 

html页面: 用html语言写页面

Jsp页面: 用html语言写页面,用java语言写业务逻辑

 

Jsp的特点; 既可以写html代码,也可以写java代码。

1.2 Jsp的作用

Jsp的主要作用是用java语言来开发动态资源的技术。

1.3 Jsp的运行

   servlet: servet程序交给tomcat服务器运行

Jsp:jsp页面交给tomcat服务器运行。

 

jsp在%tomcat%/work目录下产生临时文件。

1.4 Jsp体验

需求: 在浏览器中输出当前时间

 

1.5 Jsp的运行过程

浏览器: http://localhost:8080/day12/01.hello.jsp

 

第1次访问jsp时:

1)tomcat服务器把jsp文件翻译成java源文件(work目录下)_01_hello_jsp.java

2)tomcat服务器把java源文件编译成class字节码 _01_hello_jsp.class

3)tomcat服务器构造类对象(_01_hello_jsp)

4)tomcat服务器调用类对象的方法(_01_hello_jsp中的方法)

第n次访问jsp时:

1)tomcat服务器调用类对象的方法(_01_hello_jsp中的方法)

只走第4步

 

注意:

1)当jsp文件内容发送变化,那么会重新翻译和编译jsp文件。

2)如果java源文件和class字节码删除了,第一次访问jsp时,也会重新翻译和编译。

 

1.6 疑问

1)jsp文件中的html代码和java代码是如何被执行的?

html代码: 通过out.write("内容"); 方法输出到浏览器

java代码: 原封不动拷贝到java源文件中被执行

 

2)Jsp和servlet是什么关系?

 

public final class _01_hello_jsp extends org.apache.jasper.runtime.HttpJspBase

 

public abstract class org.apache.jasper.runtime.HttpJspBase extends javax.servlet.http.HttpServlet implements javax.servlet.jsp.HttpJspPage {

 

结论: Jsp就是一个servlet文件!!!

(servlet的知识点在jsp中全部适用,但jsp的部分知识点未必在servlet都能适用!!!)

 

Servlet的生命周期:

 1)构造方法(第一次访问时)

 2)init方法(第一次访问时)

 3)service方法(第n次访问时)

 4)destroy方法

 

Jsp的生命周期:

 1)翻译成java源文件(第一次访问时)

 2)java源文件编译成class字节码(已经是servlet类)(第一次访问时)

3)构造方法(第一次访问时)

4)_jspInit()方法(第一次访问时)

5)_jspService方法(第n次访问时)

6)_jspDestroy()方法

2 Jsp语法

2.1 Jsp模板

Jsp文件中html代码部分就是模块

2.2 Jsp表达式

语法: <%=变量或表达式%>

作用: 向浏览器输出变量的值或表达式计算的结果

注意:

1)其原理是使用out.print(name );方法向浏览器写出内容

2)结尾不能使用分号

2.3 Jsp脚本

语法: <% java代码 %>

作用: 执行java代码

注意:

1)其原理是直接把java脚本代码翻译到java文件的_jspService方法中执行。

2)Jsp脚本可以穿插html代码混合使用

2.4 Jsp声明

语法: <%! 变量或方法%>

作用: 用于声明jsp文件的变量和方法

注意

1)声明的是成员变量和成员方法。

2)方法不能在脚本中定义,而只能在声明中定义。

3)不能声明和翻译成的java文件中原有方法重复!!!

2.5 Jsp注释

语法: <%-- jsp注释--%>

注意:

1)html注释是会被翻译到java源文件中,也会被执行

2)jsp注释是不会翻译到java源文件中,不会被执行。

3 Jsp的三大指令

2.1 taglib指令

taglib指令主要是用于导入jsp的标签库。

2.2 include指令

include指令用于导入其他页面文件。

语法: <%@include file="导入的页面路径"%>

注意:

1)包含与被包含的页面先合并内容翻译到一个java源文件中,再编译执行一个java文件。(先合 并再翻译),叫静态包含(源码包含)

2)被包含的页面不要使用全局的html标签。(html/head/title/body)

2.3 page指令

page指令主要是用于告诉tomcat服务器如何翻译jsp文件。(jsp->java文件)

 

<%@ page 

language="java"   --告诉服务器以什么语言来翻译jsp文件

import="java.util.*" --导包。多个包用逗号分隔

java.util.Date,java.text.SimleDateFromat

jsp编码相关的

pageEncoding="utf-8"  --jsp翻译成java文件时使用的编码

contentType="text/html; charset=utf-8" --服务器返回给浏览器的数据类型和编码

 

jsp中涉及中文编码问题:

1)保存jsp文件时的编码(另存为)

2)jsp翻译成java文件时的编码(pageEncoding)

3)服务器输出到浏览器的数据编码(contentType)

 

注意:

1)contentType属性如果不写,会参考pageEncoding的编码

2)在ecplise中开发jsp,保存文件时的编码会参考pageEncoding编码

 

结论:

在ecplise中开发jsp文件,只需要在page指令中设置pageEncoding的属性即可解决中 文乱码问题!!

 

错误页面相关的

errorPage="error.jsp"  --指定错误页面

isErrorPage="false"    --指定当前页面是否为错误页面。如果是true,那么就可以是exception内置对象,如果false,则不能使用exception内置对象。exception用于得到错误信息。

 

全局错误页面配置:

在web.xml文件中设置

通常配置两种错误: 404   500

 

<!--  配置全局的错误处理页面 -->

  <error-page>

   <error-code>404</error-code>

   <location>/common/404.html</location>

  </error-page>

  <error-page>

   <error-code>500</error-code>

   <location>/common/500.jsp</location>

  </error-page>

 

buffer="8kb"   --jsp页面的缓存区大小

session="true"  --是否打开session功能。是否可以使用session内置对象

isELIgnored="false"  --是否忽略EL表达式。false,不忽略,可以使用EL;true,不 能EL

 

%>

4 Jsp的9大内置对象

4.1 什么是Jsp的内置对象?

在Jsp的开发过程中,开发者会频繁地使用到一些对象,例如Request,Session对象,ServletConfig,ServletContext,如果每次要使用这些对象都要去创建或者调用方法去得到就比较麻烦。Sun公司为了更加方便开发者在jsp文件中直接得到这些对象,直接就帮我们创建或得到好了这些对象,开发者直接使用这些对象即可,这些直接可以使用的对象就叫内置对象!!!!

<%

//使用请求对象HttpServletRequest

request.getContentPath();

 

//使用HttpSession对象

HttpSession session = requesst.getSesion();  --之前的servlet做法

 

session.setAttribute(name,object);

 

%>

 

4.2 9个内置对象

对象名      对应的类型             备注

    request      HttpServletRequest      请求对象,封装请求信息

response     HttpServletResponse     响应对象,封装响应信息

config       ServletConfig           servlet配置对象,封装servlet配置信息

application ServletContext          servlet的上下文对象,代表整个web应用环境

session      HttpSession             会话对象。用于保存会话数据

exception    Throwable              异常对象,用于封装异常信息

page         Object                代表当前jsp翻译成java类对象

out         JspWriter               jsp页面缓存对象,相当于带缓存功能的PrintWriter

pageContext  PageContext            jsp的上下文件对象,代表当前jsp的环境

 

4.3 out对象

out对象,类型JspWriter

 out.wirter("内容")

 

1) PrintWrite类: 直接往浏览器写出内容

out.write(“内容”);

 

2)JspWriter类: 相当于带缓存的PrintWriter

out.write("内容"): 把内容写入缓存区

 

注意:

当JspWriter缓存区满足以下条件,缓存区内容会写入到PrintWriter中。

1)缓冲区满了。

2)刷新缓冲区(JspWriet.flush())

3)关闭缓冲区 (<%@page buffer="0kb"%>  buffer属性用于设置Jsp'Writer缓存区大小,默认8KB)

4)执行完Jsp页面

 

得到当前缓冲区大小: out.getBufferSize()

得到当前缓冲区剩余大小: out.getRemaining()

4.4 pageContext对象

pageContext对象,类型PageContext类。

 

1)包含了其他8个内置对象的引用

Jsp文件翻译的java类

public class _02_out_jsp{

 

public void _jspService(HttpServletRequest rquest, HttpServetResponse response){

HttpSession session;

ServletConfig config;

......

 

//Sun设计了一个PageContext对象,用于存放其他8个内置对象

PageContext pageContext;

 

//调用method1

method1(pageContext)

 

}

 

public void method1(PageContext pageContext){

//要使用8个内置对象

pageContext.getSession();

pageContext.getRequest();

pageContext.getResponse();

......

}

}

 

以上情况,在自定义标签中频繁使用到!!!

 

2)PageContext作为域对象

    作用: 保存数据和获取数据,清除数据

方法:

getAttribute()

setAttribute()

removeAttribute();

 

保存数据:

默认情况,保存到page域中

pageContext.setAttribute(name,object);

可以指定域保存

pageContext.setAttribute(name,object, int 域范围)

 

域范围:PAGE_SCOPE, REQUET_SCOPE, SESSION_SCOPE , APPLICATION_SCOPE

 

取出数据:

默认情况,从page域取出

pageContext.getAttribute(name);

可以指定域取出

pageContext.getAttribute(name, int 域范围)

 

域范围:PAGE_SCOPE, REQUET_SCOPE, SESSION_SCOPE , APPLICATION_SCOPE

从四个域中搜索:

pageContext.findAttribute(name);

 

搜索顺序: page域-> request域 -> sesion域-> application域

5 Jsp的四个域对象

5.1 域对象的作用:

用于保存数据,获取数据,在不同资源之间共享数据

5.2 域对象的方法:

setAttribute(name,object) ; 保存数据方法

getAttribute(name)  获取数据

romveAttribute(name) 清除数据

5.3 域对象作用范围

page域: 处于同一个jsp页面中数据共享是有效的!!

request域:处于同一个请求中数据共享是有效的!!(使用转发)

session域:处于同一个会话中数据共享是有效的!!(同一个session对象)

application域:处于同一个web应用中数据共享是有效的!!

6 Jsp的最佳实战

Jsp就是一个servlet!!!

 

Servlet的作用:使用java代码开发动态资源。可以写java代码,输出html代码

Jsp的作用: 使用java代码开发动作资源。可以写java代码,也可以输出html代码。

 

项目中可以会涉及的工作:

1)接收参数

2)处理业务逻辑

3)跳转其他资源

4)显示数据

 

Servlet:擅长写java代码

Jsp:擅长显示数据

 

最佳实践:

利用servlet来处理java相关的逻辑事务,把需要显示的数据发送给jsp,然后在jsp中显示数据。

 

servlet+jsp

7 EL表达式

7.1 EL表达式的作用

在jsp显示数据,可以使用jsp表达式向浏览器输出数据。可以使用java脚本来执行业务逻辑。

 

建议: 开发者在jsp页面中要尽量减少java代码,甚至不用java代码

 

EL表达式用于替代jsp页面中的jsp表达式。

Jsp标签用于替代jsp页面中的jsp脚本。

 

EL表达式的作用: 用于向浏览器输出域对象中的变量和表达式计算的结果

(EL表达式必须要求数据放在域对象中的!!!!)

 

语法: ${变量或表达式}

 

7.2 EL语法

1)获取数据

 a)在四个域中获取

${变量}

b)指定域获取数据

${域范围.变量}

 

域范围: pageScope -> requestScope -> sessionScope -> applicationScope

 

2)EL获取普通对象数据

${student.name}  注意name表示调用getName()方法

3)EL获取集合数据(List和Map集合)

${map[key].name}  注意:map[key] 表示调用map对象的get(key)方法获取map的值对象

4)EL可以使用表达式

算术表达式 : ${a+b}

比较表达式:   ${a>b}

逻辑表达式 :  ${true && true}

判空表达式:    ${empty name} 表示判断name为null或者空字符

 

回顾重点内容:

Jsp基础

1)Jsp执行原理:

a)  翻译:tomcat服务器会把jsp文件翻译成java源文件

b)编译:tomcat服务器编译这个java文件,变为class文件

c)构造方法:tomcat服务器构造类对象

d)调用方法: tomcat服务器调用_jspService()方法

 

2)Jsp的9大内置对象

request    HttpServletRequest

response   HttpServletResponse

config      ServletConfig

application   ServletContext

session      HttpSession

exception    Throwable

page        Object

out         JspWriter

pageContext  PageContext

 

    pageContext对象:jsp的上下文对象

作用:

a)可以获取其他8个内置对象

b)作为域对象使用

保存到page域: pageContext.setAttribute("name",Object);

保存到其他域中: pageContext.setAttribute("name“,Object, PageContext.REQUEST_SCOPE)

从page域中获取: pageContext.getAttribute("name");

从其他域中获取: pageContext.getAttribute("name",PageContext.REQUEST_SCOPE);

自动从四个域中搜索: pageContext.findAttribute("name")

顺序: page域 -》 request域 -> session域 -》 application域 -》 null

 

域对象的作用范围:

    PageContext:page域: 在当前jsp页面中数据有效的!

HttpServletRequest:request域: 当前同一个请求中数据有效的!

HttpSession: session域: 当前同一个session(会话)中数据有效的!

ServletContext:application域: 当前同一个网站中数据有效的!

2 EL表达式

2.1 简介

EL表达式替代jsp表达式。因为开发jsp页面的时候遵守原则:在jsp页面中尽量少些甚至不写java代码。

 

EL表达式作用:向浏览器输出域对象中的变量或表达式计算的结果

 

基本语法: ${变量或表达式}    代替<%=变量或表达式%>

 

2.2 EL获取不同类型的数据

普通字符串

普通的对象

数组或List集合

Map集合

2.3 EL执行表达式

算术表达式

比较表达式

逻辑表达式

判空表达式

2.4 EL的11个内置对象

pageContext

pageScope

requestScope

sessionScope

applicatinoScope

param   

paramValues

header

headerValues

cookie

initParam

3 Jsp标签

3.1 简介

EL表达式可以替换jsp表达式,但是EL表达式局限: 不能条件判断,不能赋值,不能迭代。jsp标签替代jsp脚本,完成条件判断,赋值,迭代等等功能。

 

3.2 Jsp标签分类

1)jsp内置标签(动作标签): 使用的时候不需要导入标签库

2)jstl标签(标准标签): 使用的时候都需要导入标签库

3)自定义标签:使用的时候都需要导入标签库

 

3.3 动作标签

<jsp:forward/>   转发标签

<jsp:param/>    参数标签

<jsp:include/>    包含标签

注意:

包含标签的原理是包含与被包含的页面单独翻译成不同的java文件,然后再运行时合并在一起。 (先翻译再合并,动态包含)

静态包含 vs  动态包含

静态包含: 先合并再翻译。不能携带参数

动态包含: 先翻译再合并。携带参数

 

3.4 JSTL标签

  jstl标签,java standard tag libarary java标准标签库。

 

特点: 在使用jstl标签时需要导入标签库

 

jstl标签库分类:

核心标签库(重要)(c)

国际化标签库(fmt)

EL函数库(fn)

SQL标签库(sql)

XML标签库(x)

3.5 使用JSTL标签

1)导入jstl的支持jar包,在java5.0之后jstl已经是属于5.0的支持包里面。

2)使用jsp页面,需要在jsp的顶部使用taglib指令导入需要的标签库

3)使用标签:

<c:set/>

3.6 核心标签库的标签

保存数据:

<c:set></c:set>

获取数据:

     <c:out value=""></c:out>

单条件判断

     <c:if test=""></c:if>

多条件判断

     <c:choose></c:choose>

     <c:when test=""></c:when>

     <c:otherwise></c:otherwise>

用于迭代(循环)

     <c:forEach></c:forEach>

     <c:forTokens items="" delims=""></c:forTokens>

重定向

    <c:redirect></c:redirect>

 

3.7 自定义标签

当现有的标签无法满足需求的时候,就需要开发者自行开发标签。

 

需求: 获取客户端的IP地址

 

3.8 自定义标签的执行过程

访问:http://localhost:8080/day12/07.tag.jsp

 

前提: tomcat启动的时候,会读取day12项目下的WEB-INF的文件。包括web.xml和tld文件。

1)翻译成java文件-》 编译成class文件-> 构造方法- 》 调用_jspService()方法

2)在内存tld文件中,查询是否存在一个uri名称为http://gz.itcast.cn的tld文件

3)得到对应的tld文件内容。

4)读到<itcst:showIp>内容时,截取showIp名称(就是标签),到tld文件中查询是否存在name为showIp的tag标签。

5)取出<tag>标签的内容<tag-class>字符串: gz.itcast.a_tag.ShowIpTag

3.9 自定义标签的生命周期

由tocmat服务器调用的

1)构造方法: 构造标签器对象

2)void setJspContext(JspContext pc)     传入PageContext对象。JspContext是PageContext的父 类。可以使用getJspContext()方法获取PageContext 对象。

3)void setParent(JspTag parent)        传入父标签对象。如果没有父标签,则不调用次方法。

使用getParent()方法获取父标签

4)void setJspBody(JspFragment jspBody)   传入标签体内容。如果没有标签体,则不调用次方法。

使用getJspBody()获取标签体内容。标签体内容封装到 JspFragment中

5)void doTag()                      调用标签时执行方法。我们的业务逻辑就写在这个方法 中。可以调用getJspContext(), getParent(),getJspBody();

 

//  itcast:showIp

    gz.itcast.a_tag.ShowIpTag_jspx_th_itcast_005fshowIp_005f0 = new gz.itcast.a_tag.ShowIpTag();

    org.apache.jasper.runtime.AnnotationHelper.postConstruct(_jsp_annotationprocessor, _jspx_th_itcast_005fshowIp_005f0);

    _jspx_th_itcast_005fshowIp_005f0.setJspContext(_jspx_page_context);

    _jspx_th_itcast_005fshowIp_005f0.setParent(_jspx_parent);

    _jspx_th_itcast_005fshowIp_005f0.setJspBody(new Helper( 1, _jspx_page_context, _jspx_th_itcast_005fshowIp_005f0, null));

    _jspx_th_itcast_005fshowIp_005f0.doTag();

 

总结:

jsp加强:

1)EL表达式:(重点)

${变量或表达式}

2)Jsp标签

2.1 Jsp动作:

<jsp:forward/>

<jsp:param/>

<jsp:include/>

 2.2 jstl的核心标签库(重点)

<c:set/>

<c:out/>

<c:if/>

<c:choose/>+<c:when/>+<c:otherwise/>

<c:forEach/>

<c:forTokens/>

<c:redirect/>

2.3 自定义标签

开发步骤: (使用)

标签处理类+tld文件+使用(taglib)

执行原理:(理解)

setJspContext()

setParent()

setJspBody()

doTag()

 

 

 

 

 

 

1 Jsp标签

1.1 Jsp标签作用

Jsp标签主要在jsp页面执行java代码,用于替换jsp脚本。

 

EL表达式局限:

1)不能保存数据,只能获取数据

2)没有条件判断逻辑

3)没有数据遍历功能

1.2 Jsp标签分类

Jsp内置标签(动作标签): 不需要导入标签库

JSTL标签库:  需要导入标签库

自定义标签: 需要导入标签库

1.3 Jsp内置标签

<jsp:forward/>  转发标签

  用于转发

<jsp:param/>   参数标签

<jsp:incude/>  包含标签

用于包含其他页面

 

注意:

1)其原理是包含与被包含的页面先各自翻译成独立的java源文件,然后再运行时合并再一 起。(先翻译再合并),这叫动态包含

 

  ==== 静态包含  vs   动态包含====

1)原理不一样

a)静态包含(先合并再翻译)  

b)动态包含(先翻译再合并)

2)语法不一样

a)静态包含( includ指令:  <%@include%> )

b)动态包含 (include标签: <jsp:include />)

3)参数传递不同

a)静态包含不能传递参数

b)动态包含可以向被包含页面传递参数

1.4 JSTL标签

jstl , java starardard tag libarary  java标准标签库

 

以前: jsp2.0以前jstl不属于java规范。属于第三方的工具。需要导入jar包

现在: jsp2.0 jstl纳入javaee规范。不需要导入jar包。

 

JSTL标签库分类:

1)核心标签库 (core/c  ) 使用最频繁的

2)国际化互标签库(fmt)

3)EL函数库 (fn)

4)数据库标签库(sql)

5)Xml标签库(x)

 

1.5 JSTL使用步骤

1)确保jstl的支持jar包已经导入到项目中

2)在jsp页面的顶部导入标签库

<%@taglib uri="tld文件的路径" prefix="标签库缩写"%>

 

tld文件: 标签库的声明文件(每套标签都有一个tld文件)

 

<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

3)使用标签库中的标签

<c:set></c:set>

 

1.6 核心标签库

保存数据:

<c:set></c:set>

获取数据

     <c:out value=""></c:out>

单条件判断:

     <c:if test=""></c:if>

多条件判断

    <c:choose></c:choose>

     <c:when test=""></c:when>

     <c:otherwise></c:otherwise>  

数据遍历

   <c:forEach></c:forEach>

     <c:forTokens items="" delims=""></c:forTokens>

1.7 EL函数库

EL函数库: 主要是用于在jsp页面中操作字符串

 

<%

String str = "java-net-php";

str.split("-");

str.substring(0,1);

%>

 

1.8 自定义标签

需求: 在jsp页面上显示客户的IP地址(用标签来实现)

 

1.9 自定义标签步骤

1)编写一个标签处理器程序,继承SimpleTagSupport类

 

/**

 * 标签处理器类

 * @author APPle

 *

 */

public class ShowIpTag extends SimpleTagSupport{

 

/**

 * 执行标签

 */

@Override

public void doTag() throws JspException, IOException {

//得到request对象

PageContext pageContext = (PageContext)this.getJspContext();

HttpServletRequest request = (HttpServletRequest)pageContext.getRequest();

 

//得到客户ip

String ip = request.getRemoteHost();

 

//写出浏览器

pageContext.getOut().write("自定义标签实现获取客户端IP地址:"+ip);

} 

}

 

2)在WEB-INT目录下建立tld文件,例如itcast.tld,内容如下:

 

<?xml version="1.0" encoding="UTF-8" ?>

 

<taglib xmlns="http://java.sun.com/xml/ns/javaee"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"

    version="2.1">

 

  <!-- 标签库版本 -->

  <tlib-version>1.1</tlib-version>

  <!-- 标签库的缩写:简单名称 -->

  <short-name>itcast</short-name>

  <!-- tld文件的唯一标记 -->

  <uri>http://gz.itcast.cn</uri>

 

  <!--标签定义  -->

  <tag>

   <!-- 标签名称 -->

    <name>showIp</name>

   <!-- 标签对应的处理器程序 -->

    <tag-class>gz.itcast.c_tag.ShowIpTag</tag-class>

    <!-- 标签体输出格式 -->

    <body-content>scriptless</body-content>

  </tag>

</taglib>

 

3)在jsp页面中导入自定义标签库,再使用标签库中的标签

 

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

<%@taglib uri="http://gz.itcast.cn"  prefix="itcast"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head> 

    <title>第一个自定义标签</title>  

  </head>

  

  <body>

     <% 

     //得到客户IP地址

     //String ip = request.getRemoteHost();

     //out.write("客户的IP地址为: "+ip);

      %>

      

      <itcast:showIp></itcast:showIp>

  </body>

</html>

 

2 自定义标签

2.1 自定义标签的执行过程

前提: tomcat服务器在加载day14web应用时,读取web.xml和tld文件。

浏览器: http://localhost:8080/day14/01.demo.jsp

 

<itcast:demo1></itcast:demo1>

 

1)服务器读取01.demo.jsp文件,从上下往下读取文件。

2)读到<%@taglib%/>指令,检查是否存在指定uri的tld文件。如果没找到,报错!!

3)读到demo1的标签。在tld文件中查询是否存在name名称为demo1的tag标签。如果找不到,报错!!

4)得到tag标签中的tag-class内容。标签处理类: gz.itcast.a_tag.DemoTag1

5)实例化DemoTag1对象

6)调用DemoTag1类中的方法

2.2 SimpleTag接口方法

void setJspContext(JspContext pc)    设置pageContext上下文件对象。传入当前jsp页面的PageContext 对象。在标签处理类中通过getJspContext()方法得到PageContex 对象

void setParent(JspTag parent)        设置父标签对象。传入父标签对象;如果没有父标签则不调用此 方法。通过getParent()方法得到父标签对象。

void setJspBody(JspFragment jspBody)   设置标签体内容。把标签体内容封装到JspFragment对象中, 然后通过此方法传入。通过getJspBody()方法得到标签体内 容。如果没有标签体则不调用次方法。

void doTag()                        执行标签。

 

2.3 查询源代码了解标签的执行过程

private boolean _jspx_meth_itcast_005fdemo1_005f0(javax.servlet.jsp.tagext.JspTag _jspx_parent, PageContext _jspx_page_context)

          throws Throwable {

    PageContext pageContext = _jspx_page_context;

    JspWriter out = _jspx_page_context.getOut();

    //  itcast:demo1

   1)实例化DemoTag1对象

    gz.itcast.a_tag.DemoTag1 _jspx_th_itcast_005fdemo1_005f0 = new gz.itcast.a_tag.DemoTag1();

    org.apache.jasper.runtime.AnnotationHelper.postConstruct(_jsp_annotationprocessor, _jspx_th_itcast_005fdemo1_005f0);

   2)调用setJspContext方法,传入pageContext

    _jspx_th_itcast_005fdemo1_005f0.setJspContext(_jspx_page_context);

   3)调用setParent方法,传入父标签对象(DemoTag2)

    _jspx_th_itcast_005fdemo1_005f0.setParent(_jspx_parent);

   4)调用setJspBody,传入标签体内容(JspFragment)

    _jspx_th_itcast_005fdemo1_005f0.setJspBody(new Helper( 1, _jspx_page_context, _jspx_th_itcast_005fdemo1_005f0, null));

   5)调用doTag,执行标签

    _jspx_th_itcast_005fdemo1_005f0.doTag();

    org.apache.jasper.runtime.AnnotationHelper.preDestroy(_jsp_annotationprocessor, _jspx_th_itcast_005fdemo1_005f0);

    return false;

  }

2.4 自定义标签作用

1)控制是否执行标签体内容

执行:

jspFragment.invoke(null) 把标签体内容输出到浏览器

不执行:

什么都不做!!! (不执行jspFragment.invoke(null))

2)控制是否执行标签余下的内容

执行:  

什么都不做!!!

不执行:

抛出SkipPageException异常即可!

3)控制重复出现执行标签体内容

 

for(int i=1;i<=5;i++){

jspBody.invoke(null);//默认null,也是输出到浏览器

}

 

4)改变标签体内容

 

//4.1 得到标签体内容

//4.1.1 把标签体内容拷贝到Writer流中

StringWriter sw = new StringWriter();

jspBody.invoke(sw);

//4.1.2 从Writr流中得到标签体内容

String content = sw.toString();

//4.2 修改标签体内容

content = content.toLowerCase();

//4.3 输出到浏览器

//jspBody.invoke(null);注意:不能用再用此方法,因为输出还是原来的内容

this.getJspContext().getOut().write(content);

 

5)带属性的标签

a)在标签处理器类中,添加属性成员变量和一个对应的set方法,用于接收标签的属性值

 

public class DemoTag1 extends SimpleTagSupport{

//1)声明一个成员变量用于接收标签属性值

private Integer num;

 

//2)用于把外面标签的属性值传入进来

public void setNum(Integer num) {

this.num = num;

}

 

b)在tld文件的tag标签中,添加一个属性的声明

 

<tag>

    <name>demo1</name>

    <tag-class>gz.itcast.a_tag.DemoTag1</tag-class>

    <body-content>scriptless</body-content>

    <!-- 声明属性 -->

    <attribute>

     <!-- 属性名称 -->

     <name>num</name>

     <!-- 该属性是否必填 -->

     <required>true</required>

     <!-- 是否指定该属性支持EL表达式 -->

     <rtexprvalue>true</rtexprvalue>

    </attribute>

  </tag>

 

c)在jsp页面中使用属性

 

<itcast:demo1 num="20">AAAAAA<br/></itcast:demo1>

 

2.5 标签体输出格式

JSP: 可以写jsp脚本或表达式,也可以执行!(只能用在传统标签)

scriptless: 不能写jsp脚本或表达式,且不能执行!(可以是EL)

empty:  执行的是空标签或没有标签体内容

tagdependent: 可以写jsp脚本或表达式,按照脚本的原样输出(EL也是原样输出)

3 JavaBean规范

3.1 什么是JavaBean?

JavaBean是一个普通java类,遵守以下几个条件:

1)必须有无参的构造方法
2)把所有属性进行私有化 (private)

3)必须提供公开的getter和setter方法 (public)

 

应用场景:

1)项目中的实体对象(Contact,Student等遵照javabean规范)

2)EL表达式。 ${student.name}  getName()方法。EL要求获取的对象必须遵守javabean规范

3)自定义标签。属性赋值  setName(String name) javabean规范

4)jsp页面中使用javabean对象

 

  JavaBean的作用: 封装对象(数据)

设置数据:  setXXX方法

获取数据: getXXX方法 / isXXX方法(boolean)

 

 

回顾重点内容

1)EL表达式:向浏览器输出域对象中的变量或表达式计算的结果。

  1.1 获取不同类型的数据

普通字符串: ${name}

普通对象: ${student.name}   原理:调用getName() 方法

数组或List集合: ${list[0]}

Map集合: ${map[key]}

  1.2 EL内置对象:

pageContext

pageScope

requestScope

sessionScope

applicationScope

param

paramValues

header

headerValues

cookie

initParam

2)jsp标签:

jstl标签:核心标签库

2.1 导入标签库

<%@taglib uri="tld文件中的uri名称" prefix="tld文件的short-name名称"  %>

2.2 Jsp页面使用核心标签:

<c:set />  用于向域对象中保存数据

<c:out/>  用于从域对象中获取数据

<c:if/>    用于单条件判断

<c:choose/>+<c:when/>+<c:otherwise/> 用于多条件判断

<c:forEach/> + <c:forTokens/>  用于迭代数据(List或Map集合)

<c:redirect/>  用于重定向

2 自定义标签

2.1 自定义标签开发步骤

1)编写标签处理程序,继承SimpleTagSupport类,覆盖doTag方法

2)在WEB-INF目录下建立tld文件,在tld声明标签库信息,以及标签信息。

3)在jsp页面顶部导入标签库,接着使用标签库中的标签。

2.2 自定义标签生命周期

实现了SimpleTag接口的类就是标签处理程序类。

SimpleTag接口:

 1)构造方法

 2)setJspContext(JspContext context)   传入pageContext对象

 3)setParent(JspTag tag)                 传入父标签。如果没有父标签,不会调用次方法

 4)setJspBody(JspFragment jspbody)     传入标签体内容对象。标签体内容封装到JspFragment。 对象中,如果没有标签体内容,不会调用次方法

 5)doTag()                          执行标签。  

2.3 自定义标签的作用

1)控制标签体内容是否输出

输出:调用jspBody.invokie()方法

不输出: 什么都不做!

2)控制标签后面的内容是否输出

3)重复控制标签体内容输出

4)改变标签体内容输出

2.4 带属性的自定义标签

1)在标签处理程序中,添加一个setXXX方法,用于给属性赋值。

 

public void setNum(int num){

this.num = num;

}

 

2)在tld文件的所在标签中进行配置

 

<tag>

    <name>hello</name>

    <tag-class>gz.itcast.a_tag.HelloTag</tag-class>

    <body-content>scriptless</body-content>

    <!-- 配置属性 -->

    <attribute>

     <!-- 属性名称 -->

     <name>num</name>

     <!-- 属性是否必须的: true:一定要  false:可选的 -->

     <required>true</required>

     <!-- 该属性是否可以写EL表达式的内容

     true: 可以写EL

     false: 不能写EL

      -->

     <rtexprvalue>false</rtexprvalue>

    </attribute>

  </tag>

 

2.5 标签体内容的输出格式

<body-content>scriptless</body-content>

 

JSP: 表示标签体内容可以支持和输出jsp表达式内容。(注意:这个配置只能在传统标签中使用)

scriptless: 标签体内容不支持jsp表达式内容。

empty:  标签体内容是空的。该标签是空标签

tagdependent: 标签体内容支持jsp表达式,不输出jsp表达式内容。把jsp表达式当前字符串处理

2.6 案例- 高仿核心标签库

 <c:if/>    <c:choose/>   <c:forEach/>

2.7 自定义标签练习

设计一个登录页面的标签

<itcast:login name="userNanme" password="userPwd" />

 

这个登录标签的执行效果是:

 

JavaBean规范

3.1 简介

  JavaBean就是一个普通的java类,必须遵守以下规则的java类才能称为javabean。

1)必须有一个无参的构造方法

2)把类的属性私有化。   (不能直接访问属性)  private

3)必须提供公开的getter和setter方法 。 (通过getter和setter操作属性)

 

场景:

1)项目的实体对象符合javabean的规范

2)EL表达式,访问对象的属性。${student.name}  原理:调用 getName();

3)自定义标签处理,给标签属性赋值。  setNum(int num)

4)  JSP页面中可以使用javabean

JavaBean作用: 用于封装业务的数据

操作对象的属性:

通过getter或setter方法

 

问题:

  以下方法哪些是符合javabean的规范? (  ACEF   )

A) getName()            B) getName(String name)

C) setName(String name)  D) setName()

E) getTest()             F) isTest()

  

 

总结:

1)自定义标签:(应用)

  自定义标签作用:

控制标签体内容是否输出

控制标签后面的内容是否输出

重复输出标签体内容

改变标签体内容

 带属性的标签

 

   2)编程实战:

MVC开发模式:

M: javabean: 封装业务数据

V: jsp: 显示数据(jstl+el表达式)

C: servlet: 接收参数数据,调用业务逻辑,跳转视图

三层开发结构

dao层: 负责数据访问,实体对象的增删改成

service层: 负责处理系统的业务逻辑

web层: servlet+jsp完成用户交互

 

 

 

重点知识:mysql【数据库-周元】

 

 

 

1. 数据库入门

1.1 引入

数据保存在内存:

 优点: 存取速度快

 缺点: 数据不能永远保存!!!

 

数据保存在文件:

优点: 数据永远保存!!!

缺点:

1)速度比内存操作慢,频繁的IO操作。

2)查询数据不方便

 

数据保存在软件

1)数据永远保存!!!

2)速度比较快

3)查询和管理数据方便

 

数据库软件可以实现以上的功能!!!

 

1.2 市面常见数据库软件

SQL Server: 微软的产品。与net平台兼容比较好!!!收费的。

Oracle:甲骨文公司的产品。 与java平台兼容性最好!!!收费的。

收购Sun公司: java

收购mysql: mysql 数据库软件

中大型企业(中大型应用)

mysql: 开源产品。免费的。与java平台兼容性最好!!

中小企业(中小应用)

 

前面: 学习mysql

后面: 学习oracle

 

mysql学习大纲:

1)学习如何安装和基本使用

2)如何管理数据库

3)如何管理表

4)如何管理数据

5)如何查询数据

2.MySQL数据库

2.1 安装和基本使用

1)下载安装包。mysql-5.5.40-win32.ms

2)如果之前安装过mysql,要先安装文档步骤卸载mysql

3)安装安装文档安装mysql数据库软件。

4)打开cmd命令行:

输入: mysql -u root -p 回车

输入:root

看到:

Welcome to the MySQL monitor.  Commands end with ; or \g.

Your MySQL connection id is 2

Server version: 5.5.40 MySQL Community Server (GPL)

 

Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.

 

Oracle is a registered trademark of Oracle Corporation and/or its

affiliates. Other names may be trademarks of their respective

owners.

 

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

 

mysql>

 

2.2 mysql的结构

先有数据库 -> 再有表  ->再有数据

通过sql语句对mysql数据库进行管理。

3. 管理数据库

3.1 查看所有数据库

mysql> show databases;   --分号结束。sql语句就会发送给mysql服务器端执行

+--------------------+

| Database           |

+--------------------+

| information_schema |      --mysql元数据数据库。

| mysql              |    --mysql配置数据库。其中user表用于管理mysql用户和密码、权限信息。

| performance_schema |     --mysql性能监控信息数据库。

| test               |     --测试数据库。

+--------------------+ 

4 rows in set (0.00 sec)

 

mysql>

3.2 创建数据库

1)创建数据库,并制定默认字符集

 

mysql> create database day16

    -> default character set utf8;

Query OK, 1 row affected (0.00 sec)

 

查看数据库的状态(默认字符串):

show create database day15;

 

 

2)创建数据库,同时指定默认字符集,以及字符集的默认校验规则。

 

mysql> create database day15

    -> default character set utf8

    -> collate utf8_general_ci;     --指定默认的校验规则

Query OK, 1 row affected (0.00 sec)

 

校验规则:

一个字符集可以同时存在多种校验规则。

 

a)使用A校验规则:取字符的ascii码值,进行比较大小

a  <  b

97  98

b)使用B校验规则:取字符的ascii码值的负数,进行比较大小

a  >  b

-97  -98

 

查看常用的字符串集的校验规则:

show character set;

 

3.3 删除数据库

mysql> drop database day15;

Query OK, 0 rows affected (0.00 sec)

 

3.4 修改数据库

修改数据库默认字符集

mysql> alter database day15 default character set gbk;

Query OK, 1 row affected (0.00 sec)

 

4 管理表

4.1 查询所有表

mysql> use day15;   --选择数据库

Database changed

mysql> show tables;  --查看数据库中的所有表

 

4.2 创建表

mysql> create table student(

    -> id int,    -字段:字段名称  字段类型

    -> name varchar(20),

    -> age int

    -> );

 

查看一个表结构:

show creata table student;   以sql格式返回

desc student;  以表格格式返回

4.3 删除表

mysql> drop table student;

Query OK, 0 rows affected (0.01 sec)

 

4.4 修改表

1)添加字段

 

mysql> alter table student add column gender varchar(2);

Query OK, 0 rows affected (0.04 sec)

Records: 0  Duplicates: 0  Warnings: 0

 

mysql> alter table student add a int,add b int; 多个操作

2)修改字段类型

 

mysql> alter table student modify column remark varchar(100);

Query OK, 0 rows affected (0.03 sec)

Records: 0  Duplicates: 0  Warnings: 0

 

3)修改字段名称

 

mysql> alter table student change column remark remark2 varchar(100)

Query OK, 0 rows affected (0.05 sec)

Records: 0  Duplicates: 0  Warnings: 0

 

4)删除字段

 

mysql> alter table student drop column a,drop column b;

Query OK, 0 rows affected (0.04 sec)

Records: 0  Duplicates: 0  Warnings: 0

 

5)修改表名

 

mysql> alter table student rename to student2;

Query OK, 0 rows affected (0.01 sec)

 

5 管理数据

-- *************** 一、 数据增删修改操作 ********************---------

-- 1.1 查看表的数据

SELECT * FROM student;

 

-- 1.2 插入数据

-- 插入所有列(所有列的值都要按顺序依次插入)

INSERT INTO student VALUES(1,'eric',20,'广州人','男');

INSERT INTO student VALUES(2,'rose',25,'佛山人','女');

 

-- 插入部分列(列的数据和值的顺序和数量一定保持一致!)

INSERT INTO student(id,NAME,age,remark2) VALUES(3,'jacky',27,'佛山人');

 

-- 1.3 修改数据

-- 修改所有(用的很少)

UPDATE student SET gender='男';

-- 修改某个某些条件的数据(用的较多)

UPDATE student SET gender='女' WHERE id=2;

 

-- 修改多个列(SET 列名=值,列名=值...)

UPDATE student SET age=28,remark2='韶关人' WHERE id=2;

 

-- 1.4 删除数据

-- 删除表的所有数据(用的较少)

-- 注意:

   -- 1)只能删除表中的数据,不能影响表中的自增长约束

   -- 2)使用delete删除的数据,通过事务可以回滚。

   -- 3)后面带条件

DELETE FROM student;

 

-- 删除部分

DELETE FROM student WHERE id=3;

 

-- 删除所有数据

-- 注意:

   -- 1)既能删除表的数据,也能够把表的子增长约束置为0.

   -- 2)使用truncate删除的数据,不能回滚!

   -- 3)后面不能带条件

TRUNCATE TABLE student;

6 查询数据(重点的重点)

6.1 查询所有列

 

-- 2.1 查询所有列

SELECT * FROM student;

 

6.2 查询指定列

 

-- 2.2 查询指定列(多个列之间以逗号分隔)

SELECT NAME,gender FROM student;

 

6.3 查询时指定别名

-- 2.3 查询时给列指定别名(AS)

SELECT NAME AS '姓名',gender AS '性别' FROM student;

-- AS可以省略

SELECT NAME '姓名',gender '性别' FROM student;

 

6.4 合并列查询

-- 2.5 合并列查询

-- 添加servet,jsp成绩列

ALTER TABLE student ADD servlet INT,ADD jsp INT;

SELECT * FROM student;

UPDATE student SET servlet=86,jsp=75 WHERE id=1;

UPDATE student SET servlet=90,jsp=65 WHERE id=2;

UPDATE student SET servlet=78,jsp=50 WHERE id=3;

UPDATE student SET servlet=85,jsp=80 WHERE id=4;

 

-- 需求: 查询每个学生的servlet和jsp的总成绩

-- 注意: 必须是数值类型

SELECT NAME '姓名',(servlet+jsp) '总成绩'  FROM student;

 

-- 注意,和数值以外合并没有意义

SELECT NAME '姓名',(gender+jsp)  FROM student;

 

6.5 查询时添加常量列

-- 2.4 查询时添加常量列

-- 需要: 在查询学生表时都带上一个班级列,内容为"java就业班"

SELECT NAME '姓名',gender '性别',age '年龄','java就业班' AS '班级' FROM student;

 

6.6 查询去除重复数据

-- 2.6 查询去除重复数据

-- 需求: 统计学生都来自于哪里

SELECT DISTINCT remark2 FROM student;

-- 这种语法也可以

SELECT DISTINCT(remark2) FROM student;

 

6.7 条件查询

-- 2.7 条件查询(where)

SELECT * FROM student;

-- 1) 逻辑条件: and   or

-- 需求: 查询id值为3,且性别为男的学生(交集:两个条件同时满足)

SELECT * FROM student WHERE id=3 AND gender='男';

 

-- 需求:查询id为3,或性别为男的学生(并集: 两个条件其中一个满足)

SELECT * FROM student WHERE id=3 OR gender='男';

 

-- 2)比较条件: >  <  >=  <=  = between and

-- 需求: 查询servlet分数大于80分的学生

SELECT * FROM student WHERE servlet>80;

-- 需求:查询jsp分数小于或等于80分的学生

SELECT * FROM student WHERE jsp<=80;

SELECT * FROM student WHERE jsp<80 OR jsp=80;

-- 需求: 查询servlet成绩大于等于80,且小于等于88的学生

SELECT * FROM student WHERE servlet>=80 AND servlet<=88;

-- 等价于上面

SELECT * FROM student WHERE servlet BETWEEN 80 AND 88; -- (包前包后)

 

-- 3)判空条件:  =''  is null  <>''  is not null

UPDATE student SET remark2="" WHERE id=1;

UPDATE student SET remark2=NULL WHERE id=4;

 

-- 需求: 查询remark字段为空的学生(包含null,也包含字符串)

-- null 和 空字符串的区别:

-- null: 没有数据。 判断null: is null,判断不为null: is not null

-- 空字符: 有数据,数据就是空字符串。判断空字符: =''; 判断不为空字符串: <>''

SELECT * FROM student WHERE remark2 IS NULL;

SELECT * FROM student WHERE remark2='';

 

SELECT * FROM student WHERE remark2 IS NULL OR remark2='';

 

-- 需求:查询remark字段不为空的学生

SELECT * FROM student WHERE remark2 IS NOT NULL AND remark2<>'';

 

-- 4) 模糊条件: like

-- like后面跟上符合

-- %: 表示任意多个字符(0-多个)

-- _: 表示一个字符

-- 需求: 查询姓张的学生

SELECT * FROM student WHERE NAME LIKE '张%';

-- 需求: 查询姓名中包含'张'字的学生

SELECT * FROM student WHERE NAME LIKE '%张%';

-- 需求: 查询姓张,且姓名只有两个字的学生

SELECT * FROM student WHERE NAME LIKE '张__';

 

6.8 聚合查询

 

-- 2.8 聚合查询

SELECT * FROM student;

DELETE FROM student WHERE id=5;

-- 需求: 查询所有学生servlet的总分 (SUM: 求和函数)

SELECT SUM(servlet) FROM student;

 

-- 需求: 查询所有学生servlet的平均分(AVG; 平均函数)

SELECT AVG(servlet) FROM student;

 

-- 需求:查询最高的servlet分数(MAX:最大值函数)

SELECT MAX(servlet) FROM student;

 

-- 需求:查询最低的servlet分数(MIN:最小值函数)

SELECT MIN(servlet) FROM student;

 

-- 需求: 一共几个学生(COUNT: 统计数量函数)

SELECT COUNT(*) FROM student;

SELECT COUNT(id) FROM student; -- 效率会比count(*)效率稍高

 

-- 注意: 聚合函数,会排除null值的数据

SELECT COUNT(remark2) FROM student;

 

6.9 分页查询

-- 2.11 分组查询

-- 需求: 查询男女的数量各自多少

-- 预期结果:

-- 男   3

-- 女   2

-- 1) 对性别进行分组(group by) 2)在分组基础上进行聚合函数总计

 

SELECT gender,COUNT(*) '人数' FROM student GROUP BY gender;

 

6.12 分组筛选

-- 2.12 分组筛选(group by + having(条件))

-- 需求: 查询人数大于2的性别

-- 1)分组   2)统计 3)条件

SELECT gender,COUNT(*) '人数' FROM student GROUP BY gender HAVING COUNT(*)>2;

 

 

 

 

 

 

2 数据约束

2.1什么数据约束

对用户操作表的数据进行约束

2.2 默认值

作用: 当用户对使用默认值的字段不插入值的时候,就使用默认值。

注意:

1)对默认值字段插入null是可以的。

2)对默认值字段可以插入非null

-- 1.1 默认值

CREATE TABLE student(

id INT,

NAME VARCHAR(20),

address VARCHAR(20) DEFAULT '广州天河'  -- 默认值

)

 

DROP TABLE student;

-- 当字段没有插入值的时候,mysql自动给该字段分配默认值

INSERT INTO student(id,NAME) VALUES(1,'张三');

 

-- 注意:默认值的字段允许为null

INSERT INTO student(id,NAME,address) VALUE(2,'李四',NULL);

INSERT INTO student(id,NAME,address) VALUE(3,'王五','广州番禺');

 

2.3 非空

作用: 限制字段必须赋值

注意:

1)非空字符必须赋值

2)非空字符不能赋null

-- 1.2 非空

-- 需求: gender字段必须有值(不为null)

CREATE TABLE student(

id INT,

NAME VARCHAR(20),

gender VARCHAR(2) NOT NULL -- 非空

)

 

-- 非空字段必须赋值

INSERT INTO student(id,NAME) VALUES(1,'李四');

-- 非空字符不能插入null

INSERT INTO student(id,NAME,gender) VALUES(1,'李四',NULL);

 

2.4 唯一

作用: 对字段的值不能重复

注意:

1)唯一字段可以插入null

2)唯一字段可以插入多个null

 

-- 1.3 唯一

CREATE TABLE student(

id INT UNIQUE, -- 唯一

NAME VARCHAR(20)

)

 

INSERT INTO student(id,NAME) VALUES(1,'zs');

INSERT INTO student(id,NAME) VALUES(1,'lisi'); -- ERROR 1062 (23000): Duplicate entry '1' for key 'id'

 

INSERT INTO student(id,NAME) VALUES(2,'lisi');

 

2.5 主键

作用: 非空+唯一

注意:

1)通常情况下,每张表都会设置一个主键字段。用于标记表中的每条记录的唯一性。

2)建议不要选择表的包含业务含义的字段作为主键,建议给每张表独立设计一个非业务含义的 id字段。

-- 1.4 主键(非空+唯一)

DROP TABLE student;

 

CREATE TABLE student(

id INT PRIMARY KEY, -- 主键

NAME VARCHAR(20)

)

 

INSERT INTO student(id,NAME) VALUES(1,'张三');

INSERT INTO student(id,NAME) VALUES(2,'张三');

-- INSERT INTO student(id,NAME) VALUES(1,'李四'); -- 违反唯一约束: Duplicate entry '1' for key 'PRIMARY'

 

-- insert into student(name) value('李四'); -- 违反非空约束: ERROR 1048 (23000): Column 'id' cannot be null

 

2.6 自增长

作用: 自动递增

 

-- 1.5 自增长

CREATE TABLE student(

id INT(4) ZEROFILL PRIMARY KEY AUTO_INCREMENT, -- 自增长,从0开始  ZEROFILL 零填充

NAME VARCHAR(20)

)

 

-- 自增长字段可以不赋值,自动递增

INSERT INTO student(NAME) VALUES('张三');

INSERT INTO student(NAME) VALUES('李四');

INSERT INTO student(NAME) VALUES('王五');

 

SELECT * FROM student;

-- 不能影响自增长约束

DELETE FROM student;

-- 可以影响自增长约束

TRUNCATE TABLE student;

 

2.7 外键

作用:约束两种表的数据

 

出现两种表的情况:

解决数据冗余高问题: 独立出一张表

例如: 员工表  和  部门表

问题出现:在插入员工表数据的时候,员工表的部门ID字段可以随便插入!!!!!

 

使用外键约束:约束插入员工表的部门ID字段值

 

解决办法: 在员工表的部门ID字段添加一个外键约束

 

-- 部门表(主表)

CREATE TABLE dept(

id INT PRIMARY KEY,

deptName VARCHAR(20)

)

 

-- 修改员工表(副表/从表)

CREATE TABLE employee(

id INT PRIMARY KEY,

empName VARCHAR(20),

deptId INT,-- 把部门名称改为部门ID

-- 声明一个外键约束

CONSTRAINT emlyee_dept_fk FOREIGN KEY(deptId) REFERENCES dept(id)

--           外键名称                  外键               参考表(参考字段)

)

 

    注意:

1)被约束的表称为副表,约束别人的表称为主表,外键设置在副表上的!!!

2)主表的参考字段通用为主键!

3)添加数据: 先添加主表,再添加副表

4)修改数据: 先修改副表,再修改主表

5)删除数据: 先删除副表,再删除主表

 

-- 1.6 外键约束

-- 员工表

CREATE TABLE employee(

id INT PRIMARY KEY,

empName VARCHAR(20),

deptName VARCHAR(20) -- 部门名称

)

 

INSERT INTO employee VALUES(1,'张三','软件开发部');

INSERT INTO employee VALUES(2,'李四','软件开发部');

INSERT INTO employee VALUES(3,'王五','应用维护部');

 

SELECT * FROM employee;

 

-- 添加员工,部门名称的数据冗余高

INSERT INTO employee VALUES(4,'陈六','软件开发部');

 

-- 解决数据冗余高的问题:给冗余的字段放到一张独立表中

-- 独立设计一张部门表

CREATE TABLE dept(

id INT PRIMARY KEY,

deptName VARCHAR(20)

)

 

DROP TABLE employee;

 

-- 修改员工表

CREATE TABLE employee(

id INT PRIMARY KEY,

empName VARCHAR(20),

deptId INT,-- 把部门名称改为部门ID

-- 声明一个外键约束

CONSTRAINT emlyee_dept_fk FOREIGN KEY(deptId) REFERENCES dept(id) ON UPDATE CASCADE ON DELETE CASCADE  -- ON CASCADE UPDATE :级联修改

--           外键名称                  外键               参考表(参考字段)

)

 

INSERT INTO dept(id,deptName) VALUES(1,'软件开发部');

INSERT INTO dept(id,deptName) VALUES(2,'应用维护部');

INSERT INTO dept(id,deptName) VALUES(3,'秘书部');

 

INSERT INTO employee VALUES(1,'张三',1);

INSERT INTO employee VALUES(2,'李四',1);

INSERT INTO employee VALUES(3,'王五',2);

INSERT INTO employee VALUES(4,'陈六',3);

 

-- 问题: 该记录业务上不合法,员工插入了一个不存在的部门数据

INSERT INTO employee VALUES(5,'陈六',4); -- 违反外键约束: Cannot add or update a child row: a foreign key constraint fails (`day16`.`employee`, CONSTRAINT `emlyee_dept_fk` FOREIGN KEY (`deptId`) REFERENCES `dept` (`id`))

 

-- 1)当有了外键约束,添加数据的顺序: 先添加主表,再添加副表数据

-- 2)当有了外键约束,修改数据的顺序: 先修改副表,再修改主表数据

-- 3)当有了外键约束,删除数据的顺序: 先删除副表,再删除主表数据

-- 修改部门(不能直接修改主表)

UPDATE dept SET id=4 WHERE id=3;

-- 先修改员工表

UPDATE employee SET deptId=2 WHERE id=4;

 

-- 删除部门

DELETE FROM dept WHERE id=2;

 

-- 先删除员工表

DELETE FROM employee WHERE deptId=2;

 

SELECT * FROM dept;

SELECT * FROM employee;

 

  2.8 级联操作

问题: 当有了外键约束的时候,必须先修改或删除副表中的所有关联数据,才能修改或删除主表!但是,我们希望直接修改或删除主表数据,从而影响副表数据。可以使用级联操作实现!!!

 

级联修改: ON UPDATE CASCADE

级联删除: ON DELETE CASCADE

 

CREATE TABLE employee(

id INT PRIMARY KEY,

empName VARCHAR(20),

deptId INT,-- 把部门名称改为部门ID

-- 声明一个外键约束

CONSTRAINT emlyee_dept_fk FOREIGN KEY(deptId) REFERENCES dept(id) ON UPDATE CASCADE ON DELETE CASCADE  -- ON CASCADE UPDATE :级联修改

--           外键名称                  外键               参考表(参考字段)

)

注意: 级联操作必须在外键基础上使用

 

-- 级联修改(修改)

-- 直接修改部门

UPDATE dept SET id=5 WHERE id=4;

 

-- 级联删除

-- 直接删除部门

DELETE FROM dept WHERE id=1;

 

3 数据库设计

3.1 引入

 需求分析 - 需求分析师 -》 原始需求- > 抽取业务模型

图书模型:图书名称,版本号,作者

学生模型: 学号,学生姓名 手机号码

......

角色:学生 老师,图书管理员

《需求说明书》

 需求设计 -  

概要设计:

 抽取实体:业务模型 -> 实体模型(java 类 c++类)内存

class Book{ name, bookNo,author }

 数据库设计:

业务模型/实体模型 - > 数据模型 (硬盘)

 

数据库表设计

问题: 如何设计?

详细设计

类详细,属性和方法

 

    3.2 三大范式

设计原则: 建议设计的表尽量遵守三大范式。

 

第一范式: 要求表的每个字段必须是不可分割的独立单元

student     :   name              -- 违反第一范式

  张小名|狗娃

sutdent    : name    old_name    --符合第一范式

张小名    狗娃

 

第二范式: 在第一范式的基础上,要求每张表只表达一个意思。表的每个字段都和表的主键有依赖

 

employee(员工): 员工编号  员工姓名 部门名称   订单名称  --违反第二范式

 

员工表:员工编号  员工姓名 部门名称   

 

订单表:  订单编号  订单名称             -- 符合第二范式

      

第三范式: 在第二范式基础,要求每张表的主键之外的其他字段都只能和主键有直接决定依赖关系

 

员工表: 员工编号(主键) 员工姓名  部门编号  部门名 --符合第二范式,违反第三范式 (数据冗余高)

 

员工表:员工编号(主键) 员工姓名  部门编号    --符合第三范式(降低数据冗余)

部门表:部门编号  部门名

4 关联查询(多表查询)

--  **************二、关联查询(多表查询)****************----

-- 需求:查询员工及其所在部门(显示员工姓名,部门名称)

-- 2.1 交叉连接查询(不推荐。产生笛卡尔乘积现象:4 * 4=16,有些是重复记录)

SELECT empName,deptName FROM employee,dept;

 

-- 需求:查询员工及其所在部门(显示员工姓名,部门名称)

-- 多表查询规则:1)确定查询哪些表   2)确定哪些哪些字段   3)表与表之间连接条件 (规律:连接条件数量是表数量-1)

-- 2.2 内连接查询:只有满足条件的结果才会显示(使用最频繁)

SELECT empName,deptName       -- 2)确定哪些哪些字段

FROM employee,dept    -- 1)确定查询哪些表

WHERE employee.deptId=dept.id  -- 3)表与表之间连接条件

 

-- 内连接的另一种语法

SELECT empName,deptName

FROM employee

INNER JOIN dept

ON employee.deptId=dept.id;

 

-- 使用别名

SELECT e.empName,d.deptName

FROM employee e

INNER JOIN dept d

ON e.deptId=d.id;

 

-- 需求: 查询每个部门的员工

-- 预期结果:

 --  软件开发部  张三

 --  软件开发部  李四

 --  应用维护部  王五

 --  秘书部      陈六

 --  总经办      null

-- 2.2 左[外]连接查询: 使用左边表的数据去匹配右边表的数据,如果符合连接条件的结果则显示,如果不符合连接条件则显示null

 -- (注意: 左外连接:左表的数据一定会完成显示!)

SELECT d.deptName,e.empName

FROM dept d

LEFT OUTER JOIN employee e

ON d.id=e.deptId;

 

-- 2.3 右[外]连接查询: 使用右边表的数据去匹配左边表的数据,如果符合连接条件的结果则显示,如果不符合连接条件则显示null

 -- (注意: 右外连接:右表的数据一定会完成显示!)

SELECT d.deptName,e.empName

FROM employee e

RIGHT OUTER JOIN dept d

ON d.id=e.deptId;

 

-- 2.4 自连接查询

-- 需求:查询员工及其上司

-- 预期结果:       

-- 张三    null

-- 李四    张三

-- 王五    李四

-- 陈六    王五

SELECT e.empName,b.empName

FROM employee e

LEFT OUTER JOIN employee b

ON e.bossId=b.id;

 

5 存储过程

5.1 什么是存储过程

  存储过程,带有逻辑的sql语句

之前的sql没有条件判断,没有循环

存储过程带上流程控制语句(if  while)

5.2 存储过程特点

1)执行效率非常快!存储过程是在数据库的服务器端执行的!!!

2)移植性很差!不同数据库的存储过程是不能移植。

 

5.3 存储过程语法

-- 创建存储过程

DELIMITER $       -- 声明存储过程的结束符

CREATE PROCEDURE pro_test()           --存储过程名称(参数列表)

BEGIN             -- 开始

-- 可以写多个sql语句;          -- sql语句+流程控制

SELECT * FROM employee;

END $            -- 结束 结束符

 

-- 执行存储过程

CALL pro_test();          -- CALL 存储过程名称(参数);

 

参数:

IN:   表示输入参数,可以携带数据带存储过程中

OUT: 表示输出参数,可以从存储过程中返回结果

INOUT: 表示输入输出参数,既可以输入功能,也可以输出功能

 

 

-- **************三、存储过程*******************-

-- 声明结束符

-- 创建存储过程

DELIMITER $

CREATE PROCEDURE pro_test()

BEGIN

-- 可以写多个sql语句;

SELECT * FROM employee;

END $

 

-- 执行存储过程

CALL pro_test();

 

-- 3.1 带有输入参数的存储过程

-- 需求:传入一个员工的id,查询员工信息

DELIMITER $

CREATE PROCEDURE pro_findById(IN eid INT)  -- IN: 输入参数

BEGIN

SELECT * FROM employee WHERE id=eid;

END $

 

-- 调用

CALL pro_findById(4);

 

-- 3.2 带有输出参数的存储过程

DELIMITER $

CREATE PROCEDURE pro_testOut(OUT str VARCHAR(20))  -- OUT:输出参数

BEGIN

        -- 给参数赋值

SET str='helljava';

END $

 

-- 删除存储过程

DROP PROCEDURE pro_testOut;

-- 调用

-- 如何接受返回参数的值??

-- ***mysql的变量******

--  全局变量(内置变量):mysql数据库内置的变量 (所有连接都起作用)

        -- 查看所有全局变量: show variables

        -- 查看某个全局变量: select @@变量名

        -- 修改全局变量: set 变量名=新值

        -- character_set_client: mysql服务器的接收数据的编码

        -- character_set_results:mysql服务器输出数据的编码

        

--  会话变量: 只存在于当前客户端与数据库服务器端的一次连接当中。如果连接断开,那么会话变量全部丢失!

        -- 定义会话变量: set @变量=值

        -- 查看会话变量: select @变量

        

-- 局部变量: 在存储过程中使用的变量就叫局部变量。只要存储过程执行完毕,局部变量就丢失!!

 

-- 1)定义一个会话变量name, 2)使用name会话变量接收存储过程的返回值

CALL pro_testOut(@NAME);

-- 查看变量值

SELECT @NAME;

 

-- 3.3 带有输入输出参数的存储过程

DELIMITER $

CREATE PROCEDURE pro_testInOut(INOUT n INT)  -- INOUT: 输入输出参数

BEGIN

   -- 查看变量

   SELECT n;

   SET n =500;

END $

 

-- 调用

SET @n=10;

 

CALL pro_testInOut(@n);

 

SELECT @n;

 

-- 3.4 带有条件判断的存储过程

-- 需求:输入一个整数,如果1,则返回“星期一”,如果2,返回“星期二”,如果3,返回“星期三”。其他数字,返回“错误输入”;

DELIMITER $

CREATE PROCEDURE pro_testIf(IN num INT,OUT str VARCHAR(20))

BEGIN

IF num=1 THEN

SET str='星期一';

ELSEIF num=2 THEN

SET str='星期二';

ELSEIF num=3 THEN

SET str='星期三';

ELSE

SET str='输入错误';

END IF;

END $

 

CALL pro_testIf(4,@str);

 

SELECT @str;

 

-- 3.5 带有循环功能的存储过程

-- 需求: 输入一个整数,求和。例如,输入100,统计1-100的和

DELIMITER $

CREATE PROCEDURE pro_testWhile(IN num INT,OUT result INT)

BEGIN

-- 定义一个局部变量

DECLARE i INT DEFAULT 1;

DECLARE vsum INT DEFAULT 0;

WHILE i<=num DO

      SET vsum = vsum+i;

      SET i=i+1;

END WHILE;

SET result=vsum;

END $

 

DROP PROCEDURE pro_testWhile;

 

 

CALL pro_testWhile(100,@result);

 

SELECT @result;

 

USE day16;

 

-- 3.6 使用查询的结果赋值给变量(INTO)

DELIMITER $

CREATE PROCEDURE pro_findById2(IN eid INT,OUT vname VARCHAR(20) )

BEGIN

SELECT empName INTO vname FROM employee WHERE id=eid;

END $

 

CALL pro_findById2(1,@NAME);

 

SELECT @NAME;

 

6 触发器

6.1 触发器作用

当操作了某张表时,希望同时触发一些动作/行为,可以使用触发器完成!!

 

例如: 当向员工表插入一条记录时,希望同时往日志表插入数据

 

-- 需求: 当向员工表插入一条记录时,希望mysql自动同时往日志表插入数据

-- 创建触发器(添加)

CREATE TRIGGER tri_empAdd AFTER INSERT ON employee FOR EACH ROW    -- 当往员工表插入一条记录时

     INSERT INTO test_log(content) VALUES('员工表插入了一条记录');

     

-- 插入数据

INSERT INTO employee(id,empName,deptId) VALUES(7,'扎古斯',1);

INSERT INTO employee(id,empName,deptId) VALUES(8,'扎古斯2',1);

 

-- 创建触发器(修改)

CREATE TRIGGER tri_empUpd AFTER UPDATE ON employee FOR EACH ROW    -- 当往员工表修改一条记录时

     INSERT INTO test_log(content) VALUES('员工表修改了一条记录');

     

 -- 修改

 UPDATE employee SET empName='eric' WHERE id=7;

 

-- 创建触发器(删除)

CREATE TRIGGER tri_empDel AFTER DELETE ON employee FOR EACH ROW    -- 当往员工表删除一条记录时

     INSERT INTO test_log(content) VALUES('员工表删除了一条记录');

  

 -- 删除

 DELETE FROM employee WHERE id=7;

 

7 mysql权限问题

-- ***********五、mysql权限问题****************

 -- mysql数据库权限问题:root :拥有所有权限(可以干任何事情)

 -- 权限账户,只拥有部分权限(CURD)例如,只能操作某个数据库的某张表

 -- 如何修改mysql的用户密码?

 -- password: md5加密函数(单向加密)

 SELECT PASSWORD('root'); -- *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B

 

--  mysql数据库,用户配置 : user表

USE mysql;

 

SELECT * FROM USER;

 

-- 修改密码

UPDATE USER SET PASSWORD=PASSWORD('123456') WHERE USER='root';

 

-- 分配权限账户

GRANT SELECT ON day16.employee TO 'eric'@'localhost' IDENTIFIED BY '123456';

GRANT DELETE ON day16.employee TO 'eric'@'localhost' IDENTIFIED BY '123456';

 

回顾重点内容

1)jsp自定义标签

1.1 自定义标签的生命周期

a)构造方法

b)setJspContext()   传入pageContext对象

c)setParent()   传入父标签对象

d)setJspBody(JspFragment) 传入标签体内容

e) doTag()  执行标签

1.2 自定义标签作用

控制标签体内容是否输出:

输出: 调用 getJspBody().invoke(null)

不输出: 不调用

控制标签后面的内容是否输出:

输出: 不用做

不输出: 抛出一个SkipPageException异常

重复输出标签体内容:

循环执行getJspBody().invoke(null)

修改标签体内容:

a) 创建临时容器 : StringWriter sw = new StringWriter();

b)把标签体内容拷贝到临时容器: jspBody().invoke(sw)

c) 获取标签体内容:  sw.toString();

d)修改内容

e)手动输出到浏览器: this.getJspContext.getOut().write(修改后的内容);

1.3 带属性的标签

a)  在标签处理程序添加一个   setXXX方法

b)在tld文件中声明属性

 

2)编码实战

2.1 JavaBean规范

    Javabean三个要求:

a)提供无参的构造方法

b)私有化属性

c)提供公开的getter和setter方法,以便操作javabean的属性

 

javabean作用: 封装业务数据

 

    2.2 MVC开发模式(servlet+jsp+javabean)

M,Model 模型,javabean,封装业务数据

V, View 视图, jsp,数据展示

C,Controller,控制器, servlet,接收参数,调用业务逻辑,跳转视图

 

2.3 三层开发结构(底层往上层)

dao层:数据访问对象。对数据(实体对象)操作的方法

service层: 业务逻辑对象。系统中的业务逻辑处理方法

web层: 表现层。数据展示(jsp),流程控制(servlet)

 

今天: mysql基础

 

管理数据的问题

 

1 数据库入门

1.1 引入

方式一: 数据放到内存

优点:

1)擦写数据的效率很高!

缺点:

1)无法永久保存,当程序关闭了,数据丢失

 

方式二: 数据放到普通文件

优点:

1)可以永久保存

缺点:

1)频繁地进行IO操作,效率比较低

2)查询数据不方便的!!!

 

方式三: 数据放到数据库软件

优点:

    1)数据永久保存下来

2)查询数据非常方便的!!

3)效率不能低

 

1.2 市面上常见的数据库软件

数据库软件,存储和管理数据的仓库。

 

Oracle: 是甲骨文公司的产品。满足中大型应用。和java语言兼容性非常好的。

SQL Server: 是微软公司的产品。和net平台(c#语言)兼容最好。

DB2: 是IBM的产品。

mysql:开源的数据库产品。和java语言兼容非常好。满足中小型应用。

mangoDB: noSQL数据库

 

mysql: 满足中小型应用

oracle:满足中大小应用

1.3 mysql数据库基本使用

 

C:\Users\APPle>mysql -u root -p

Enter password: ****

Welcome to the MySQL monitor.  Commands end with ; or \g.

Your MySQL connection id is 12

Server version: 5.5.40 MySQL Community Server (GPL)

 

Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.

 

Oracle is a registered trademark of Oracle Corporation and/or its

affiliates. Other names may be trademarks of their respective

owners.

 

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

 

mysql>

 

 

2 管理数据库

2.1 查看所有数据库

 

mysql> show databases;

+--------------------+

| Database           |

+--------------------+

| information_schema |         数据库的元数据

| mysql              |        数据库用户信息或软件配置信息

| performance_schema |        数据库软件运行的性能数据

| test               |        测试数据库

+--------------------+

4 rows in set (0.00 sec)

 

2.2 创建新的数据库

mysql> create database day14;

Query OK, 1 row affected (0.00 sec)

指定字符集

 

mysql> create database day15 default character set gbk;

Query OK, 1 row affected (0.01 sec)

2.3 修改数据库

修复数据库的字符集

mysql> alter database day15 default character set utf8;

Query OK, 1 row affected (0.00 sec)

 

 

2.4删除数据库

 

mysql> drop database day15;

Query OK, 0 rows affected (0.01 sec)

 

3 管理表

操作表之前,需要切换数据库:  use 数据库名称     例如  use day14;

3.1 创建新的表(create table)

mysql> create table student(id int,name varchar(20),age int);

Query OK, 0 rows affected (0.01 sec)

 

create table 表名(字段名称 字段类型,字段名称 字段类型.....);

 

3.2 修改表(alter table)

添加字段:

 

 

mysql> alter table student add column gender varchar(1);

Query OK, 0 rows affected (0.04 sec)

Records: 0  Duplicates: 0  Warnings: 0

修改字段类型:

 

mysql> alter table student modify column gender varchar(2);

Query OK, 0 rows affected (0.03 sec)

Records: 0  Duplicates: 0  Warnings: 0

修改字段名称:

mysql> alter table student change column gender sex varchar(2);

Query OK, 0 rows affected (0.06 sec)

Records: 0  Duplicates: 0  Warnings: 0

删除字段:

mysql> alter table student drop column age;

Query OK, 0 rows affected (0.02 sec)

Records: 0  Duplicates: 0  Warnings: 0

修改表名称:

mysql> alter table student rename to teacher;

Query OK, 0 rows affected (0.01 sec)

 

 

3.3 查看表

mysql> desc student;

+-------+-------------+------+-----+---------+-------+

| Field | Type        | Null | Key | Default | Extra |

+-------+-------------+------+-----+---------+-------+

| id    | int(11)     | YES  |     | NULL    |       |

| name  | varchar(20) | YES  |     | NULL    |       |

| age   | int(11)     | YES  |     | NULL    |       |

+-------+-------------+------+-----+---------+-------+

 

show tables: 查看当前数据库的所有表

3.4 删除表

 

mysql> drop table teacher;

Query OK, 0 rows affected (0.01 sec)

 

 

4 管理数据

 

-- 二、管理数据

-- 1.1插入数据(insert into)

-- 需求: 往学生表插入数据

INSERT INTO student VALUES(1,'张三',20);

-- 1)插入的字段值顺序一定是按照表的字段顺序

INSERT INTO student VALUES('张三',1,20); -- ERROR 1366 (HY000): Incorrect integer value: 'eric' for column 'id' at row 1

-- 2)字段的数据一定要和值的数量要一致

INSERT INTO student VALUES(2,20); -- ERROR 1136 (21S01): Column count doesn't match value count at row 1

-- 3)插入部分字段

INSERT INTO student(id,NAME) VALUES(2,'李四');

 

 

-- 1.2 修改数据(update)

-- 需求: 修改学生表

-- 1)批量操作(不建议经常使用这种)

UPDATE student SET NAME='张三';

-- 2)按条件修改,修改一个字段

-- 需求: 修改id为2的学生姓名

UPDATE student SET NAME='李四' WHERE id=2;

-- 需求: 修改id为1的学生姓名和年龄

-- 3)修改多个字段

UPDATE student SET NAME='王五',age=40 WHERE id=1;

 

-- 1.3 删除数据(delete from)

-- 1) 全表数据删除

DELETE FROM student;

-- 2)按条件删除数据

DELETE FROM student WHERE id=2;

-- 3)truncate table也可以删除全表数据

TRUNCATE TABLE student;

-- 注意:delete from 和 truncate table 的区别?

--  1)delete from删除全部,也可以按条件删除,但是truncate table只能全表删除,不能按条件删除

--  2)delete from删除的数据可以回滚,truncate table删除的数据不能回滚。

--  3)delete from不可以把自增长约束(auto_increment)重置,truncate table可以把自增长约束(auto_increment)重置

 

-- truncate table student where id=1; 错误的语法

 

 

-- 1.4 查看所有数据(重点中的重点)

SELECT * FROM student;

 

5 查询数据(重点)

5.1 查询所有字段

5.2 查询指定的字段

5.3 查询时指定别名

5.4 查询时添加常量列

5.5 查询时合并列

5.6 查询去除重复记录

5.7 条件查询

-- 3.1 查询所有字段

SELECT * FROM student;

 

-- 3.2 查询指定的字段

SELECT id,NAME FROM student;

 

-- 3.3 查询时指定别名

SELECT id AS '编号',NAME AS '姓名' FROM student;

-- AS可以省略

SELECT id '编号',NAME '姓名' FROM student;

 

-- 3.4 查询时添加常量列

-- 临时使用的列可以通过查询时动态添加进去

-- 需求: 查询学生数据时添加一个"班级"列。值为“java就业班”

SELECT id AS '编号',NAME AS '姓名','java就业班' AS '班级' FROM student;

 

-- 3.5 查询时合并列

-- 需求: 查询每个学生的总分。

SELECT NAME AS '姓名',(servlet+mysql) AS '总成绩' FROM student;

-- 注意: 合并列的字段必须是数值类型的字段。非数值类型合并没有效果

SELECT NAME AS '姓名',(servlet+NAME) FROM student;

 

 

-- 3.6 查询去除重复记录(distinct)

-- 需求: 查询有哪些的地区学生

SELECT DISTINCT address FROM student;

-- 另一种语法

SELECT DISTINCT(address) FROM student;

 

-- 3.7 条件查询(where)

-- 1)逻辑条件: and(与)     or(或)

-- 当出现两个或两个以上的条件,那么这两个条件直接一定会存在逻辑关系。要么是与关系,要么或关系

 

-- 需求:查询学生的id为1,且姓名为张三的学生 

SELECT * FROM student WHERE id=1 AND NAME='张三'; -- (交集,结果数小于或等于任何一个条件的结果数)

 

-- 需求:查询学生的id为2,或姓名为张三的学生

SELECT * FROM student WHERE id=2 OR NAME='张三';  -- (并集,结果数一定会大于或等于任何一个条件的结果数)

 

 

-- 2)比较条件: >  <  >=   <=  =  <>  (between and)

-- 需求: 查询servlet分数大于80分的学生

SELECT * FROM student WHERE servlet>80;

-- 需求:查询mysql分数小于或等于85分的学生

SELECT * FROM student WHERE mysql<=85;

SELECT * FROM student WHERE mysql<85 OR mysql=85;

-- 需求: 查询servlet分数大于或等于80分,且小于或等于85分的学生

SELECT * FROM student WHERE servlet>=80 AND servlet<=85;

-- 上面sql代替的语法

SELECT * FROM student WHERE servlet BETWEEN 80 AND 85; -- 在..。之间(包前包后)

-- 需求:查询年龄不等于30岁的学生

SELECT * FROM student WHERE age<>30;

 

-- 3)判空条件: is null , is not null, ='' , <>''

-- null: 表示没有数据   is null   is not null

-- 空字符:有数据    =''   

-- 需求:查询没有性别数据的学生(数据‘男’或‘女’)

SELECT * FROM student WHERE gender IS NULL OR gender='';

 

-- 需求: 查询有性别数据的学生

SELECT * FROM student WHERE gender IS NOT NULL AND gender<>'';

 

 

-- 4)模糊条件: like

-- 模糊替代符号:

--  %: 替代任意个字符

--  _: 替代一个字符

-- 需求: 查询姓‘李’的学生

SELECT * FROM student WHERE NAME LIKE '李%';

-- 需求: 查询姓名中包含‘四’字的学生

SELECT * FROM student WHERE NAME LIKE '%四%';

-- 需求:查询姓‘李’,全名只有两个字的学生

SELECT * FROM student WHERE NAME LIKE '李_';

 

5.8 聚合查询

5.9 分页查询

5.10 查询后排序

5.11 分组查询

5.12 分组查询后筛选

 

总结:

1)mysql数据结构: 数据库 -> 表 -> 数据

2)管理数据库:

create database

alter database

drop database

show databases;

3)管理表:

create table

alter table

drop table

show tables; / desc 表

4)管理数据

insert into

update 表 set ...

delete from 表

12种查询(重点)

 

 

 

 

 

回顾重点内容

mysql基础:

1)管理数据库:

增: create database 数据库名 default character set 字符集;

修: alter database 数据库名 default character set 新的字符集;

删: drop database 数据库名;

查: show databases;

2)管理表:

增: create table 表名(字段名1 字段类型,字段名2 字段类型......);

修:

增加字段: alter table 表名 add column 字段名 字段类型;

修改字段类型: alter table 表名 modify column 字段名 新的字段类型;

修改字段名: alter table 表名 change column 旧字段名 新的字段名 字段类型;

修改表名: alter table 表名 rename to 新表名;

删: drop table 表名;

查: show tables;         desc 表名;

3)管理数据:

增: insert into 表名(字段名1,字段名2....) values(值1,值2.....);

修: update 表名 set 字段名1=值1,字段名2=值2...... where 条件;

删: delete from 表名 where 条件;

 truncate table 表名;

查: (12中查询)

a)所有字段:select * from 表名;

b)指定字段: select 字段名1,字段名2 from 表名;

c)指定别名: select 字段名1 as 别名1,字段名2 as 别名2  from 表名;

d)添加常量列: select 常量值 as 别名 from 表名;

e)合并列: select (字段名1+字段名2+....) as 别名 from 表名;

f)去除重复: select distinct 字段名 from 表名;

g)条件查询:

 逻辑条件: where 条件1 and/or 条件2;

 比较条件: where 字段名  >/>=/</<=/=/<> 值

where 字段名 between 值1 and 值2;

判空条件:

null;   where 字段名 is null/is not null;

    空字符串:  where 字段名=''/<>''

模糊条件: where 字段名 like 值

%: 代表任意个字符

_: 代表一个字符

h)聚合查询:

 max(): 最大值

 min():最小值

 avg():平均值

 count(): 统计数量

i)分页查询:

 limit 起始行,查询行数

j)排序:

order by 字段名 asc/desc

asc: 升序

desc: 降序

h)分组查询:

group by 字段名

k)分组后筛选:

group by 字段名 having 条件;

 

sql语句分类:

1)数据定义语句(DDL):

create/alter/drop

2)数据操作语句(DML)

insert/update/delete/truncate

3)数据查询语句(DQL)

select/show

 

 

1 数据约束

1.1 简介

给表添加数据约束,从而约束用户操作表数据的行为。

 

1.2 默认值约束

注意: 当前没有插入默认值字段的时候,默认值才会起作用

 

-- 1.1 默认值(default)

CREATE TABLE test(

NAME VARCHAR(20),

gender VARCHAR(2) DEFAULT '男'

)

 

INSERT INTO test(NAME) VALUES('张三');

INSERT INTO test(NAME,gender) VALUES('张三',NULL);

 

SELECT * FROM test;

 

-- 需求:当不插入gender的时候,分配一个‘男’的默认值

-- 注意: 1)当没有插入gender字段的时候,分配一个默认值

 

1.3 非空约束

-- 1.2 非空(not null)

CREATE TABLE test(

NAME VARCHAR(20) NOT NULL,

gender VARCHAR(2)

)

-- 需求: name字段一定要有值(不能不插入数据,不能是null),这是给name添加非空约束

-- 1)非空约束,不能不插入值

INSERT INTO test(gender) VALUES('男'); -- ERROR 1364 (HY000): Field 'NAME' doesn't have a default value

 

-- 2)非空约束,不能插入null

INSERT INTO test(NAME,gender) VALUES(NULL,'男'); -- ERROR 1048 (23000): Column 'NAME' cannot be null

 

1.4 唯一约束

CREATE TABLE test(

id INT UNIQUE,

NAME VARCHAR(20)

)

-- 需求: id的值不能出现重复值。这时就要给id添加一个唯一约束。

INSERT INTO test(id,NAME) VALUES(1,'张三');

-- 1)不能插入重复的值

INSERT INTO test(id,NAME) VALUES(1,'李四'); -- Duplicate entry '1' for key 'id'

INSERT INTO test(id,NAME) VALUES(2,'李四');

-- 2)唯一约束,可以插入多个null。所以唯一约束不能约束null

INSERT INTO test(id,NAME) VALUES(NULL,'王五');

INSERT INTO test(id,NAME) VALUES(NULL,'陈六');

 

1.5 主键约束

-- 1.4 主键约束(primary key)(唯一+非空)

-- 注意:

-- 1)通常情况下,我们会给每张表都会设置一个主键字段,用来标记记录的唯一性

-- 2)但是不建议把业务含义字段作为主键,因为随着业务的变化,业务字段可能会出现重复。

-- 3)建议给每张张独立添加一个叫id的字段,把这个id字段设置成主键,用来作为记录的唯一性。

 

CREATE TABLE test(

id INT PRIMARY KEY,

NAME VARCHAR(20)

)

 

-- 1)唯一性

INSERT INTO test(id,NAME) VALUES(1,'张三');

INSERT INTO test(id,NAME) VALUES(1,'张三'); -- Duplicate entry '1' for key 'PRIMARY'

 

-- 2)非空性

INSERT INTO test(id,NAME) VALUES(NULL,'张三'); -- ERROR 1048 (23000): Column 'id' cannot be null

 

1.6 自增长约束

1.7 外键约束

外键约束: 约束两种表的情况

问题:什么情况下会出现两种表?

答案:员工表中出现部门名称的冗余字段!!!!

如何解决部门名称冗余问题?

答案:独立设计一张部门表,把部门名称放到部门表中,这是员工表只需要关联部门的id即可!!

问题: 当插入员工表的部门id的时候,可能会出现不存在的部门id!!这是非法数据!!!如何防止非法数据的插入?

答案: 这是可以把员工表的部门id设置为外键约束

 

当有了外键约束之后,操作数据的顺序如下:

插入数据: 先插入主表的数据,再插入副表数据

修改数据: 先修改主表数据,再修改副表数据

  删除数据: 先删除副表数据,再删除主表数据

 

-- 1.6 外键约束

-- 外键作用: 约束两种表的数据

-- 问题: 约束哪种情况下的两种表呢?

-- 员工表

CREATE TABLE employee(

id INT PRIMARY KEY AUTO_INCREMENT,

NAME VARCHAR(20),

deptName VARCHAR(20)

)

 

 

INSERT INTO employee(NAME,deptName) VALUES('张三','软件开发部');

INSERT INTO employee(NAME,deptName) VALUES('李四','软件维护部');

INSERT INTO employee(NAME,deptName) VALUES('王五','软件开发部');

INSERT INTO employee(NAME,deptName) VALUES('陈六','软件开发部');

 

-- 问题:每次插入员工数据时,部门名称数据会出现重复(冗余),如果数据出现冗余,那么会浪费数据库存储空间。

-- 如何解决部门名称数据冗余的问题? 这时就可以设计一张独立的 部门表,把部门名称放到部门表中。

 

-- 员工表

CREATE TABLE employee(

id INT PRIMARY KEY AUTO_INCREMENT,

NAME VARCHAR(20),

deptId INT

)

 

-- 部门表

CREATE TABLE dept(

id INT PRIMARY KEY AUTO_INCREMENT,

NAME VARCHAR(20)

)

 

SELECT * FROM employee;

SELECT * FROM dept;

 

INSERT INTO dept(NAME) VALUES('软件开发部');

INSERT INTO dept(NAME) VALUES('软件维护部');

INSERT INTO employee(NAME,deptId) VALUES('陈六',1);

INSERT INTO employee(NAME,deptId) VALUES('王五',1);

 

INSERT INTO employee(NAME,deptId) VALUES('张三',3); -- 问题:在插入员工表的部门id的时候,插入了不存在的部门id,如何防止这种非法数据的插入,这时就添加外键约束了。

 

-- 添加外键约束(foreign key)

-- 需求:deptId字段值来自于dept表的id字段的值,这时可以给deptId字段添加外键约束。

-- 员工表(副表: 被别的表约束。外键设置在副表)

CREATE TABLE employee(

id INT PRIMARY KEY AUTO_INCREMENT,

NAME VARCHAR(20),

deptId INT,

CONSTRAINT employee_dept_fk FOREIGN KEY(deptId) REFERENCES dept(id)

--          外键名称                     外键字段  参考          

)

 

-- 部门表(主表:约束别人的表)

CREATE TABLE dept(

id INT PRIMARY KEY AUTO_INCREMENT,

NAME VARCHAR(20)

)

 

SELECT * FROM employee;

SELECT * FROM dept;

 

INSERT INTO employee(NAME,deptId) VALUES('陈六',1);

INSERT INTO employee(NAME,deptId) VALUES('王五',1);

-- 插入数据

INSERT INTO employee(NAME,deptId) VALUES('张三',3); -- 违反外键约束:a foreign key constraint fails

-- 修改数据

UPDATE employee SET deptId=5 WHERE id=2; -- a foreign key constraint fails

-- 删除数据

DELETE FROM dept WHERE id=1; -- a foreign key constraint fails

 

-- 外键约束在什么情况下,会其作用?

-- 插入数据:当往副表插入了主表不存在的数据时,外键起作用

-- 修改数据:当往副表修改为主表不存在的数据时,外键起作用

-- 删除数据: 副表中有关联主表的数据的时候,当删除主表数据,外键其作用

 

-- 当有了外键之后,应该如何管理数据呢?

-- 插入数据: 先插入主表的数据,再插入副表数据

-- 修改数据: 先修改主表数据,再修改副表数据

UPDATE employee SET deptId=3 WHERE id=5;

UPDATE dept SET id=3 WHERE id=2;

-- 删除数据:先删除副表数据,再删除主表数据

DELETE FROM dept WHERE id=3;

DELETE FROM employee WHERE deptId=3;

 

1.8 级联技术

级联: 当有了外键的时候,我们希望修改或删除数据的时候,修改或删除了主表的数据,同时能够影响副表的数据,这时就可以使用级联。

 

CREATE TABLE employee(

id INT PRIMARY KEY AUTO_INCREMENT,

NAME VARCHAR(20),

deptId INT,

-- 添加级联修改: ON UPDATE CASCADE

-- 添加级联删除: ON DELETE CASCADE

CONSTRAINT employee_dept_fk FOREIGN KEY(deptId) REFERENCES dept(id) ON UPDATE CASCADE ON DELETE CASCADE

--          外键名称                     外键字段  参考          

)

 

2 数据库设计

2.1 引入

需求分析: 原始需求 -> 业务需求

客户 业务模型:客户(姓名   登记时间 邮箱  微信号 )

需求设计:

业务模型(客户业务模型): -》 抽取实体模型: class Customer{name email weixin}  

业务模型(客户业务模型) ->  数据模型:设计数据库表(customer表: 字段)

 

2.2 数据库设计的三大范式

第一范式: 要求表的每个字段必须独立的不可分割的单元

 

学生表: student    name             --违反第一范式

 张三|狗娃

 王含|张小含

 

查询: 现用名中包含‘张’的学生

select * from student where name like '%张%';

 

 

学生表: student  name   old_name             --符合第一范式

 张三      狗娃

 王含      张小含

 

第二范式: 在第一范式的基础上,要求表的除主键以外的字段都和主键有依赖关系的。

一张表应该只表达一个意思!!!!

 

员工表:employee

员工编号  员工姓名  部门名称   订单名称      --违反第二范式

 

员工表:employee

员工编号  员工姓名  部门名称        --符合第二范式

 

订单表:

订单编号  订单名称

 

第三范式: 在第二范式基础上,要求表的除主键外的字段都只能和主键有直接决定的依赖关系。

 

 

员工表:employee                                  --不符合第三范式(出现数据冗余)

员工编号  员工姓名  部门编号 部门名称

1       张三         1    软件开发部

2       李四 1     软件开发部

 

员工表:employee                                  --符合第三范式(降低数据冗余)

员工编号  员工姓名  部门编号 

1       张三         1    

2       李四  1    

部门表: dept

部门编号  部门名称

1    软件开发部

 

数据库存储空间  和 数据查询效率

3 多表查询

 

-- 1.1 交叉连接查询(笛卡尔乘积: 4*3=12,产生笛卡尔积的原因是没有足够的连接条件)

-- 需求: 员工及其部门

SELECT employee.name,dept.name FROM employee,dept;

 

-- 多表查询的步骤: 1)确定查询哪些表  2)确定查询哪些字段  3)确定连接条件(规则: 表数量-1)

-- 内连接效果:只有满足连接条件的数据才会显示出来

-- 1.2 内连接查询(使用最多)

SELECT e.name,d.name

FROM employee e,dept d

WHERE e.deptId=d.id;

 

-- 另一种语法

SELECT e.name,d.name

FROM employee e

INNER JOIN dept d

ON e.deptId=d.id;

 

-- 1.3 左外连接查询(其次)

-- 需求: 查询部门及其部门的员工(部门全部显示)

-- 左外连接查询效果: 左表(部门表)的数据全部显示,右表(员工)的数据当满足连接条件的时候,

         -- 就显示满足条件的的数据,但是如果不满足连接条件,则显示null

-- 预期结果:

-- 软件开发部  张三

-- 软件开发部  王五

-- 软件维护部  李四

-- 软件维护部  陈六

-- 秘书部      null

SELECT d.name,e.name

FROM dept d

LEFT OUTER JOIN employee e

ON d.id=e.deptId;

 

-- 1.4 右外连接查询

-- 右外连接查询效果: 右表(部门表)的数据全部显示,左表(员工)的数据当满足连接条件的时候,

         -- 就显示满足条件的数据,但是如果不满足连接条件,则显示null

SELECT d.name,e.name

FROM employee e

RIGHT OUTER JOIN dept d

ON d.id=e.deptId;      

      

         

-- 1.5 自连接查询

-- 需求: 查询员工姓名及其上司姓名(没有上司的员工也显示)

-- 预期结果:

           员工    上司

-- 张三   null

-- 李四   张三

-- 王五   李四

-- 陈六   王五

SELECT e.name AS '员工',b.name AS '上司'

FROM employee e

LEFT OUTER JOIN employee b

ON e.bossId=b.id;

 

4 mysql存储过程

4.1 引入

存储过程,其实就是带逻辑的(多个)sql语句。也是sql编程。

4.2 存储过程的特点

1)存储过程保存到数据库服务器端,通过数据库客户端工具调用存储过程

2)存储过程的效率会非常高!因为存储过程是在数据库服务器端执行。

3)存储过程的移植性非常差的!

4.3 存储过程语法

 

创建存储过程

-- 定义结束符号

DELIMITER 结束符号

CREATE PROCEDURE 存储过程名称 (形式参数列表)

BEGIN

多个sql语句

END 结束符号

 

-- 调用存储过程

CALL 存储过程名称(实际参数列表);

 

参数类型:

IN: 输入参数,可以携带数据到存储过程中

OUT: 输出参数,可以携带数据到存储过程外面。

INOUT: 输入输出参数。

 

 

-- 3.1 带有输入参数的存储过程

-- 需求: 传入员工id查询对应的员工

DELIMITER $

CREATE PROCEDURE pro_testByIn(IN eid INT)  -- 参数类型(IN) 参数名称 数据类型(int)

BEGIN

SELECT * FROM employee WHERE id=eid;

END $

 

-- 调用

CALL pro_testByIn(2);

 

-- 3.2 带有输出参数的存储过程

DELIMITER $

CREATE PROCEDURE pro_testByOut(OUT n VARCHAR(20))

BEGIN

-- 修改变量n

SET n = '输出参数';

END $

 

-- 问题: 如何接收存储过程的输出参数???

-- 定义变量去接收输出参数数据。

 

-- mysql数据库三种变量:

-- 1)全局变量。mysql内置的变量,mysql程序关闭的时候全局变量才会失效!!

-- character_set_client: mysql接收的客户端的数据编码

-- character_set_results: mysql使用什么编码输出给客户端数据

        -- 查看某个全局变量: select @@变量名

        -- 修改某个全局变量: set @@变量名=值

-- 2) 会话变量。变量只在某次登录的会话中有效!退出连接,会话变量数据失效!!   

-- 查看某个会话变量: select @变量名

        -- 修改/定义某个会话变量: set @变量名=值

-- 3) 局部变量:在存储过程中定义的变量。存储过程结束局部变量失效!!

-- 查看某个局部变量: select 变量名

        -- 修改某个局部变量: set 变量名=值

        -- 定义某个局部变量: declare 变量名 数据类型;

        

-- 定义会话变量去接收输出参数数据         

-- set @n='eric';

CALL pro_testByOut(@n);

-- 查看会话变量n

SELECT @n;

 

-- 3.3 带有输入输出参数的存储过程

DELIMITER $

CREATE PROCEDURE pro_testByInOut(INOUT n VARCHAR(20))

BEGIN

-- 查看n变量

SELECT n;

-- 修改n变量

SET n = '500';

END $

 

-- 定义会话变量调用存储过程

SET @n='100';

CALL pro_testByInOut(@n);

-- 查看n

SELECT @n;

 

-- 3.4 带有判断条件的存储过程

-- 需求: 输入一个num整数,num=1 ,输出‘星期一’,num=2,输出‘星期二’,num=3,输出‘星期三’,否则,输出‘错误参数’

DELIMITER $

CREATE PROCEDURE pro_testByIf(IN num INT,OUT str VARCHAR(20))

BEGIN

IF num=1 THEN

SET str = '星期一';

ELSEIF num= 2 THEN

SET str ='星期二';

ELSEIF num=3 THEN

SET str = '星期三';

ELSE

SET str = '错误参数';

END IF;

END $

 

CALL pro_testByIf(5,@str);

SELECT @str;

 

-- 3.5 带有循环条件的存储过程

-- 需求: 输入一个num,计算从1到num的总和。

DELIMITER $

CREATE PROCEDURE pro_testByWhile(IN num INT,OUT score INT)

BEGIN

-- int result =0;

-- for(int i=1;i<=100;i++){

-- result += i;

-- }

 

-- 定义局部变量

DECLARE i INT DEFAULT 1;

DECLARE result INT DEFAULT 0;

WHILE i<=num DO

SET result = result + i;

SET i = i+1;

END WHILE;

SET score = result;

END $

 

 

CALL pro_testByWhile(200,@score);

SELECT @score;

 

-- 3.6 携带数据库的数据给输出参数(INTO)

-- 需求: 传入员工id,查询对应的员工,输出员工姓名

DELIMITER $

CREATE PROCEDURE pro_testByData(IN eid INT,OUT sname VARCHAR(20))

BEGIN

SELECT NAME INTO sname FROM employee WHERE id=eid;

END $

 

CALL pro_testByData(2,@sname);

SELECT @sname;ss

 

5 触发器

5.1 简介

当往员工表插入/修改/删除一条数据的时候,同时往日志表记录下来,这时就要使用触发器完成。

 

总结:

1)sql基础语法(重点)

DDL: create/drop/alter

DML: insert/update/delete

DQL:  

 单表: 12种

多表:  内连接  左外连接  右外连接  自连接

 

2)数据约束(应用)

 默认值

 唯一

主键

自增长

外键+级联

 

3)存储过程(了解)

3.1 输入参数

3.2 输出参数

3.3 输入输出参数

3.4 if条件

3.5 while条件

3.6 into

 

4)数据库设计(重点)

三大范式

 

5)触发器+权限问题+备份问题

 

 

结束语:任凭花落三千,随风一笑踏前行

 

 

猜你喜欢

转载自blog.csdn.net/weixin_41987706/article/details/84848436