二阶段复杂简易整理

第一天 HTML

第一节 HTML简介

  • 文件名后缀为.html或.htm

第二节 HTML基本标签

2.1 结构标签

<html><html>:根标签         
<head></head>:头标签           
<title></title>:页面的标题        
<body></body>:主体标签:网页内容

2.2 排版标签

1.注释标签:<!--注释-->                
    2.换行标签:<br/>           
    3.段落标签:<p>文本文字</p>   
          特点:段与段之间有行高                         
          属性:align对齐方式  (left:左对齐   center:居中  right:右对齐)          
    4.水平线标签:<hr/>                      
          属性:   
              width:水平线的长度(两种:第一种:像素表示;第二种,百分比表示)                                       size: 水平线的粗细 (像素表示,例如:10px)                                 
              color:水平线的颜色                                  
              align:水平线的对齐方式(left:左对齐   center:居中  right:右对齐)    

2.3 标题标签

<h1></h1>—-<h6></h6>  
 随着数字增大文字逐渐变小,字体是加粗的,内置字号,默认占据一行;

2.4 容器标签

<div></div>:块级标签,独占一行,换行
 <span></span>:行级标签,所有内容都在同一行
         作用:   <div></div>:主要是结合css页面分块布局
                  <span></span>:进行友好提示信息

2.5 列表标签

无序列表标签: <ul></ul>
             属性:type :三个值,分别为
                  circle(空心圆) ,disc(默认,实心圆),square(黑色方块)
            列表项:<li></li>
   
   示例如下:  
        <ul type="square">无序列表
            <li>苹果</li>
            <li>香蕉</li>
            <li>橘子</li>
        </ul>
        
    有序列表标签:<ol></ol>
             属性:type:1、A、a、I、i(数字、字母、罗马数字)
             列表项: <li></li>
      示例如下:
        <ol type="I">有序列表
            <li>苹果</li>
            <li>香蕉</li>
            <li>橘子</li>
        </ol>
  • 定义列表

    dl (defination list) 定义列表

    dt (defination title) 定义标题

    dd (defination description) 定义描述

    代码示例

    定义列表   <dl>
                    <dt>苹果</dt>
                    <dd>苹果是一种水果,富含维生素C,美容养颜,吃了长寿....</dd>
               </dl>

2.6 图片标签

<img/> 独立标签   
  属性: 
      src:图片地址: 相对路径 (同一个网站)  绝对路径 (不同网站)
      width:宽度
      height:高度
      border:边框
      align:对齐方式,代表图片与相邻的文本的相当位置(有三个属性值:top middle bottom)
      alt:图片的文字说明
      title:图片的悬停显示
      hspace 和 vspace 设定图片边沿上下左右空白,以免文字或其它图片过于贴近

2.7 链接标签

<a>文本或图片</a>
属性: 
    href:跳转页面的地址(跳转到外网需要添加协议)     
    target:_self(自己)  _blank(新页面,之前页面存在)  _parent  _top  默认_self
          _search相等于给页面起一个名字,如果再次打开时,如果页面存在,则不再打开新的页面。可以是任意名字。
    name:名称,锚点(回到锚点: 顶部,底部,中间),在访问锚点的书写格式:#name的值            

2.8 表格标签

  • table、tr、td、 th

  • colspan 属性,用法先扣再填

  • rowspan属性

2.9 文本格式化标签

<b> 	定义粗体文本。
    <big> 	定义大号字。
    <em> 	定义着重文字。
    <i> 	定义斜体字。
    <small> 	定义小号字。
    <strong> 	定义加重语气。
    <sub> 	定义下标字。
    <sup> 	定义上标字。
    <ins> 	定义插入字。
    <del> 	定义删除字。

第三节 HTML表单标签

3.1form标签

常用属性:action:表示动作,值为服务器的地址,把表单的数据提交到该地址上处理         
method:请求方式:get 和post         
enctype:表示是表单提交的类型                
默认值:application/x-www-form-urlencoded  普通表单                      
multipart/form-data  多部分表单(一般用于文件上传)                      
text/plain 普通文本                            
get:       
1.数据存在地址栏中,请求参数都在地址后拼接 path?name=张三&password=123456       
2.不安全      
3.效率高      
4.get请求大小有限制,不同浏览器有不同,但是大约是2KB使用情况:一般情况用于查询数据。    
post:       
1.地址栏没有数据:请求参数单独处理。       
2.安全可靠      
3.效率低       
4.post请求大小理论上无限。使用情况:一般用于插入修改等操作        
​put deleteheader

3.2 input标签

type: 以下为type可能要取的值: 
      1.1   text 文本框  输入内容
      1.2   password  密码框   密文或者掩码
      1.3   radio 表示是单选,name必须一致;value:提交给服务器的数据
                  表示同一组中只能选中一个( checked ="checked" 表示选中)
      1.4  checkbox  表示多选 ,name必须一致,
                 表示同一组中可以选多个,返回值是个数组( checked ="checked" 表示选中)
      1.5   file :表示上传控件			    
      以上具有输入性质的必须要有name属性,初始开始写value表示是默认值(以后获取输入框的内容要根据name来取)	 
	 以下按钮不具有输入性质,不需要name属性,但是按钮上的文字提示使用value属性
      1.6 submit   提交
      1.7 reset   重置
      1.9 image   图片提交按钮
	  1.10 button 普通按钮
	  
      1.11 hidden  表示隐藏域,该框的内容服务器需要,但是不想让用户知道(不想清楚的显示在界面上)
      1.12 email  表示邮箱格式的数据
     
name属性:表单元素名字,只有name属性才能提交给服务器。   
value属性:提交给服务器的数据
placeholder:提示信息
高级属性:
	disabled:禁用
	readonly:只读

3.3 select元素

<select name="city">   <!--select标签添加该属性multiple="multiple"表示多选 、size表示显示的个数--> 
     <!--option表示下拉列表项-->
	<option value="北京">北京</option> 
     <!--selected="selected"表示选中该项-->
	<option value="上海" selected="selected">上海</option>
	<option value="广州">广州</option>
	<option value="杭州">杭州</option>
</select>

3.4 textarea 元素

<textarea cols="100" rows="5">  表示5行100列的区域可以输入内容,该元素没有value属性

3.5 示例综合代码--注册

<form action="" method="get">
			<table align="center">
				<caption>
					<h1>注册</h1></caption>
				<tr>
					<td align="right">用户名:</td>
					<td><input type="text" name="username" value="bluesky" /></td>
				</tr>
				<tr>
					<td align="right">密码:</td>
					<td><input type="password" name="password" /></td>
				</tr>
				<tr>
					<td align="right">确认密码:</td>
					<td><input type="password" name="confirmpwd" /></td>
				</tr>
				<tr>
					<td align="right">性别:</td>
					<td>
						<input type="radio" name="sex" value="男" />男
						<input type="radio" name="sex" value="女" checked="checked" />女
					</td>
				</tr>
				<tr>
					<td align="right">爱好:</td>
					<td>
						<input type="checkbox" name="hobby" value="篮球" checked="checked" />篮球
						<input type="checkbox" name="hobby" value="足球 " />足球
						<input type="checkbox" name="hobby" value="乒乓球 " />乒乓球
						<input type="checkbox" name="hobby" value="羽毛球 " />羽毛球
					</td>
				</tr>
				</tr>
				<tr>
					<td align="right">上传头像:</td>
					<td>
						<input type="file" name="upload" />
					</td>
				</tr>
				</tr>
				<tr>
					<td align="right">居住地:</td>
					<td>
						<select name="city">
							<option value="北京">北京</option>
							<option value="上海" selected="selected">上海</option>
							<option value="广州">广州</option>
							<option value="杭州">杭州</option>
						</select>
					</td>
				</tr>
				</tr>
				<tr>
					<td align="right">个人介绍:</td>
					<td>
						<textarea cols="100" rows="5">
			     </textarea>
					</td>
				</tr>
				</tr>
				<tr>
					<td></td>
					<td align="center">
						<input type="submit" value="注册" />
						<input type="reset" value="重置" />
					</td>
				</tr>
			</table>
</form>

第五节 HTML框架标签

5.1 frameset

示例代码

  • top.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
    
    </head>
    <body bgcolor="red">
    <h1>HTML的框架标签</h1>
    </body>
    </html>
  • left.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
    </head>
    <body bgcolor="#FFA600">
    <a href="http://www.qfedu.com">千锋官网</a><br/>
    <a href="http://www.qfedu.com">JAVA官网</a><br/>
    <a href="http://www.qfedu.com">JAVA在线</a><br/>
    </body>
    </html>
  • right.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body bgcolor="#00FFFF">
    <h1>正文内容</h1>
    </body>
    </html>
  • content.html

    <!--1.框架标签不能和body同时出现
    	2.frameset: border去除框架标签的框 ,示例:border="0"
    			         border="10px" bordercolor="yellow"
    	3.frame框大小不变:两种情况: 
    		   第一种:border ="0"
    		   第二种: noresize="noresize"  不改变大小
    	 备注:scrolling是否显示滚动条
    			    yes  显示
    			    no   不显示
    			    auto  如果内容高度超过屏幕高度直接显示滚动,  
    	4. frame 是框,内容使用src来填充,
    			 定位显示到指定位置:  使用name属性
    		例如:
    			点击left.html的标签跳转内容显示在right.html		    
    			 1.给right.html的frame添加name属性,方便定位。
    			 2.在left.html中使用target目标定位,根据name名查找
    		-->
    	<frameset rows="200,*" border="10px" bordercolor="yellow">
    		<frame src="top.html" scrolling="yes" noresize="noresize" />
    		<frameset cols="200,*">
    			<frame src="left.html" scrolling="yes" noresize="noresize" />
    			<frame src="right.html" name="content" scrolling="yes" />
    		</frameset>
    	</frameset>

第六节 HTML的其它标签和特殊字符

6.1其他标签

<!--该网页的关键字-->
		<meta name="keywords" content="keyword1,keyword2,keyword3">
		<!--该网页的描述-->
		<meta name="description" content="this is my page">
		 <!--该网页的编码-->
		<meta http-equiv="content-type" content="text/html; charset=UTF-8">  html4.01
		 <!--页面自动跳转,2秒后跳转到百度-->
		<meta http-equiv="refresh" content="2;URL=https://www.baidu.com">
		 <!--该网页的编码-->
         <meta charset="UTF-8">  html5
        <!-- href:引入css文件的地址-->
		<link rel="stylesheet" type="text/css" href="./styles.css">
		<!--src:js的文件地址-->
		<script type="text/javascript" src=""></script>

6.2特殊字符

&lt; 小于号  
        &gt; 大于号
        &amp; 与字符
        &quot; 引号 
        &reg; 己注册
        &copy; 版权
        &trade; 商标
        &nbsp; 空格	
        &emsp;制表符

小结

基本标签:

(1)结构标签 html head title body

(2)排版p br hr

(3)标题 h1-h6

(4)容器 div span

(5)列表 ul ol dl

(6) 表格 table

(7) 图片 img

(8)超链接 a

表单内容

form

action 表单提交的服务器地址

method 提交方式

enctype 编码类型

表单元素

input

type: text password radio checkbox button submit reset image file hidden email

select

textarea

框架标签

frameset

rows

cols

frame

其他标签

meta

特殊字符


第二天 CSS层叠样式表

第一节 CSS简介

  • 概念

    CSS :层叠样式表(英文全称:Cascading Style Sheets)是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言。CSS不仅可以静态地修饰网页,还可以配合各种脚本语言动态地对网页各元素进行格式化。 多个样式可以层层覆盖叠加,如果不同的css样式对同一个html标签进行修饰,样式有冲突的,应用优先级高的,不冲突的样式规则共同作用。

  • 特点

    1 丰富的样式定义 CSS提供了丰富的文档样式外观,以及设置文本和背景属性的能力;允许为任何元素创建边框,以及元素边框与其他元素间的距离,以及元素边框与元素内容间的距离;允许随意改变文本的大小写方式、修饰方式以及其他页面效果。

    2 易于使用和修改 CSS可以将样式定义在HTML元素的style属性中,也可以将其定义在HTML文档的header部分,也可以将样式声明在一个专门的CSS文件中,以供HTML页面引用。总之,CSS样式表可以将所有的样式声明统一存放,进行统一管理。 另外,可以将相同样式的元素进行归类,使用同一个样式进行定义,也可以将某个样式应用到所有同名的HTML标签中,也可以将一个CSS样式指定到某个页面元素中。如果要修改样式,我们只需要在样式列表中找到相应的样式声明进行修改。

    3 多页面应用 CSS样式表可以单独存放在一个CSS文件中,这样我们就可以在多个页面中使用同一个CSS样式表。CSS样式表理论上不属于任何页面文件,在任何页面文件中都可以将其引用。这样就可以实现多个页面风格的统一。

    4 层叠 简单的说,层叠就是对一个元素多次设置同一个样式,这将使用最后一次设置的属性值。例如对一个站点中的多个页面使用了同一套CSS样式表,而某些页面中的某些元素想使用其他样式,就可以针对这些样式单独定义一个样式表应用到页面中。这些后来定义的样式将对前面的样式设置进行重写,在浏览器中看到的将是最后面设置的样式效果。

    5 页面压缩 在使用HTML定义页面效果的网站中,往往需要大量或重复的表格和font元素形成各种规格的文字样式,这样做的后果就是会产生大量的HTML标签,从而使页面文件的大小增加。而将样式的声明单独放到CSS样式表中,可以大大的减小页面的体积,这样在加载页面时使用的时间也会大大的减少。另外,CSS样式表的复用更大程序的缩减了页面的体积,减少下载的时间

第二节 CSS使用方式

  • 内联方式

    把CSS样式嵌入到html标签当中,类似属性的用法,示例如下:

    <div style="color:blue;font-size:50px">This is my HTML page. </div>

    好处:可以单独设置某个元素样式,缺点:不利于样式重用

  • 内部方式

    在head标签中使用style标签引入css,示例如下:
           <style type=“text/css”> //告诉浏览器使用css解析器去解析
                div {color:red; font-size:50px}
           </style>
    好处:可以控制页面中多个元素样式,缺点:只能一个页面使用
  • 外部方式

    将css样式抽成一个单独文件,谁用谁就引用,好处:多个页面可以同时使用。
     示例如下:
           单独文件div.css:  内容示例:div{color:green;font-size:50px}
           引用语句写在head标签内部,
           
     链接式:      
    <link rel="stylesheet" type="text/css" href=“div.css"></link>
          rel:代表当前页面与href所指定文档的关系
          type:文件类型,告诉浏览器使用css解析器去解析
          href:css文件地址
          
     导入式:
     
      <style type="text/css">
           @import url("div.css")
      </style>
     该内容放在head标签中
     
     备注:link和@import区别:
               1.link所有浏览器都支持,@import某些版本低的IE不支持
               2.@import是等待html加载完成才加载,link解析到这个语句,就加载
               3.@import不支持js动态修改
  • 优先级 内联样式>内部样式>外部样式,就近原则

第三节 CSS选择器

3.1 基本选择器

  • 标签选择器

  • id选择器

  • class选择器

3.2 属性选择器

格式为:html标签[属性='属性值']{css属性:css属性值;}
    或者html标签[属性]{css属性:css属性值;}, 
具体示例如下:
body内容:
     <form name="login" action="#" method="get">
		<font size="3">用户名:<font> 
         <input type=“text" name="username" value="zhangsan" /> </br>
      密码: <input type="password" name="password" value="123456" /> </br>
            <input   type="submit" value="登录"></input>
	</form>

 head中书写:
<style type="text/css">
        input[type='text'] {
            background-color: pink
        }
        input[type='password'] {
            background-color: yellow
        }
        font[size] {
            color: green
        }
        a[href] {
            color: blue;
        }
</style>

3.3 伪元素选择器

语法:
              静止状态 a:link{css属性}
              悬浮状态 a:hover{css属性}
              触发状态 a:active{css属性}
              完成状态 a:visited{css属性}
具体示例如下:
   <a href="https://hao.360.cn/">点我吧</a>
<style type="text/css">
			<!--静止状态 -->
			a:link {color: red;}
			<!--悬浮状态 -->
			a:hover {color: green;}
			<!--触发状态 -->
			a:active {color: yellow;}
			<!--完成状态 -->
			a:visited {color: blue;}
</style>

3.4 层级选择器

后代选择器

div p{...} 表示div中的p标签,所有的p,后代

div span{....} 表示div中的span标签,包括所有的span,后代

子代选择器

div>span{....} 表示 div中有一个span, span是子代

相邻兄弟 +

通用兄弟 ~

<div id="div1">
			<div class="div11">
				<span>span1-1</span>
			</div>
			<div class="div12">
				<span>span1-2</span>
			</div>
 </div>
		<div class="div2">
			<div id="div22">
				<span>span2-1</span>
			</div>
			<div id="div23">
				<span>span2-2</span>
			</div>
		</div>

		<style type="text/css">
			#div1 .div11{color:red;}
			#div1 .div12{color:purple;}
			.div2 #div22{color:green;}
			.div2 #div23{color:blue;}
		</style>

3.5 其他选择器

  • 全局选择器

  • 群组选择器

第四节 CSS属性

  • 文字属性

    font-weight 属性设置文本的粗细。关键字 100 ~ 900 为字体指定了 9 级加粗度。 100 对应最细的字体变形,900 对应最粗的字体变形。 数字 400 等价于 normal,而 700 等价于 bold。

    斜体(italic)是对每个字母的结构有一些小改动,来反映变化的外观。 倾斜(oblique)文本则是正常竖直文本的一个倾斜版本。

    简写: font: italic bold 30px "幼圆","黑体"; /style weight size family swsf/

  • 文本属性

    text-indent:缩进元素中文本的首行,取值类型如下: text-indent:5em;表示此段落第一行缩进5个字符的宽度 text-indent:20%:表示此段落第一行缩进父容器宽度的百分之二十

  • 背景属性

    /简写 没有顺序/ background: red center no-repeat url(img/003.jpg);

  • 列表属性

    list-style-type:decimal;改变列表的标志类型
    list-style-image: url("images/dog.gif");用图像表示标志
    list-style-position: inside;确定标志出现在列表项内容之外还是内容内部 
    
    简写
    list-style: decimal url(img/001.png) inside;
    去掉样式:
    list-style:none;
    list-style-type:none;
  • 尺寸显示轮廓属性

    width:设置元素的宽度
    height:设置元素的高度
    显示属性(display)
    display: none 不显示
    		block:块级显示
    		inline:行级显示
    		inline-block:行级块
    轮廓(outline)
    	绘制于元素周围的一条线,位于边框边缘的外围,可起到突出元素的作用。常用属性:
    outline-style:solid(实线)/dotted(虚线)/dashed(虚线,虚线的每段较长)/double(框为空心);设置轮廓的样outline-color:red;设置轮廓的颜色
    outline-width:10px设置轮廓的宽度
  • 浮动属性

    浮动:简单理解---飘起来了

    clear 属性

    规定元素的哪一侧不允许其他浮动元素。

  • 定位属性

    postion: static(默认) | relative| absolute| fixed

第五节 CSS盒子模型

5.1 边框属性

border-style:边框样式,值有以下情况:
				solid:实线
				double:空心线
				dashed:虚线组成的边框
				dotted:圆点组成的边框
border-color:边框颜色
border-width:边框宽度
简写
border: 1px solid red;

5.2 外边距属性

margin:外间距,边框和边框外层的元素的距离
margin:四个方向的距离(top right bottom left)

5.3 内边距属性

padding:内间距,元素内容和边框之间的距离((top right bottom left))
  • div水平居中显示

    margin: 0 auto;  /*0  上下 0  左右 auto*/
  • div垂直居中显示

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style type="text/css">
			#box{
				height: 300px;
				background-color:#FFC0CB;
              	 /*弹性盒子*/
				display: flex;
              	 /*垂直对齐*/
				align-items: center;
              	 /*水平对齐*/
				justify-content: center;
			}
			#div1,#div2{
				width: 100px;
				height: 100px;
			}
			#div1{
				background-color: #6495ED;
			}
			#div2{
				background-color: #7FFFD4;
			}
		</style>
	</head>
	<body>
		<div id="box">
			<div id="div1">第一个div</div>
			<div id="div2">第二个div</div>
		</div>
	</body>
</html>
注意,设为 Flex 布局以后,子元素的float、clear和vertical-align属性将失效。

第六节 CSS3扩展属性

6.1 border-radius

圆角属性

6.2 box-shadow

用于向方框添加阴影

6.3 background-size

属性规定背景图片的尺寸

6.4 background-image

为指定元素使用多个背景图像

6.5 text-shadow

可向文本应用阴影


第三天 JS基础使用

第一节JS概述

  • 简介

    JavaScript(LiveScript)一种解释性脚本语言,是一种动态类型、弱类型、基于原型继承的语言,内置支持类型。它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML(标准通用标记语言下的一个应用)网页上使用,用来给HTML网页增加动态功能。

第二节 JS基本语法

2.1 数据类型

  • 基本(原始)类型

    number、string、boolean、undefined、null五种

  • 引用(对象)类型

    Number String Boolean Object Array

2.2 JavaScript的三种使用方式

  • 第一种方式:在<script>标签中,script可以放在网页中任何位置。

    <script type="text/javascript">
      	var num=10;
    	var d=new Date();
    	document.write(num);
    </script>
  • 第二种方式:使用外部JavaScript文件,把js代码放入单独的文件中 ,这个文件的扩展名.js

    <script type="text/javascript" src="js/myjs.js"></script>
  • 第三种方式: 放在标签中的事件属性中,常见事件 ,onclick

    <input type="button" value="你点我啊" οnclick="alert('你点我干嘛')" />

2.3 JS运算符

  • == 自动转型比较数值

  • ===直接比较地址

 

第三节 JS函数和事件

3.1 函数定义

function functionName(parameters){
    //执行的代码
}

3.2 匿名函数

/*匿名函数*/
var method1=function(){
document.write("这是一个匿名函数");
}

method1();
/*匿名函数(自执行匿名函数)*/
(function(s){
document.write("这是一个自执行匿名函数"+s);
})("hahaha");

3.3 闭包

闭包就是能够读取其他函数内部局部变量的函数; 闭包可以理解成“定义在一个函数内部的函数“。

闭包三个条件:

1 闭包是一个内部函数

2 闭包能够读取其他(外部)函数的局部变量

3 闭包和局部变量在同一个作用域。

使用形式:1 闭包作为函数的返回值;2闭包作为函数的参数。

案例:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>闭包 closure</title>
		<script type="text/javascript">
			/*定义一个函数*/
			function  a(){
				var a=10;
				document.write(a);
				document.write("<br/>");
			}
			
//			a();
//			a();
//			a();
			
			
			function b(){
				var num=10;//没有释放
				/*函数包含函数*/
				function c(){
					num++;
					document.write(num);
					document.write("<br />")
				}
				return c;
			}
			
			var f=b();//f是一个函数:闭包
			f();
			f();
			f();
          	
	
		</script>
	</head>
	<body>
		
	</body>
</html>

好处:1 使局部变量常驻内存,2 避免污染全局变量 3 .提高封装性保护局部变量

3.4 系统函数

  • 提示框 alert();

  • 确认框 confirm();

  • 输入框 prompt();

  • 字符串转换整数 parseInt();

  • 字符串转成小数 parseFloat();

  • 判断数字是不是不是一个数字 isNaN();

3.5 事件

事件描述
onchangeHTML 元素内容改变(离开光标触发)
onclick用户点击 HTML 元素
onmouseover光标移动到HTML元素
onmouseout光标离开HTML元素
onkeydown用户按下键盘按键
onload浏览器已完成页面的加载

3.6 字符串、正则表达式

  • 字符串常用函数演示

    var str="hello,我爱java";//原始类型
    var str2=new String("hello");//引用类型对象类型
    var str3=String("hello");//原始类型
    document.write(str==str2);
    document.write("<br/>");
    document.write(str===str2);
    document.write("<br/>");
    document.write(typeof(str2));
    document.write("<br/>");
    //document.write(str instanceof String);
    
    document.write("长度:"+str.length);
    document.write("<br/>");
    document.write("指定位置的字符:"+str.charAt(0));
    document.write("<br/>");
    document.write("indexOf:"+str.indexOf("java"));
    document.write("<br/>");
    var ss=str.split(",");
    document.write(ss.length);
    document.write("<br/>");
    var s1=str.substr(6,6);
    document.write(s1);
    var s2=str.substring(6,12);
    document.write(s2);
  • RegExp 对象

    语法:

    var patt=new RegExp(pattern,modifiers);

    或者更简单的方式:

    var patt=/pattern/modifiers;

    修饰符

    修饰符描述
    i执行对大小写不敏感的匹配。
    g执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。
    m执行多行匹配。

    元字符

    元字符描述
    .查找单个字符,除了换行和行结束符。
    \w查找单词字符。[a-zA-Z0-9_]
    \W查找非单词字符。
    \d查找数字。[0-9]
    \D查找非数字字符。
    \s查找空白字符。
    \S查找非空白字符。
    \b匹配单词边界。

    量词

    量词描述
    n+匹配任何包含至少一个 n 的字符串。例如,/a+/ 匹配 "candy" 中的 "a","caaaaaaandy" 中所有的 "a"
    n*匹配任何包含零个或多个 n 的字符串。例如,/bo*/ 匹配 "A ghost booooed" 中的 "boooo","A bird warbled" 中的 "b",但是不匹配 "A goat grunted"。
    n?匹配任何包含零个或一个 n 的字符串。例如,/e?le?/ 匹配 "angel" 中的 "el","angle" 中的 "le"。
    n{X}匹配包含 X 个 n 的序列的字符串。例如,/a{2}/ 不匹配 "candy," 中的 "a",但是匹配 "caandy," 中的两个 "a",且匹配 "caaandy." 中的前两个 "a"。
    n{X,}X 是一个正整数。前面的模式 n 连续出现至少 X 次时匹配。例如,/a{2,}/ 不匹配 "candy" 中的 "a",但是匹配 "caandy" 和 "caaaaaaandy." 中所有的 "a"。
    n{X,Y}X 和 Y 为正整数。前面的模式 n 连续出现至少 X 次,至多 Y 次时匹配。例如,/a{1,3}/ 不匹配 "cndy",匹配 "candy," 中的 "a","caandy," 中的两个 "a",匹配 "caaaaaaandy" 中的前面三个 "a"。注意,当匹配 "caaaaaaandy" 时,即使原始字符串拥有更多的 "a",匹配项也是 "aaa"。
    n$匹配任何结尾为 n 的字符串。
    ^n匹配任何开头为 n 的字符串。

    RegExp 对象方法

    方法描述
    exec检索字符串中指定的值。返回找到的值,并确定其位置。
    test检索字符串中指定的值。返回 true 或 false。

    支持正则表达式的 String 对象的方法

    方法描述
    match找到一个或多个正则表达式的匹配。
    replace替换与正则表达式匹配的子串。
    split把字符串分割为字符串数组。

     

小结

(1)javascript是一门脚本语言,动态添加,弱类型语言。

(2)定义变量

​ var

(3)javascript包括基本(原始)类型,引用(对象)类型

​ 原始类型:number boolean string undefined null

​ 引用类型:Object (Person)、Array

(4)运算符

(5)选择(if(条件))、循环

(6)函数和事件

​ 自定义函数

​ 匿名函数

​ 系统函数

​ 事件: onchange onclick onmouseover onmouseout onkeydown onload

(7)字符串(记住)

(8)正则表达式


第四天 JS的DOM和BOM

第一节 DOM

1.1 概述

  • 通过 HTML DOM,使用 JavaScript访问 HTML 文档的所有元素。

当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model)。

  • JS DOM能力

    1. JavaScript 能够改变页面中的所有 HTML 元素。

    2. JavaScript 能够改变页面中的所有 HTML 属性。

    3. JavaScript 能够改变页面中的所有 CSS 样式。

    4. JavaScript 能够对页面中的所有事件做出反应。

1.2 获取HTML元素

  1. id找到HTML元素

    var x=document.getElementById("intro");
  2. 标签名找到 HTML 元素

    var x=document.getElementById("main");
    var y=x.getElementsByTagName("p");
  3. 类名找到HTML 元素

    var x=document.getElementsByClassName("intro");

    1.3 修改HTML

  4. 改变HTML内容

    <html>
    <body>
    <p id="p1">Hello World!</p>
    <script>
    document.getElementById("p1").innerHTML="abcd";
    </script>
    </body>
    </html>
  5. 改变html属性

    <!DOCTYPE html>
    <html>
    <body>
    <img id="image" src="1.gif">
    <script>
    document.getElementById("image").src="2.jpg";
    </script>
    </body>
    </html>
  6. 修改CSS样式

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    </head>
    <body>
    <p id="p1">Hello World!</p>
    <p id="p2">Hello World!</p>
    <script>
    document.getElementById("p2").style.color="blue";
    document.getElementById("p2").style.fontFamily="Arial";
    document.getElementById("p2").style.fontSize="larger";
    </script>
    <p>以上段落通过脚本修改。</p>
    </body>
    </html>
  7. 元素操作

    <div id="div1">
    <p id="p1">这是一个段落。</p>
    <p id="p2">这是另一个段落。</p>
    </div>
    ​
    <script>
    var para=document.createElement("p");
    var node=document.createTextNode("这是一个新段落。");
    para.appendChild(node);
    ​
    var element=document.getElementById("div1");
    element.appendChild(para);
    </script>
  8. 删除已有的 HTML 元素

    <div id="div1">
    <p id="p1">这是一个段落。</p>
    <p id="p2">这是另一个段落。</p>
    </div>
    <script>
    var parent=document.getElementById("div1");
    var child=document.getElementById("p1");
    parent.removeChild(child);
    </script>
  9. DOM事件

    <!DOCTYPE html>
    <html>
    <body>
    ​
    <h1 id="id1">myH1</h1>
    <button type="button" 
    οnclick="document.getElementById('id1').style.color='red'">
    button</button>
    ​
    </body>
    </html>
  10. 杂烩

    <script>
    document.getElementById("myBtn").οnclick=function(){
        document.getElementById("myhead2").style.color='blue';
    };
    </script>
    <body οnlοad="alert('页面加载完毕')">
    <input type="text" id="fname" οnchange="upperCase()">
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    </head>
    <body>
    <div οnmοuseοver="mOver(this)" οnmοuseοut="mOut(this)" style="background-color:#D94A38;width:120px;height:20px;padding:40px;">Mouse Over Me</div>
    <script>
    function mOver(obj){
        obj.innerHTML="Thank You"
    }
    function mOut(obj){
        obj.innerHTML="Mouse Over Me"
    }
    </script>
    ​
    </body>
    </html>
  11. 1.4 EventListener

  12. addEventListener() 方法

    document.getElementById("myBtn").addEventListener("click", displayDate);
  13. addEventListener() 方法可以更简单的控制事件(冒泡与捕获)。

    第一个参数是事件的类型 (如 "click" 或 "mousedown"). 把on去掉

    第二个参数是事件触发后调用的函数。

    第三个参数是个布尔值用于描述事件是冒泡还是捕获。该参数是可选的。

    默认值为 false, 即冒泡传递,当值为 true 时, 事件使用捕获传递。

    注意:不要使用 "on" 前缀。 例如,使用 "click" ,而不是使用 "onclick"。

  14. element.addEventListener("click", myFunction);
    ​
    function myFunction() {
        alert ("Hello World!");
    }
  15. addEventListener() 方法允许向同个元素添加多个事件,且不会覆盖已存在的事件:

    element.addEventListener("click", myFunction);
    element.addEventListener("click", mySecondFunction);
  16. removeEventListener() 方法移除由 addEventListener() 方法添加的事件句柄:

    element.removeEventListener("mousemove", myFunction);
  17. 第二节 JavaScript的BOM

    2.1 window

  18. 三种方法能够确定浏览器窗口的尺寸。

    var w=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth;
    var h=window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight;

     

  19. 可用宽度,可用高度

    document.write("可用宽度: " + screen.availWidth);
    document.write("可用高度: " + screen.availHeight);
  20. 2.2 Location

    window.location 对象用于获得当前页面的地址 (URL),并把浏览器重定向到新的页面。

    window.location 对象在编写时可不使用 window 这个前缀。 一些例子:

    一些实例:

  21. location.href 属性返回当前页面的 URL。

  22. location.hostname 返回 web 主机的域名

  23. location.pathname 返回当前页面的路径和文件名

  24. location.port 返回 web 主机的端口 (80 或 443)

  25. location.protocol 返回所使用的 web 协议(http:// 或 https://)

  26. 示例代码:

     document.write(location.href);
      document.write(location.pathname);

    location.assign() 方法加载新的文档

     <html>
      <head>
      <script>
      function newDoc()
        {
        window.location.assign("http://www.baidu.com/")
        }
      </script>
      </head>
      <body>
      
      <input type="button" value="Load new document" οnclick="newDoc()">
      
      </body>
      </html>

    2.3 History

    history.back() - 与在浏览器点击后退按钮相同

    <html>
    <head>
    <script>
    function goBack()
      {
      window.history.back()
      }
    </script>
    </head>
    <body>
    ​
    <input type="button" value="Back" οnclick="goBack()">
    ​
    </body>
    </html>

    history.forward() - 与在浏览器中点击按钮向前相同

    <html>
    <head>
    <script>
    function goForward()
      {
      window.history.forward()
      }
    </script>
    </head>
    <body>
    ​
    <input type="button" value="Forward" οnclick="goForward()">
    ​
    </body>
    </html>

    2.4Navigatory

    已弃用

    <div id="example"></div>
    <script>
    txt = "<p>浏览器代号: " + navigator.appCodeName + "</p>";
    txt+= "<p>浏览器名称: " + navigator.appName + "</p>";
    txt+= "<p>浏览器版本: " + navigator.appVersion + "</p>";
    txt+= "<p>启用Cookies: " + navigator.cookieEnabled + "</p>";
    txt+= "<p>硬件平台: " + navigator.platform + "</p>";
    txt+= "<p>用户代理: " + navigator.userAgent + "</p>";
    txt+= "<p>用户代理语言: " + navigator.systemLanguage + "</p>";
    document.getElementById("example").innerHTML=txt;
    </script>

    第三节 JavaScript计时

    3.1 Date对象

    var d=new Date();
    document.write(d);
    document.write("<br/>")
    document.write("年份:"+(d.getYear()+1900));
    document.write("<br/>")
    document.write("年份:"+d.getFullYear());
    document.write("<br/>");
    document.write("月份:"+(d.getMonth()+1))
    document.write("<br/>");
    document.write("日期:"+d.getDate());
    document.write("<br/>");
    document.write("小时:"+d.getHours());
    document.write("<br/>");
    document.write("分钟:"+d.getMinutes());
    document.write("<br/>");
    document.write("秒:"+d.getSeconds());

    3.2 JavaScript计时函数

    setInterval()周期执行函数

    每三秒弹出 "hello" :

    setInterval(function(){alert("Hello")},3000);

    setInterval() 方法设置每秒钟执行一次代码,就是手表一样。

    var myVar=setInterval(function(){myTimer()},1000);
    ​
    function myTimer()
    {
    var d=new Date();
    var t=d.toLocaleTimeString();
    document.getElementById("demo").innerHTML=t;
    }

    clearInterval() 方法用于停止 setInterval() 方法执行的函数代码。

    代码:

    <p id="demo"></p>
    <button οnclick="myStopFunction()">Stop time</button>
    ​
    <script>
    var myVar=setInterval(function(){myTimer()},1000);
    function myTimer()
    {
    var d=new Date();
    var t=d.toLocaleTimeString();
    document.getElementById("demo").innerHTML=t;
    }
    function myStopFunction()
    {
    clearInterval(myVar);
    }
    </script>

    setTimeout()延迟执行函数

    异步执行

    等待3秒,然后弹出 "Hello":

    setTimeout(function(){alert("Hello")},3000);

    clearTimeout() 方法用于停止执行setTimeout()方法的函数代码。

    var myVar;
    ​
    function myFunction()
    {
    myVar=setTimeout(function(){alert("Hello")},3000);
    }
    ​
    function myStopFunction()
    {
    clearTimeout(myVar);
    }

    使用setTimeout实现周期执行

    <script type="text/javascript">
                
                var num=0;
                var id=0;
                function show(){
                    document.write(id+"好好学习<br/>");
                    num++;
                    if(num!=10){
                        id=setTimeout(show,1000);
                    }
                }
                
                id=setTimeout(show,1000);
                
            </script>

    小结

    DOM

    (1)获取网页元素

    getElementById();

    getElementsByTagName();

    getElementsByClassName();

    (2)获取或设置内容

    innerHTML

    innerText

    (3)获取或修改属性

    dom对象.src="";

    dom对象.width=""

    dom对象.setAttribute("属性名","属性值");

    (4)修改css

    dom对象.style.fontSize="";

    (5)创建或删除元素

    document.createElement();

    appendChild();

    insertBefore();

    dom对象.remove();

    dom对象.parentNode.removeChild(dom对象);

    (6)DOM事件

    html添加事件属性

    EventListenner方式添加

    事件的冒泡和捕获

    (7)BOM

    window:全局对象

    innerWidth

    innerHeight

    open();

    close();

    screen 屏幕对象

    location:地址

    history:历史记录

    navigator:导航对象

    (8)时间

    Date

    setInterval(); 周期执行函数

    setTimeOut(); 延迟执行函数

    其他

    Math

    eval


    第五天 SQL基础操作

    第一节 数据库简介

    1.1 SQL语句分类

  27. DDL(Data Definition Language):数据定义语言,用来定义数据库对象:库、表、列等。

  28. DML(Data Manipulation Language):数据操作语言,用来定义数据库记录(数据)。

  29. DCL(Data Control Language):数据控制语言,用来定义访问权限和安全级别。

  30. DQL(Data Query Language):数据查询语言,用来查询记录(数据)。

  31. 1.2 DDL操作数据库

  32. 系统默认数据库:

    • information_schema:

      information_schema数据库是MySQL自带的,它提供了访问数据库元数据的方式。什么是元数据呢?元数据是关于数据的数据,如数据库名或表名,列的数据类型,或访问权限等。
    • mysql:

      mysql:这个是mysql的核心数据库,主要负责存储数据库的用户、权限设置、关键字等mysql自己需要使用的控制和管理信息,不可以删除。
    • performance_schema:

      性能优化的数据库
    • test:

      这个是安装时候创建的一个测试数据库,和它的名字一样,是一个完全的空数据库,没有任何表,可以删除。
  33. 创建数据库

    CREATE DATABASE [IF NOT EXISTS] db_name

  34. 查看

    SHOW DATABASES;

  35. 查看前面创建的mydb2数据库的定义信息

    ShOW CREATE DATABASE mydb2;

  36. 把mydb2的字符集修改为utf8

    ALTER DATABASE mydb2 character SET utf8;

  37. 删除

    DROP DATABASE [IF EXISTS] db_name

  38. 查看当前使用的数据库

    SQL> Select database(); #没有选择数据 null

  39. 切换数据库

    USE mydb2;

  40. 退出MySQL

    quit;或exit;

  41. 1.3 DDL操作表

  42. 创建新表

    CREATE TABLE [IF NOT EXISTS] 表名(

    字段1 字段类型(长度) 约束,

    字段2 字段类型(长度) 约束,

    ...

    字段n 字段类型(长度) 约束

    ) [charset=utf8];

    SQL> CREATE TABLE IF NOT EXISTS student
    (
       id INT NOT NULL,
       name VARCHAR(50),
       age INT,
       address VARCHAR(100)
    ) CHARSET=utf8;
    或
    SQL> CREATE TABLE  IF NOT EXISTS `student`
    (
       `id` INT NOT NULL,
       `name` VARCHAR(50),
       `age` INT,
       `address` VARCHAR(100)
    ) CHARSET=utf8;

    注意:数据库名、表名、字段名可以使用反勾号` 括住,也可以不括。如果SQL关键字一般要括住。

    常用数据类型:

    • int:整型(4个字节)

    • double:浮点型(8个字节),近似值例如double(5,2)表示最多5位,其中必须有2位小数,即最大值为999.99

    • decimal:精确数值数据,最大位数可以是65例如decimal(5,2)能够存储具有五位数和两位小数的任何值,因此可以存储范围为-999.99至999.99。

    • char:固定长度字符串类型; char(10) 'aaa ' 固定10个字符,不足补空格, 长度0-255缺点:

      浪费空间,优点:查询速度快

    • varchar:可变长度字符串类型; varchar(10) 'aaa' 最多存储10个字符

      缺点:查询速度慢,优点:节省空间

    • text:大文本字符串类型;有字符编码,存储比较大的文本数据。

    • blob:Binary Large Object二进制大对象数据;可以存储图片、音频、视频

    • date:日期类型,格式为:yyyy-MM-dd;

    • time:时间类型,格式为:hh:mm:ss

    • timestamp:时间戳类型 yyyy-MM-dd hh:mm:ss 会自动赋值

    • datetime:日期时间类型 yyyy-MM-dd hh:mm:ss

    常用约束:

    • 主键约束:primary key (保证数据唯一性),不能重复,不能为null

    • 唯一约束:unique [key],不能重复,可以为null

    • 非空约束:not null

    • 默认约束:default

    • 外键约束:foreign key

    • 自动增长:auto_increment

  43. 删除现有表

    DROP TABLE table_name;

  44. 查看当前数据库中的所有表

    SHOW TABLES;

  45. 查看表的字段信息

    DESC student;

  46. 在上面学生表的基础上增加一个image列。

    ALTER TABLE student ADD image blob;

  47. 修改address列,使其长度为60。

    ALTER TABLE student MODIFY address varchar(60);

  48. 删除image列,一次只能删一列。

    ALTER TABLE student DROP image;

  49. 表名改为user。

    RENAME TABLE student TO user;

  50. 查看表的创建细节

    SHOW CREATE TABLE user;

  51. 修改表的字符集为gbk

    ALTER TABLE user CHARACTER SET gbk;

  52. 列名name修改为username

    ALTER TABLE user CHANGE name username varchar(100);

  53. 1.4 DML操作

    DML是对表中的数据进行增、删、改的操作。

    主要包括:INSERT 、UPDATE、 DELETE

    小知识:

    在mysql中,字符串类型和日期类型都要用单引号括起来。

    空值:null

  54. 插入操作:INSERT:

    INSERT INTO 表名(列名1,列名2 ...)VALUES(列值1,列值2...);

    INSERT INTO student(id,name,age,address) values (1,'zhangsan',20,'北京海淀');
    INSERT INTO student(id,name,age,address) values (4,'曹操',27,'北京海淀'),(5,'周瑜',28,'北京朝阳'),(6,'赵云',30,'北京大兴');

    小知识:

    查看数据库编码的具体信息

    Show variables like ‘character%’;

    临时更改客户端和服务器结果集的编码

    Set character_set_client=gbk;

    Set character_set_results=gbk;

    或者

    SET NAMES ‘gbk’; // client connection results

  55. 修改操作:UPDATE

    语法:UPDATE 表名 SET 列名1=列值1,列名2=列值2 ... WHERE 列名=值

  56. 删除操作:DELETE

    DELETE FROM 表名 【WHERE 列名=值】

  57. 第二节 DQL数据查询(重点)

    查询返回的结果集是一张虚拟表

    语法: SELECT 列名 FROM 表名 【WHERE --> GROUP BY-->HAVING--> ORDER BY-->LIMIT】

    有顺序

    SELECT selection_list /要查询的列名称/

    FROM table_list /要查询的表名称/

    WHERE condition /行条件/

    GROUP BY grouping_columns /对结果分组/

    HAVING condition /分组后的行条件/

    ORDER BY sorting_columns /对结果排序/

    LIMIT offset_start, row_count /结果限定/

    2.1 简单查询

  58. 查询所有列 *表示所有列

    SELECT * FROM stu;
  59. 查询指定列

    SELECT sid, sname, age FROM stu;
  60. 比较运算符**

    l =、!=、<>、<、<=、>、>=;

    l BETWEEN…AND; 含头含尾

    l IN(set);

    l IS NULL;

    关系运算符

    l AND;

    l OR;

    l NOT;

    算术运算符:

    +  -  *  /  %
  61. 模糊查询

    _ 任意一个字符

    %:任意0~n个字符

    '张%' ---》张三丰 张三 张无忌

    '李_' --->李四 李逵 李刚

    SELECT * 
    FROM stu
    WHERE sname LIKE '___';

    模糊查询必须使用LIKE关键字。其中 “”匹配任意一个字母,5个“”表示5个任意字母。

  62. 字段控制查询

    去除重复记录

    SELECT DISTINCT sal FROM emp;
    SELECT DISTINCT sal,comm FROM emp; --两个都重复才排重

    用了把NULL转换成数值0的函数IFNULL:

    SELECT *,sal+IFNULL(comm,0) FROMemp;

    给列名添加别名

    SELECT *, sal+IFNULL(comm,0) AS total FROM emp;

    给列起别名时,是可以省略AS关键字的:

    SELECT *,sal+IFNULL(comm,0)  total FROM emp;
  63. 排序

    查询所有学生记录,按年龄升序排序

    SELECT *
    FROM stu
    ORDER BY age ASC;
    ​
    SELECT *
    FROM stu
    ORDER BY age;# 默认升序

    查询所有学生记录,按年龄降序排序

    SELECT *
    FROM stu
    ORDER BY age DESC;

    查询所有雇员,按月薪降序排序,如果月薪相同时,按编号升序排序

    SELECT * FROM emp
    ORDER BY sal DESC,empno ASC;
  64. 聚合函数

    聚合函数是用来做纵向运算的函数:

    l COUNT():统计指定列不为NULL的记录行数;

    l MAX():计算指定列的最大值,如果指定列是字符串类型,那么使用字符串排序运算;

    l MIN():计算指定列的最小值,如果指定列是字符串类型,那么使用字符串排序运算;

    l SUM():计算指定列的数值和,如果指定列类型不是数值类型,那么计算结果为0;

    l AVG():计算指定列的平均值,如果指定列类型不是数值类型,那么计算结果为0;

    示例

    -- 查询emp表中记录数
    SELECT COUNT(*) AS ‘cnt’ FROM emp;
    --查询emp表中有佣金的人数:
    SELECT COUNT(*) FROM emp WHERE sal > 2500;
    --查询emp表中月薪大于2500的人数
    SELECT COUNT(*) AS cnt FROM emp WHERE sal+IFNULL(comm,0) >2500;
    --统计月薪与佣金之和大于2500元的人数:
    SELECT COUNT(*) AS cnt FROM emp WHERE sal+IFNULL(comm,0) > 2500;
    --查询有佣金的人数,以及有领导的人数:
    SELECT COUNT(comm), COUNT(mgr)FROM emp;
    --查询所有雇员月薪和:
    SELECT SUM(sal) FROM emp;
    --查询所有雇员月薪和,以及所有雇员佣金和:
    SELECT SUM(sal), SUM(comm) FROMemp;
    --查询所有雇员月薪+佣金和:
    SELECT SUM(sal+IFNULL(comm,0))FROM emp;
    -- 统计所有员工平均工资:
    SELECT AVG(sal) FROM emp;
    --查询最高工资和最低工资:
    SELECT MAX(sal), MIN(sal) FROM emp;
  65. 分组查询

    --查询每个部门的部门编号和每个部门的工资和:
    SELECT deptno, SUM(sal)
    FROM emp
    GROUP BY deptno;
    --查询每个部门的部门编号以及每个部门的人数:
    SELECT deptno,COUNT(*)
    FROM emp
    GROUP BY deptno;
    --查询每个部门的部门编号以及每个部门工资大于1500的人数:
    SELECT deptno,COUNT(*)
    FROM emp
    WHERE sal>1500
    GROUP BY deptno;
  66. HAVING子句

    --查询工资总和大于9000的部门编号以及工资和
    SELECT deptno, SUM(sal)
    FROM emp
    GROUP BY deptno
    HAVING SUM(sal) > 9000;

    注:having与where的区别:

    1.having是在分组后对数据进行过滤,where是在分组前对数据进行过滤

    2.having后面可以使用分组函数(统计函数)

    where后面不可以使用分组函数。

    where是对分组前记录的条件,如果某行记录没有满足WHERE子句的条件,那么这行记录不会参加分组;而 having是对分组后数据的约束。

  67. LIMIT限制

    --查询前5行记录,起始行从0开始
    SELECT * FROM emp LIMIT 0, 5;
    --查询10行记录,起始行从3开始
    SELECT* FROM emp LIMIT 3, 10;
    --分页查询可以5,5即从第6条数据向后走5行
  68. 小结

    1 数据库:存储数据的仓库。

    2 数据库管理系统: MySQL Oracle SQL Server DB2

    3 MySQL安装、卸载

    4 SQL语句:

    DDL 数据定义语言 创建库,创建表

    DML数据操纵语言 添加 删除 更新 insert delete udpate

    DQL 数据查询语言 select

    DCL 数据控制语言, 用户的创建 权限分配。

    5 DQL

    简单查询

    条件查询 where 运算符 = != <> > >= < <= in between and and or not + - * / %

    模糊查询 通配符 _表示一个字符 %表示任意多个字符

    字段控制 distinct 去重 合并 别名

    排序 order by

    聚合函数 count sum max min avg

    分组查询 group by having

    limit 限制查询


    第六天 MySQL约束和多表查询

    第一节 数据完整性

    作用:保证用户输入的数据保存到数据库中是正确的。

    确保数据的完整性 = 在创建表时给表中添加约束

  69. 实体完整性约束

    约束类型:

    主键约束(primary key)

    唯一约束(unique)

    自动增长列(auto_increment)

  70. 主键约束(primary key)数据不能重复。不可以为null

    第一种添加方式:

    CREATE TABLE student(
        id int primary key,
        name varchar(50)
    );
    CREATE TABLE student(
        id int,
        name varchar(50),
        primary key(id)
    );

    第二种添加方式:此种方式优势在于,可以创建联合主键

    CREATE TABLE student(
        classid int,
        stuid int,
        name varchar(50),
        primary key(classid,stuid)
    );

    第三种添加方式:(不推荐)

    CREATE TABLE student(
        id int,
        name varchar(50)
    );
    ALTER TABLE student  ADD  PRIMARY KEY (id);
  71. 唯一约束(unique)

    特点:数据不能重复。可以为null

    CREATE TABLE student(
        Id int primary key,
        Name varchar(50) unique
    );
  72. 自动增长列(auto_increment)

    CREATE TABLE student(
        Id int primary key auto_increment,
        Name varchar(50)
    ) auto_increment=100;
    INSERT INTO student(name) values(‘tom’);
  73. 域完整性约束

    域完整性约束的作用:限制此单元格的数据正确,不对其它单元格起作用,域代表当前单元格

    域完整性约束:数据类型、非空约束(not null)、默认值约束(default)

    check约束(mysql不支持)check(sex='男'or sex='女')

    check约束可以用enum代替

    数值类型

    类型大小范围(有符号)范围(无符号)用途
    TINYINT1 字节(-128,127)(0,255)小整数值
    SMALLINT2 字节(-32 768,32 767)(0,65 535)大整数值
    MEDIUMINT3 字节(-8 388 608,8 388 607)(0,16 777 215)大整数值
    INT或INTEGER4 字节(-2 147 483 648,2 147 483 647)(0,4 294 967 295)大整数值
    BIGINT8 字节(-9 233 372 036 854 775 808,9 223 372 036 854 775 807)(0,18 446 744 073 709 551 615)极大整数值
    FLOAT4 字节查看帮助文档查看帮助文档单精度浮点数值
    DOUBLE8 字节查看帮助文档查看帮助文档双精度浮点数值
    DOUBLE(M,D)8个字节,M表示长度,D表示小数位数同上,受M和D的约束 DUBLE(5,2) -999.99-999.99同上,受M和D的约束双精度浮点数值
    DECIMAL(M,D)对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2依赖于M和D的值,M最大值为65依赖于M和D的值,M最大值为65小数值

    日期类型:

    每个时间类型有一个有效值范围和一个"零"值,当指定不合法的MySQL不能表示的值时使用"零"值。

     

  74. 类型大小(字节)范围格式用途
    DATE31000-01-01/9999-12-31YYYY-MM-DD日期值
    TIME3'-838:59:59'/'838:59:59'HH:MM:SS时间值或持续时间
    YEAR11901/2155YYYY年份值
    DATETIME81000-01-01 00:00:00/9999-12-31 23:59:59YYYY-MM-DD HH:MM:SS混合日期和时间值
    TIMESTAMP41970-01-01 00:00:00/2038 结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07YYYYMMDD HHMMSS混合日期和时间值,时间戳

    字符串类型:

    类型大小用途
    CHAR0-255字符定长字符串 char(10) 10个字符
    VARCHAR0-65535 字节变长字符串 varchar(10) 10个字符
    TINYBLOB0-255字节不超过 255 个字符的二进制字符串
    TINYTEXT0-255字节短文本字符串
    BLOB(binary large object)0-65 535字节二进制形式的长文本数据
    TEXT0-65 535字节长文本数据
    MEDIUMBLOB0-16 777 215字节二进制形式的中等长度文本数据
    MEDIUMTEXT0-16 777 215字节中等长度文本数据
    LONGBLOB0-4 294 967 295字节二进制形式的极大文本数据
    LONGTEXT0-4 294 967 295字节极大文本数据

    CHAR和VARCHAR类型类似,但它们保存和检索的方式不同。它们的最大长度和是否尾部空格被保留等方面也不同。在存储或检索过程中不进行大小写转换。

    INARY和VARBINARY类类似于CHAR和VARCHAR,不同的是它们包含二进制字符串而不要非二进制字符串。也就是说,它们包含字节字符串而不是字符字符串。这说明它们没有字符集,并且排序和比较基于列值字节的数值值。

    BLOB是一个二进制大对象,可以容纳可变数量的数据。有4种BLOB类型:TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB。它们只是可容纳值的最大长度不同。

    有4种TEXT类型:TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT。

  75. 非空约束

    not null

  76. 默认值约束

    default

    CREATE TABLE student(
        Id int primary key,
        Name varchar(50) not null,
        Sex varchar(10) default '男'
    );
    insert intostudent1 values(1,'tom','女');
    insert intostudent1 values(2,'jerry',default);
  77. 引用完整性约束

    外键约束:FOREIGN KEY

    第一种添加外键方式。推荐

    #学生表(主表)
    CREATE TABLE student(
        sid int primary key,
        name varchar(50) not null,
        sex varchar(10) default '男'
    );
    #成绩表(从表)
    create table score(
            id int,
            score int,
            sid int , 
            CONSTRAINT fk_score_sid foreign key(sid) references student(sid)
    );
    -- 外键列的数据类型一定要与主键的类型一致

    第二种添加外键方式。

    ALTER TABLE score ADD CONSTRAINT fk_stu_score FOREIGN KEY(sid) REFERENCES student(sid);
  78. 第二节 多表查询

    多表的关系

  79. 多表的关系

    一对多关系

    多对多关系(可以通过建立新表转换成一对多关系)

    一对一关系

  80. 多表查询

    --去除重复记录
    SELECT * FROM t1 UNION SELECT * FROM t2;
    --不去除重复记录
    SELECT * FROM t1 UNION ALL SELECT * FROM t2;
    # 注意:被合并的两个结果:列数必须相同,列类型可以不同。
    # 连接查询
    # 交叉连接(笛卡儿积),有很多重复数据
    SELECT * FROM emp,dept; # 14*4=56 传统写法
    SELECT * FROM emp CROSS JOIN dept; # 标准写法
    # 内连接 两个表的位置可以交换(外键为空置拿不出数据)
    SELECT * FROM emp CROSS JOIN dept WHERE emp.deptno = dept.deptno; # 交叉连接基础上做一个判断  传统写法
    SELECT * FROM emp CROSS JOIN dept ON emp.deptno = dept.deptno; # 标准写法
    SELECT * FROM emp INNER JOIN dept ON emp.deptno = dept.deptno;
    # 外连接 连个表的位置不能交换,有主次之分
    # 左外连接(左表为主表,右表为从表)
    SELECT * FROM emp LEFT OUTER JOIN dept ON emp.deptno = dept.deptno;
    SELECT * FROM emp LEFT JOIN dept ON emp.deptno = dept.deptno; # OUTER可以省略
    SELECT * FROM emp LEFT JOIN dept ON emp.deptno = dept.deptno WHERE dept.deptno IS NULL;
    # 右外连接(右表为主表,左表为从表)
    SELECT * FROM emp RIGHT JOIN dept ON emp.deptno = dept.deptno WHERE emp.deptno IS NULL; # OUTER可以省略
    ​
    ​
    # 子查询
    SELECT sal FROM emp WHERE ename='jones';
    SELECT * FROM emp WHERE sal > 2975;
    SELECT * FROM emp WHERE sal > (SELECT sal FROM emp WHERE ename='jones');
    ​
    SELECT deptno FROM emp WHERE ename='scott';
    SELECT * FROM emp WHERE deptno=(SELECT deptno FROM emp WHERE ename='scott');
    ​
    SELECT MAX(sal) FROM emp WHERE deptno=30;
    SELECT * FROM emp WHERE sal > (SELECT MAX(sal) FROM emp WHERE deptno=30);
    ​
    SELECT * FROM emp WHERE sal > ALL (SELECT sal FROM emp WHERE deptno=30); # 大于所有的,即最高的
    ​
    SELECT * FROM emp WHERE sal > ANY (SELECT sal FROM emp WHERE deptno=30); # 大于所有的,即最低的
    ​
    SELECT * FROM (SELECT ename,job,sal FROM emp) AS temp; # 结果多行多列
    # `localhost` 只能本地账户登陆, '%'所有账户都能登陆, '10.9.21.188'只能这个地址能登陆账户
    # 创建用户
    CREATE USER `zhangsan1`@`localhost` IDENTIFIED BY '123';
    ​
    # 授权
    GRANT SELECT,UPDATE,DELETE,INSERT ON test01.* TO `zhangsan1`@`localhost`;
    ​
    # 撤销权限
    REVOKE ALL ON test01.* FROM `zhangsan1`@`localhost`;
    ​
    # 删除用户
    DROP USER `zhangsan1`@`localhost`;
    ​

    第三节 视图、存储过程、变量、函数

    3.1 视图

    概念

    视图就是一条SELECT语句执行后返回的结果集。所以我们在创建视图的时候,主要的工作就落在创建这条SQL查询语句上。

    视图特点

    视图是对若干张基本表的引用,一张虚表,查询语句执行的结果,不存储具体的数据(基本表数据发生了改变,视图也会跟着改变)视图一般不执行增删改操作。

    好处

    方便操作,特别是查询操作,减少复杂的SQL语句,增强可读性;
    更加安全,数据库授权命令不能限定到特定行和特定列,但是通过合理创建视图,可以把权限限定到行列级别;

    示例

    -- ----------------------------
    -- View structure for `view_user_course`
    -- ----------------------------
    DROP VIEW
    IF EXISTS `view_user_course`;
    ​
    CREATE VIEW `view_user_course` AS 
    (SELECT 
      `uc`.`id` AS `id`,
      `u`.`name` AS `username`,
      `c`.`name` AS `coursename` 
    FROM
      `user` `u` 
      LEFT JOIN `user_course` `uc` 
        ON `u`.`id` = `uc`.`userid` 
      LEFT JOIN `course` `c` 
        ON `uc`.`courseid` = `c`.`id`) ;
        
        
    SELECT
        vuc.username,
        vuc.coursename
    FROM
        view_user_course vuc
    WHERE
         vuc.username = '小张'

    3.2 存储过程

    简介

    存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它。
        存储过程是可编程的函数,在数据库中创建并保存,可以由SQL语句和控制结构组成。当想要在不同的应用程序或平台上执行相同的函数,或者封装特定功能时,存储过程是非常有用的。数据库中的存储过程可以看做是对编程中面向对象方法的模拟,它允许控制数据的访问方式。

    优点

    (1).增强SQL语言的功能和灵活性.
        存储过程可以用控制语句编写,有很强的灵活性,可以完成复杂的判断和较复杂的运算。
    ​
    (2).标准组件式编程.
        存储过程被创建后,可以在程序中被多次调用,而不必重新编写该存储过程的SQL语句。而且数据库专业人员可以随时对存储过程进行修改,对应用程序源代码毫无影响。
    (3).较快的执行速度.
        如果某一操作包含大量的Transaction-SQL代码或分别被多次执行,那么存储过程要比批处理的执行速度快很多。因为存储过程是预编译的。在首次运行一个存储过程时查询,优化器对其进行分析优化,并且给出最终被存储在系统表中的执行计划。而批处理的Transaction-SQL语句在每次运行时都要进行编译和优化,速度相对要慢一些。
    ​
    (4).减少网络流量.
        针对同一个数据库对象的操作(如查询、修改),如果这一操作所涉及的Transaction-SQL语句被组织进存储过程,那么当在客户计算机上调用该存储过程时,网络中传送的只是该调用语句,从而大大减少网络流量并降低了网络负载。
    (5).作为一种安全机制来充分利用.
        通过对执行某一存储过程的权限进行限制,能够实现对相应的数据的访问权限的限制,避免了非授权用户对数据的访问,保证了数据的安全。

    创建存储过程

    CREATE PROCEDURE  过程名([[IN|OUT|INOUT] 参数名 数据类型[,[IN|OUT|INOUT] 参数名 数据类型…]]) [特性 ...] 过程体

    举例

    DELIMITER //
      CREATE PROCEDURE myproc(OUT s int)
        BEGIN
          SELECT COUNT(*) INTO s FROM students;
        END
        //
    DELIMITER ;
    --"DELIMITER ;"的意为把分隔符还原为;

    参数

    IN:参数的值必须在调用存储过程时指定,在存储过程中修改该参数的值不能被返回,为默认值
    OUT:该值可在存储过程内部被改变,并可返回
    INOUT:调用时指定,并且可被改变和返回

    存储过程的删除

    DROP PROCEDURE [过程1[,过程2…]]

    示例

    --例子1 输入参数
    DELIMITER //
      CREATE PROCEDURE in_param(IN p_in int)
        BEGIN
        SELECT p_in;
        SET p_in=2;
        SELECT p_in;
        END;
        //
    DELIMITER ;
    #调用
    CALL in_param(10);
    --例子2 输出参数
    DELIMITER //
      CREATE PROCEDURE out_param(OUT p_out int)
        BEGIN
          SELECT p_out;
          SET p_out=2;
          SELECT p_out;
        END;
        //
    DELIMITER ;
    #调用
    SET @p_out=1;
    CALL out_param(@p_out);
    SELECT @p_out;
    --例子3 输入输出参数
    DELIMITER //
      CREATE PROCEDURE inout_param(INOUT p_inout int)
        BEGIN
          SELECT p_inout;
          SET p_inout=2;
          SELECT p_inout;
        END;
        //
    DELIMITER ;
    #调用
    SET @p_inout=1;
    CALL inout_param(@p_inout) ;
    SELECT @p_inout;
    --案例4  转账存储过程
    DELIMITER //
    CREATE PROCEDURE transMoney(IN fromid INT, IN toid INT, IN m DECIMAL)
    BEGIN
        UPDATE account SET money=money-m WHERE id=fromid;
        UPDATE account SET money=money+m WHERE id=toid;
    END;
    //
    DELIMITER ;
    #调用
    CALL transMoney(1,2,1000);
    --案例5 使用存储添加学生
    DELIMITER //
    CREATE PROCEDURE addStudent(IN _id INT, IN `_name` VARCHAR(10), IN _age INT,_address VARCHAR(100))
    BEGIN
        INSERT INTO student(id,NAME,age,address) VALUES(_id,_name,_age,_address);
        
    END;
    //
    DELIMITER ;
    #调用
    CALL addStudent(6,'张无忌',20,'南京');

    3.3 MySQL中的变量

  81. 局部变量

    DECLARE var_name [, var_name]... data_type [ DEFAULT value ];
    --示例1
    DELIMITER //
    CREATE PROCEDURE addNum(IN a INT, IN b INT)
    BEGIN
        DECLARE c INT DEFAULT 0;
        SET c=a+b; #赋值,必须要有SET
        SELECT c AS C;
    END;
    //
    DELIMITER ;
    #调用
    CALL addNum(10,20);
    --示例2
    DELIMITER //
    CREATE PROCEDURE queryemp()
    BEGIN
        
        DECLARE v_name VARCHAR(100);
        DECLARE v_salary DECIMAL(8,2);
     
        SELECT `name`, `salary`
        INTO v_name, v_salary
        FROM employee
        WHERE id=1;
        SELECT v_name,v_salary;
    END;
    //
    DELIMITER ;
    #调用
    CALL queryemp();
  82. 用户变量

    在客户端链接到数据库实例整个过程中用户变量都是有效的。

    示例

    set @name = '';
    select @name:=password from user limit 0,1;
  83. 会话变量

    服务器为每个连接的客户端维护一系列会话变量。在客户端连接数据库实例时,使用相应全局变量的当前值对客户端的会话变量进行初始化。设置会话变量不需要特殊权限,但客户端只能更改自己的会话变量,而不能更改其它客户端的会话变量。会话变量的作用域与用户变量一样,仅限于当前连接。当当前连接断开后,其设置的所有会话变量均失效。
    查看所有的会话变量
    SHOW  [SESSION] VARIABLES;
    查看一个会话变量也有如下三种方式:
    select @@var_name;
     
    select @@session.var_name;
     
    show session variables like "%var%";
  84. 全局变量

    全局变量影响服务器整体操作。当服务器启动时,它将所有全局变量初始化为默认值。这些默认值可以在选项文件中或在命令行中指定的选项进行更改。要想更改全局变量,必须具有SUPER权限
    查看所有的全局变量 
    show global variables; 
    要想查看一个全局变量,有如下两种方式:
    select @@global.var_name;
    show global variables like “%var%”;
  85. 3.4 函数

    存储没有返回值,使用输出参数返回数据,可以有多个,函数有返回值,只能返回一个。

    MySQL 有很多内置的函数

  86. 字符串函数

    CHARSET(str) //返回字串字符集
    ​
    CONCAT (string2 [,... ]) //连接字串
    ​
    INSTR (string ,substring ) //返回substring首次在string中出现的位置,不存在返回0
    ​
    LCASE (string2 ) //转换成小写
    ​
    LEFT (string2 ,length ) //从string2中的左边起取length个字符
    ​
    LENGTH (string ) //string长度,字节的长度
    ​
    LOAD_FILE (file_name ) //从文件读取内容
    ​
    LOCATE (substring , string [,start_position ] ) 同INSTR,但可指定开始位置
    ​
    LPAD (string ,length ,pad ) //重复用pad加在string开头,直到字串长度为length
    ​
    LTRIM (string ) //去除前端空格
    ​
    REPEAT (string2 ,count ) //重复count次
    ​
    REPLACE (str ,search_str ,replace_str ) //在str中用replace_str替换search_str
    ​
    RPAD (string ,length ,pad) //在str后用pad补充,直到长度为length
    ​
    RTRIM (string ) //去除后端空格
    ​
    STRCMP (string1 ,string2) //逐字符比较两字串大小,
    ​
    SUBSTRING (str , position [,length ]) //从str的position开始,取length个字符,
    ​
    TRIM([[BOTH|LEADING|TRAILING] [padding] FROM]string2) //去除指定位置的指定字符
    ​
    UCASE (string2 ) //转换成大写
    ​
    RIGHT(string2,length) //取string2最后length个字符
    ​
    SPACE(count) //生成count个空格
    ​
    注:mysql中处理字符串时,默认第一个字符下标为1,即参数position必须大于等于1

    数学类函数

    ABS (number2 ) //绝对值
    ​
    BIN (decimal_number) //十进制转二进制
    ​
    CEILING (number2 ) //向上取整
    ​
    CONV(number2,from_base,to_base) //进制转换
    ​
    FLOOR (number2 ) //向下取整
    ​
    FORMAT (number,decimal_places ) //保留小数位数
    ​
    POWER (number ,power ) //求指数
    ​
    RAND([seed]) //随机数
    ​
    ROUND (number [,decimals ]) //四舍五入,decimals为小数位数] 注:返回类型并非均为整数

    日期时间类

    ADDTIME (date2 ,time_interval) //将time_interval天加到date2  秒
    ​
    ADDDATE('2019-04-15',2); #2天
    ​
    CURRENT_DATE ( ) //当前日期
    ​
    CURRENT_TIME ( ) //当前时间
    ​
    CURRENT_TIMESTAMP ( ) //当前时间戳
    ​
    DATE (datetime ) //返回datetime的日期部分
    ​
    DATE_ADD (date2 , INTERVAL d_value d_type ) //在date2中加上日期或时间
    ​
    DATE_FORMAT (datetime ,FormatCodes ) //使用formatcodes格式显示datetime
    ​
    DATE_SUB (date2 , INTERVAL d_value d_type ) //在date2上减去一个时间
    ​
    DATEDIFF (date1 ,date2 ) //两个日期差
    ​
    DAY (date ) //返回日期的天
    ​
    DAYNAME (date ) //英文星期
    ​
    DAYOFWEEK (date ) //星期(1-7) ,1为星期天
    ​
    DAYOFYEAR (date ) //一年中的第几天
    ​
    EXTRACT (interval_name FROM date ) //从date中提取日期的指定部分
    ​
    MAKEDATE (year ,day ) //给出年及年中的第几天,生成日期串
    ​
    MAKETIME (hour ,minute ,second ) //生成时间串
    ​
    MONTHNAME (date ) //英文月份名
    ​
    NOW ( ) //当前时间
    ​
    SEC_TO_TIME (seconds ) //秒数转成时间
    ​
    STR_TO_DATE (string ,format ) //字串转成时间,以format格式显示
    ​
    TIMEDIFF (datetime1 ,datetime2 ) //两个时间差
    ​
    TIME_TO_SEC(time) //时间转秒数
    ​
    WEEK (date_time [,start_of_week ]) //第几周
    ​
    YEAR (datetime ) //年份
    ​
    DAYOFMONTH(datetime) //月的第几天
    ​
    HOUR(datetime) //小时
  87. 3.1 使用步骤

  88. 导入JDBC驱动包:**需要下载包含数据库编程所需的JDBC的jar包。

  89. 注册JDBC驱动程序:要求您初始化驱动程序,以便您可以打开与数据库的通信通道。

  90. 创建连接:需要使用DriverManager.getConnection()方法创建一个Connection对象,该对象表示与数据库的物理连接。

  91. 执行查询:需要使用类型为Statement的对象来构建和提交SQL语句到数据库。

  92. 从结果集中提取数据:需要使用相应的ResultSet.getXXX()方法从结果集中检索数据。

  93. 释放资源:需要明确地关闭所有数据库资源,而不依赖于JVM的垃圾收集。

  94. 3.2 注册驱动

  95. 第一种方式(推荐写法):Class.forName()

    try {
       Class.forName("com.mysql.jdbc.Driver");
    }
    catch(ClassNotFoundException ex) {
       System.out.println("Error: unable to load driver class!");
       System.exit(1);
    }
  96. 第二种方式:是使用静态DriverManager.registerDriver()方法。

    try {
       Driver myDriver = new com.mysql.jdbc.Driver();
       DriverManager.registerDriver( myDriver );
    }
    catch(ClassNotFoundException ex) {
       System.out.println("Error: unable to load driver class!");
       System.exit(1);
    }
    ​
     * 1>驱动程序注册两次
     * 2>java程序依赖mysql驱动包
  97. 3.3 获取连接

    DriverManager.getConnection()方法

    RDBMSJDBC驱动程序名称连接字符串格式
    MySQL的com.mysql.jdbc.Driverjdbc:mysql://hostname:3306 / databaseName
    ORACLEoracle.jdbc.driver.OracleDriverjdbc:oracle:thin:@ hostname:port Number:databaseName
    DB2COM.ibm.db2.jdbc.net.DB2Driverjdbc:db2:hostname:port Number / databaseName
    SYBASEcom.sybase.jdbc.SybDriverjdbc:sybase:Tds: hostname:port Number / databaseName

    创建数据库连接对象

    String URL = "jdbc:mysql://localhost:3306/emp";
    String USER = "root";
    String PASS = "root"
    Connection conn = DriverManager.getConnection(URL, USER, PASS);

    第四节 JDBC执行SQL语句

  98. Statement

    • boolean execute(String SQL)**:如果可以检索到ResultSet对象,则返回一个布尔值true; 否则返回false。使用此方法执行SQL DDL语句或需要使用真正的动态SQL时。

    • int executeUpdate(String SQL):返回受SQL语句执行影响的行数。使用此方法执行预期会影响多个行的SQL语句,例如INSERT,UPDATE或DELETE语句。

    • ResultSet executeQuery(String SQL):返回一个ResultSet对象。当您希望获得结果集时,请使用此方法,就像使用SELECT语句一样。

  99. ResultSet

    SELECT语句是从数据库中选择行并在结果集中查看行的标准方法。该java.sql.ResultSet中的接口表示结果集数据库查询。

    ResultSet对象维护指向结果集中当前行的游标。术语“结果集”是指包含在ResultSet对象中的行和列数据。

    如果没有指定任何ResultSet类型,您将自动获得一个TYPE_FORWARD_ONLY。

    类型描述
    ResultSet.TYPE_FORWARD_ONLY光标只能在结果集中向前移动。
    ResultSet.TYPE_SCROLL_INSENSITIVE光标可以向前和向后滚动,结果集对创建结果集后发生的数据库的其他更改不敏感。
    ResultSet.TYPE_SCROLL_SENSITIVE。光标可以向前和向后滚动,结果集对创建结果集之后发生的其他数据库所做的更改敏感。
    --演示案例1:查询数据
    public class JdbcDemo2 {
        public static void main(String[] args) {
            Connection connection=null;
            Statement stat=null;
            ResultSet rs=null;
            //2注册驱动
            try {
                Class.forName("com.mysql.jdbc.Driver");
                //3获取连接
                connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/school", "root", "root");
                //4创建命令(语句)对象
                stat=connection.createStatement();
                //执行命令查询
                rs=stat.executeQuery("select ename,empno from emp");
                //5处理结果
                while(rs.next()){
    //               int empno=rs.getInt(1);
    //               String empname=rs.getString(2);
                     int empno=rs.getInt("empno");
                     String empname=rs.getString("ename");
                     System.out.println(empno+"...."+empname);
                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally {
                if(rs!=null){
                    try {
                        rs.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if(stat!=null){
                    try {
                        stat.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if(connection!=null){
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    --演示案例2:添加数据
    public class JdbcDemo3 {
        public static void main(String[] args) {
            Connection connection=null;
            Statement stat=null;
            //2 注册驱动
            try {
                Class.forName("com.mysql.jdbc.Driver");
                //3打开连接
                connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/school", "root", "root");
                //4创建命令并执行
                stat=connection.createStatement();
                int result=stat.executeUpdate("insert into dept(deptno,dname,loc) values(80,'市场部','天津')");
                if(result>0){
                    System.out.println("添加成功");
                }else{
                    System.out.println("添加失败");
                }
                
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally {
                if(stat!=null){
                    try {
                        stat.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if(connection!=null){
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    --演示案例3:更新数据
    public class JdbcDemo4 {
        public static void main(String[] args) {
            Connection connection=null;
            Statement stat=null;
            //2 注册驱动
            try {
                Class.forName("com.mysql.jdbc.Driver");
                //3打开连接
                connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/school", "root", "root");
                //4创建命令并执行
                stat=connection.createStatement();
                int result=stat.executeUpdate("update dept set loc='内蒙' where deptno=80");
                if(result>0){
                    System.out.println("更新成功");
                }else{
                    System.out.println("更新失败");
                }
                
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally {
                if(stat!=null){
                    try {
                        stat.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if(connection!=null){
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    --演示案例4:删除
    public class JdbcDemo5 {
        public static void main(String[] args) {
            Connection connection=null;
            Statement stat=null;
            //2 注册驱动
            try {
                Class.forName("com.mysql.jdbc.Driver");
                //3打开连接
                connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/school", "root", "root");
                //4创建命令并执行
                stat=connection.createStatement();
                int result=stat.executeUpdate("delete from dept where deptno=80");
                if(result>0){
                    System.out.println("删除成功");
                }else{
                    System.out.println("删除失败");
                }
                
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally {
                if(stat!=null){
                    try {
                        stat.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if(connection!=null){
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    --演示案例5:实现用户登录
    数据库myschool
    ​
    表 :user 
    ​
    create table user(      
    ​
    •   id int primary key auto_increment,
    ​
    •   username varchar(18) not null,
    ​
    •   password varchar(16) not null,  # 密文 123456
    ​
    •   phone varchar(11)
    ​
    );
    ​
    insert into user (username,password,phone) values('zhangsan','123456','13898765678');
    ​
    insert into user (username,password,phone) values('lisi','6666','17898879988');
    package com.qf.day03;
    ​
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.Scanner;
    ​
    import javax.management.remote.rmi.RMIJRMPServerImpl;
    ​
    /*
     * 实现用户登录
     */
    public class JdbcDemo1 {
        public static void main(String[] args) {
            Scanner input=new Scanner(System.in);
            System.out.println("请输入用户名");
            String username=input.nextLine();
            System.out.println("请输入密码");
            String pass=input.nextLine();
            
            //连接对象
            Connection connection=null;
            //命令对象
            Statement stat=null;
            //结果集
            ResultSet rs=null;
            //1 注册驱动
            try {
                Class.forName("com.mysql.jdbc.Driver");
                //2获取连接
                connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/school", "root", "root");
                //3创建命令
                stat=connection.createStatement();
                //4执行命命令  select * from user where username='zhangsan' and password='123456';
                 rs=stat.executeQuery("select * from user where username='"+username+"' and password='"+pass+"'");
                if(rs.next()){ //有数据
                    System.out.println("登录成功");
                }else{
                    System.out.println("账号或密码错误");
                }
            
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally {
                if(rs!=null){
                    try {
                        rs.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if(stat!=null){
                    try {
                        stat.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if(connection!=null){
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }       
        }
    }
  100. SQL注入

    就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到SQL注入式攻击。

  101. PreparedStatement

    作用:1预编译,效率高 2 安全,避免SQL注入

    PreparedStatement pstmt = null;
    try {
       String SQL = "Update Employees SET age = ? WHERE id = ?";
       pstmt = conn.prepareStatement(SQL);
       . . .
    }
    catch (SQLException e) {
       . . .
    }
    finally {
       . . .
    }

    练习

    package com.qf.day03;
    ​
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Scanner;
    ​
    /**
     * 使用PreparedStatement实现emp表的数据添加
     * @author wgy
     *
     */
    public class Demo6 {
        public static void main(String[] args) throws Exception{
            Scanner input=new Scanner(System.in);
            System.out.println("请输入员工编号");
            int empno=input.nextInt();
            System.out.println("请输入员工姓名");
            String ename=input.next();
            System.out.println("请输入工作");
            String job=input.next();
            System.out.println("请输入经理的编号");
            int mgr=input.nextInt();
            System.out.println("请输入入职日期");
            
            String date=input.next();
            SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
            Date hiredate=sdf.parse(date);
            System.out.println("请输入工资");
            double salary=input.nextDouble();
            System.out.println("请输入奖金");
            double comm=input.nextDouble();
            System.out.println("请输入部门");
            int deptno=input.nextInt();
            
            //1注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2获取连接
            String url="jdbc:mysql:///school";
            Connection conn=DriverManager.getConnection(url, "root", "root");
            //3创建命令
            PreparedStatement pstat=conn.prepareStatement("insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(?,?,?,?,?,?,?,?);");
            //4参数赋值
            pstat.setObject(1, empno);
            pstat.setObject(2, ename);
            pstat.setObject(3, job);
            pstat.setObject(4, mgr);
            pstat.setObject(5, hiredate);
            pstat.setObject(6, salary);
            pstat.setObject(7, comm);
            pstat.setObject(8, deptno);
            //5执行
            int count=pstat.executeUpdate();
            if(count>0) {
                System.out.println("添加成功");
            }else {
                System.out.println("添加失败");
            }
            //6释放资源
            pstat.close();
            conn.close();
            
        }
    }
    ​
  102. 抽取数据库工具类

    package com.qf.utils;
    /**
     * 1 注册驱动
     * 2 获取连接
     * 3 释放资源
     * 4 执行SQL 增删改
     * @author wgy
     *
     */
    ​
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    ​
    ​
    public class DbUtils {
        
        //驱动名称
        static String driver="com.mysql.jdbc.Driver";
        //url连接字符串
        static String url="jdbc:mysql://localhost:3306/school";
        //用户名
        static String user="root";
        //密码
        static String password="root";
        static {
            try {
                Class.forName(driver);
            } catch (ClassNotFoundException e) {
                System.out.println("注册驱动失败");
            }
            
        }
        /**
         * 获取连接
         * @return
         */
        public static Connection getConnection() {
            try {
                return DriverManager.getConnection(url, user, password);
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null;
        }
        /**
         * 释放资源
         * @param rs
         * @param stat
         * @param conn
         */
        public static void closeAll(ResultSet rs,Statement stat,Connection conn) {
            try {
                if(rs!=null) {
                    rs.close();
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                if(stat!=null) {
                    stat.close();
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            try {
                if(conn!=null) {
                    conn.close();
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        /**
         * 执行命令
         * @param sql   insert int emp() values(?,?,?,?)
         * @param params
         */
        public static int executeUpdate(String sql,Object... params) {
            try {
                Connection conn = getConnection();
                PreparedStatement pstat = conn.prepareStatement(sql);
                if(params!=null) {
                    for(int i=0;i<params.length;i++) {
                        pstat.setObject(i+1, params[i]);
                    }
                }
                int count=pstat.executeUpdate();
                closeAll(null, pstat, conn);
                return count;
                
            } catch (Exception e) {
                e.printStackTrace();
            }
            return 0;
            
        }
    }
  103. 小结

    1 单元测试

    2 jdbc介绍 :

    Java Database Connectity java数据库连接技术

    定义一套连接数据的规范和标准。

    3 jdbc包含两个部分

    JDBC API

    JDBC 驱动程序

    4 JDBC的使用步骤

    1 导入jar包

    2 注册驱动

    3 获取连接

    4 创建命令

    5 执行命令,处理结果

    6 释放资源

    5 JDBC的api

    Driver 驱动

    DriverManager 驱动管理类

    Connection 负责连接数据库

    Statement 负责执行命令

    ResultSet 封装结果集

    PreparedStatment 预编译命令

    5 数据库工具类

    DbUtils.java

    1 注册驱动

    2 获取连接

    3 释放资源

    4 执行命令 (增删改 DDL)

    5 执行查询(反射)


    第八天 JDBC高级操作和事务

    第一节 JDBC批处理

    Statement批处理

  104. 1 注册驱动获取连接

  105. 2 使用createStatement()方法创建Statement对象。

  106. 3 使用setAutoCommit()将auto-commit设置为false 。(可选)

  107. 4 使用addBatch()方法在创建的语句对象上添加您喜欢的SQL语句到批处理中。

  108. 5 在创建的语句对象上使用executeBatch()方法执行所有SQL语句。

  109. 6 使用commit()方法提交所有更改。(可选)

  110. 7 释放资源

  111. // Create statement object
    Statement stmt = conn.createStatement();
    ​
    // Set auto-commit to false
    conn.setAutoCommit(false);
    ​
    // Create SQL statement
    String SQL = "INSERT INTO Employees (id, first, last, age) " +
                 "VALUES(200,'Zia', 'Ali', 30)";
    // Add above SQL statement in the batch.
    stmt.addBatch(SQL);
    ​
    // Create one more SQL statement
    String SQL = "INSERT INTO Employees (id, first, last, age) " +
                 "VALUES(201,'Raj', 'Kumar', 35)";
    // Add above SQL statement in the batch.
    stmt.addBatch(SQL);
    ​
    // Create one more SQL statement
    String SQL = "UPDATE Employees SET age = 35 " +
                 "WHERE id = 100";
    // Add above SQL statement in the batch.
    stmt.addBatch(SQL);
    ​
    // Create an int[] to hold returned values
    int[] count = stmt.executeBatch();
    ​
    //Explicitly commit statements to apply changes
    conn.commit();

    PrepareStatement批处理

  112. 使用占位符创建SQL语句。

  113. 使用prepareStatement() 方法创建PrepareStatement对象。

  114. 使用setAutoCommit()将auto-commit设置为false 。(可选)

  115. 使用addBatch()方法在创建的语句对象上添加您喜欢的SQL语句到批处理中。

  116. 在创建的语句对象上使用executeBatch()方法执行所有SQL语句。

  117. 最后,使用commit()方法提交所有更改。(可选)

  118. // Create SQL statement
    String SQL = "INSERT INTO Employees (id, first, last, age) " +
                 "VALUES(?, ?, ?, ?)";
    ​
    // Create PrepareStatement object
    PreparedStatemen pstmt = conn.prepareStatement(SQL);
    ​
    //Set auto-commit to false
    conn.setAutoCommit(false);
    ​
    // Set the variables
    pstmt.setInt( 1, 400 );
    pstmt.setString( 2, "Pappu" );
    pstmt.setString( 3, "Singh" );
    pstmt.setInt( 4, 33 );
    // Add it to the batch
    pstmt.addBatch();
    ​
    // Set the variables
    pstmt.setInt( 1, 401 );
    pstmt.setString( 2, "Pawan" );
    pstmt.setString( 3, "Singh" );
    pstmt.setInt( 4, 31 );
    // Add it to the batch
    pstmt.addBatch();
    ​
    //add more batches
    ​
    //Create an int[] to hold returned values
    int[] count = stmt.executeBatch();
    ​
    //Explicitly commit statements to apply changes
    conn.commit();
    Statment批处理和PrepareStatment批处理区别:
    (1)Statment批处理可以添加不同Sql语句,而PrepareStatment只能添加一种sql语句
    (2)PrepareStatment效率比Statment高,而且更安全。

    第二节 JDBC操作二进制

  119. setAsciiStream():**此方法用于提供大的ASCII值。

  120. setCharacterStream():此方法用于提供大型UNICODE值。

  121. setBinaryStream():此方法用于提供较大的二进制值。

  122. XML文件的内容

    <?xml version="1.0" encoding="UTF-8"?>
    <Employee>
      <id>100</id>
      <first>张</first>
      <last>无极</last>
      <Salary>10000</Salary>
      <Dob>18-08-1978</Dob>
    </Employee>
    // Import required packages
    import java.sql.*;
    import java.io.*;
    import java.util.*;
    ​
    public class JDBCExample {
       // JDBC driver name and database URL
       static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";  
       static final String DB_URL = "jdbc:mysql://localhost:3306/EMP";
    ​
       //  Database credentials
       static final String USER = "username";
       static final String PASS = "password";
       
       public static void main(String[] args) {
       Connection conn = null;
       PreparedStatement pstmt = null;
       Statement stmt = null;
       ResultSet rs = null;
       try{
          // Register JDBC driver
          Class.forName("com.mysql.jdbc.Driver");
          // Open a connection
          System.out.println("Connecting to database...");
          conn = DriverManager.getConnection(DB_URL,USER,PASS);
    ​
          //Create a Statement object and build table
          stmt = conn.createStatement();
          createXMLTable(stmt);
    ​
          //Open a FileInputStream
          File f = new File("XML_Data.xml");
          long fileLength = f.length();
          FileInputStream fis = new FileInputStream(f);
    ​
          //Create PreparedStatement and stream data
          String SQL = "INSERT INTO XML_Data VALUES (?,?)";
          pstmt = conn.prepareStatement(SQL);
          pstmt.setInt(1,100);
          pstmt.setAsciiStream(2,fis,(int)fileLength);
          pstmt.execute();
    ​
          //Close input stream
          fis.close();
    ​
          // Do a query to get the row
          SQL = "SELECT Data FROM XML_Data WHERE id=100";
          rs = stmt.executeQuery (SQL);
          // Get the first row
          if (rs.next ()){
             //Retrieve data from input stream
             InputStream xmlInputStream = rs.getAsciiStream (1);
             int c;
             ByteArrayOutputStream bos = new ByteArrayOutputStream();
             while (( c = xmlInputStream.read ()) != -1)
                bos.write(c);
             //Print results
             System.out.println(bos.toString());
          }
          // Clean-up environment
          rs.close();
          stmt.close();
          pstmt.close();
          conn.close();
       }catch(SQLException se){
          //Handle errors for JDBC
          se.printStackTrace();
       }catch(Exception e){
          //Handle errors for Class.forName
          e.printStackTrace();
       }finally{
          //finally block used to close resources
          try{
             if(stmt!=null)
                stmt.close();
          }catch(SQLException se2){
          }// nothing we can do
          try{
             if(pstmt!=null)
                pstmt.close();
          }catch(SQLException se2){
          }// nothing we can do
          try{
             if(conn!=null)
                conn.close();
          }catch(SQLException se){
             se.printStackTrace();
          }//end finally try
       }//end try
       System.out.println("Goodbye!");
    }//end main
    ​
    public static void createXMLTable(Statement stmt) 
       throws SQLException{
       System.out.println("Creating XML_Data table..." );
       //Create SQL Statement
       String streamingDataSql = "CREATE TABLE XML_Data " +
                                 "(id INTEGER, Data TEXT)";
       //Drop table first if it exists.
       try{
          stmt.executeUpdate("DROP TABLE IF EXISTS XML_Data");
          //Build table.
          stmt.executeUpdate(streamingDataSql);
       }catch(SQLException se){
       }// do nothing
      
    }//end createXMLTable
    }//end JDBCExample
    package com.qf.day04;
    ​
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.lang.ProcessBuilder.Redirect;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    ​
    /**
     * 把图片放入数据库
     * @author wgy
     *
     */
    public class Demo4 {
        public static void main(String[] args) throws Exception{
            //write();
            read();
        }
        public static void write() throws Exception{
            Class.forName("com.mysql.jdbc.Driver");
            String url="jdbc:mysql://localhost:3306/school";
            Connection conn=DriverManager.getConnection(url, "root", "root");
            PreparedStatement pstat=conn.prepareStatement("insert into bigdata2(id,img) values(?,?)");
            FileInputStream fis=new FileInputStream("d:\\图片\\003.jpg");
            pstat.setInt(1, 1);
            pstat.setBinaryStream(2, fis);
            int count=pstat.executeUpdate();
            System.out.println(count);
            pstat.close();
            conn.close();
        }
        public static void read() throws Exception{
            Class.forName("com.mysql.jdbc.Driver");
            String url="jdbc:mysql://localhost:3306/school";
            Connection conn=DriverManager.getConnection(url, "root", "root");
            PreparedStatement pstat=conn.prepareStatement("select * from bigdata2 where id=1");
        
            ResultSet rs=pstat.executeQuery();
            if(rs.next()) {
                int id=rs.getInt("id");
                System.out.println(id);
                //处理图片
                InputStream is=rs.getBinaryStream("img");
                FileOutputStream fos=new FileOutputStream("d:\\haha.jpg");
                byte[] buf=new byte[1024];
                int len=0;
                while((len=is.read(buf))!=-1) {
                    fos.write(buf,0,len);
                }
                fos.close();
                is.close();
                
            }
            rs.close();
            pstat.close();
            conn.close();
            System.out.println("读取完成");
        }
    }

    小结

    1 数据完整性 :数据的正确性。

    实体完整性:

    主键约束:不能重复,不能为为null

    唯一约束: 不能重复 ,可以为null

    自动增长: auto_increment, 默认从1 开始每次增长1

    域完整性:

    数据类型:

    int

    double

    double(5,2)

    decimal(5,2);

    char 0-255

    varchar 长度不固定

    text

    blob

    date

    datetime

    timestamp

    非空约束 not null

    默认约束 default

    引用完整性

    外键约束

    2 多表查询

    2.1 表关系

    一对多

    一对一

    多对多

    2.2 查询

    合并结果集

    union 去掉重复

    union all 包含重复

    连接查询

    直接连接(交叉连接)

    内连接

    传统写法

    select *from emp ,dept where emp.deptno=dept.deptno;

    标准写法

    select *from emp inner join dept on emp.deptno=dept.deptno;

    外连接

    左外连接

    select *from emp left outer join dept on emp.deptno=dept.deptno;

    右外连接

    select *from emp right outer join dept on emp.deptno=dept.deptno;

    子查询:

    where 子查询

    from 子查询

    子查询结果:

    1 单行单列

    2 多行单列

    3 多行多列

    2.3 导出导入

    2.4 创建用户

    create user zhangsan identified by '123';

    授权

    grant all on school.* to zhangsan

    撤销权限

    revoke all on scholl.* from zhangsan


    第七天 JDBC概述和CRUD

    第一节 单元测试

    注意点:

    测试类加后缀Test,测试方法加前缀test

    第二节 JDBC的简介

    JDBC核心组件

    DriverManager: 此类管理数据库驱动程序列表。使用通信协议将来自java应用程序的连接请求与适当的数据库驱动程序匹配。

    Driver:此接口处理与数据库服务器的通信,我们很少会直接与Driver对象进行交互。而是使用DriverManager对象来管理这种类型的对象。

    Connection:该接口具有用于连接数据库的所有方法。连接对象表示通信上下文,数据库的所有通信仅通过连接对象。

    Statement:使用从此接口创建的对象将SQL语句提交到数据库。除了执行存储过程之外,一些派生接口还接受参数。

    ResultSet:在使用Statement对象执行SQL查询后,这些对象保存从数据库检索的数据。它作为一个迭代器,允许我们移动其数据。

    SQLException:此类处理数据库应用程序中发生的任何异常。

    第三节 JDBC初始

3.1 使用步骤

  • 导入JDBC驱动包:**需要下载包含数据库编程所需的JDBC的jar包。

  • 注册JDBC驱动程序:要求您初始化驱动程序,以便您可以打开与数据库的通信通道。

  • 创建连接:需要使用DriverManager.getConnection()方法创建一个Connection对象,该对象表示与数据库的物理连接。

  • 执行查询:需要使用类型为Statement的对象来构建和提交SQL语句到数据库。

  • 从结果集中提取数据:需要使用相应的ResultSet.getXXX()方法从结果集中检索数据。

  • 释放资源:需要明确地关闭所有数据库资源,而不依赖于JVM的垃圾收集。

3.2 注册驱动

  • 第一种方式(推荐写法):Class.forName()

    try {
       Class.forName("com.mysql.jdbc.Driver");
    }
    catch(ClassNotFoundException ex) {
       System.out.println("Error: unable to load driver class!");
       System.exit(1);
    }
  • 第二种方式:是使用静态DriverManager.registerDriver()方法。

    try {
       Driver myDriver = new com.mysql.jdbc.Driver();
       DriverManager.registerDriver( myDriver );
    }
    catch(ClassNotFoundException ex) {
       System.out.println("Error: unable to load driver class!");
       System.exit(1);
    }
    ​
     * 1>驱动程序注册两次
     * 2>java程序依赖mysql驱动包

3.3 获取连接

DriverManager.getConnection()方法

RDBMSJDBC驱动程序名称连接字符串格式
MySQL的com.mysql.jdbc.Driverjdbc:mysql://hostname:3306 / databaseName
ORACLEoracle.jdbc.driver.OracleDriverjdbc:oracle:thin:@ hostname:port Number:databaseName
DB2COM.ibm.db2.jdbc.net.DB2Driverjdbc:db2:hostname:port Number / databaseName
SYBASEcom.sybase.jdbc.SybDriverjdbc:sybase:Tds: hostname:port Number / databaseName

创建数据库连接对象

String URL = "jdbc:mysql://localhost:3306/emp";
String USER = "root";
String PASS = "root"
Connection conn = DriverManager.getConnection(URL, USER, PASS);

第四节 JDBC执行SQL语句

  • Statement

    • boolean execute(String SQL)**:如果可以检索到ResultSet对象,则返回一个布尔值true; 否则返回false。使用此方法执行SQL DDL语句或需要使用真正的动态SQL时。

    • int executeUpdate(String SQL):返回受SQL语句执行影响的行数。使用此方法执行预期会影响多个行的SQL语句,例如INSERT,UPDATE或DELETE语句。

    • ResultSet executeQuery(String SQL):返回一个ResultSet对象。当您希望获得结果集时,请使用此方法,就像使用SELECT语句一样。

  • ResultSet

    SELECT语句是从数据库中选择行并在结果集中查看行的标准方法。该java.sql.ResultSet中的接口表示结果集数据库查询。

    ResultSet对象维护指向结果集中当前行的游标。术语“结果集”是指包含在ResultSet对象中的行和列数据。

    如果没有指定任何ResultSet类型,您将自动获得一个TYPE_FORWARD_ONLY。

    类型描述
    ResultSet.TYPE_FORWARD_ONLY光标只能在结果集中向前移动。
    ResultSet.TYPE_SCROLL_INSENSITIVE光标可以向前和向后滚动,结果集对创建结果集后发生的数据库的其他更改不敏感。
    ResultSet.TYPE_SCROLL_SENSITIVE。光标可以向前和向后滚动,结果集对创建结果集之后发生的其他数据库所做的更改敏感。
    --演示案例1:查询数据
    public class JdbcDemo2 {
        public static void main(String[] args) {
            Connection connection=null;
            Statement stat=null;
            ResultSet rs=null;
            //2注册驱动
            try {
                Class.forName("com.mysql.jdbc.Driver");
                //3获取连接
                connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/school", "root", "root");
                //4创建命令(语句)对象
                stat=connection.createStatement();
                //执行命令查询
                rs=stat.executeQuery("select ename,empno from emp");
                //5处理结果
                while(rs.next()){
    //               int empno=rs.getInt(1);
    //               String empname=rs.getString(2);
                     int empno=rs.getInt("empno");
                     String empname=rs.getString("ename");
                     System.out.println(empno+"...."+empname);
                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally {
                if(rs!=null){
                    try {
                        rs.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if(stat!=null){
                    try {
                        stat.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if(connection!=null){
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    --演示案例2:添加数据
    public class JdbcDemo3 {
        public static void main(String[] args) {
            Connection connection=null;
            Statement stat=null;
            //2 注册驱动
            try {
                Class.forName("com.mysql.jdbc.Driver");
                //3打开连接
                connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/school", "root", "root");
                //4创建命令并执行
                stat=connection.createStatement();
                int result=stat.executeUpdate("insert into dept(deptno,dname,loc) values(80,'市场部','天津')");
                if(result>0){
                    System.out.println("添加成功");
                }else{
                    System.out.println("添加失败");
                }
                
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally {
                if(stat!=null){
                    try {
                        stat.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if(connection!=null){
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    --演示案例3:更新数据
    public class JdbcDemo4 {
        public static void main(String[] args) {
            Connection connection=null;
            Statement stat=null;
            //2 注册驱动
            try {
                Class.forName("com.mysql.jdbc.Driver");
                //3打开连接
                connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/school", "root", "root");
                //4创建命令并执行
                stat=connection.createStatement();
                int result=stat.executeUpdate("update dept set loc='内蒙' where deptno=80");
                if(result>0){
                    System.out.println("更新成功");
                }else{
                    System.out.println("更新失败");
                }
                
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally {
                if(stat!=null){
                    try {
                        stat.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if(connection!=null){
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    --演示案例4:删除
    public class JdbcDemo5 {
        public static void main(String[] args) {
            Connection connection=null;
            Statement stat=null;
            //2 注册驱动
            try {
                Class.forName("com.mysql.jdbc.Driver");
                //3打开连接
                connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/school", "root", "root");
                //4创建命令并执行
                stat=connection.createStatement();
                int result=stat.executeUpdate("delete from dept where deptno=80");
                if(result>0){
                    System.out.println("删除成功");
                }else{
                    System.out.println("删除失败");
                }
                
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally {
                if(stat!=null){
                    try {
                        stat.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if(connection!=null){
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    --演示案例5:实现用户登录
    数据库myschool
    ​
    表 :user 
    ​
    create table user(      
    ​
    •   id int primary key auto_increment,
    ​
    •   username varchar(18) not null,
    ​
    •   password varchar(16) not null,  # 密文 123456
    ​
    •   phone varchar(11)
    ​
    );
    ​
    insert into user (username,password,phone) values('zhangsan','123456','13898765678');
    ​
    insert into user (username,password,phone) values('lisi','6666','17898879988');
    package com.qf.day03;
    ​
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.Scanner;
    ​
    import javax.management.remote.rmi.RMIJRMPServerImpl;
    ​
    /*
     * 实现用户登录
     */
    public class JdbcDemo1 {
        public static void main(String[] args) {
            Scanner input=new Scanner(System.in);
            System.out.println("请输入用户名");
            String username=input.nextLine();
            System.out.println("请输入密码");
            String pass=input.nextLine();
            
            //连接对象
            Connection connection=null;
            //命令对象
            Statement stat=null;
            //结果集
            ResultSet rs=null;
            //1 注册驱动
            try {
                Class.forName("com.mysql.jdbc.Driver");
                //2获取连接
                connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/school", "root", "root");
                //3创建命令
                stat=connection.createStatement();
                //4执行命命令  select * from user where username='zhangsan' and password='123456';
                 rs=stat.executeQuery("select * from user where username='"+username+"' and password='"+pass+"'");
                if(rs.next()){ //有数据
                    System.out.println("登录成功");
                }else{
                    System.out.println("账号或密码错误");
                }
            
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally {
                if(rs!=null){
                    try {
                        rs.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if(stat!=null){
                    try {
                        stat.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if(connection!=null){
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }       
        }
    }
  • SQL注入

    就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到SQL注入式攻击。

  • PreparedStatement

    作用:1预编译,效率高 2 安全,避免SQL注入

    PreparedStatement pstmt = null;
    try {
       String SQL = "Update Employees SET age = ? WHERE id = ?";
       pstmt = conn.prepareStatement(SQL);
       . . .
    }
    catch (SQLException e) {
       . . .
    }
    finally {
       . . .
    }

    练习

    package com.qf.day03;
    ​
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Scanner;
    ​
    /**
     * 使用PreparedStatement实现emp表的数据添加
     * @author wgy
     *
     */
    public class Demo6 {
        public static void main(String[] args) throws Exception{
            Scanner input=new Scanner(System.in);
            System.out.println("请输入员工编号");
            int empno=input.nextInt();
            System.out.println("请输入员工姓名");
            String ename=input.next();
            System.out.println("请输入工作");
            String job=input.next();
            System.out.println("请输入经理的编号");
            int mgr=input.nextInt();
            System.out.println("请输入入职日期");
            
            String date=input.next();
            SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
            Date hiredate=sdf.parse(date);
            System.out.println("请输入工资");
            double salary=input.nextDouble();
            System.out.println("请输入奖金");
            double comm=input.nextDouble();
            System.out.println("请输入部门");
            int deptno=input.nextInt();
            
            //1注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2获取连接
            String url="jdbc:mysql:///school";
            Connection conn=DriverManager.getConnection(url, "root", "root");
            //3创建命令
            PreparedStatement pstat=conn.prepareStatement("insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(?,?,?,?,?,?,?,?);");
            //4参数赋值
            pstat.setObject(1, empno);
            pstat.setObject(2, ename);
            pstat.setObject(3, job);
            pstat.setObject(4, mgr);
            pstat.setObject(5, hiredate);
            pstat.setObject(6, salary);
            pstat.setObject(7, comm);
            pstat.setObject(8, deptno);
            //5执行
            int count=pstat.executeUpdate();
            if(count>0) {
                System.out.println("添加成功");
            }else {
                System.out.println("添加失败");
            }
            //6释放资源
            pstat.close();
            conn.close();
            
        }
    }
    ​
  • 抽取数据库工具类

    package com.qf.utils;
    /**
     * 1 注册驱动
     * 2 获取连接
     * 3 释放资源
     * 4 执行SQL 增删改
     * @author wgy
     *
     */
    ​
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    ​
    ​
    public class DbUtils {
        
        //驱动名称
        static String driver="com.mysql.jdbc.Driver";
        //url连接字符串
        static String url="jdbc:mysql://localhost:3306/school";
        //用户名
        static String user="root";
        //密码
        static String password="root";
        static {
            try {
                Class.forName(driver);
            } catch (ClassNotFoundException e) {
                System.out.println("注册驱动失败");
            }
            
        }
        /**
         * 获取连接
         * @return
         */
        public static Connection getConnection() {
            try {
                return DriverManager.getConnection(url, user, password);
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null;
        }
        /**
         * 释放资源
         * @param rs
         * @param stat
         * @param conn
         */
        public static void closeAll(ResultSet rs,Statement stat,Connection conn) {
            try {
                if(rs!=null) {
                    rs.close();
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                if(stat!=null) {
                    stat.close();
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            try {
                if(conn!=null) {
                    conn.close();
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        /**
         * 执行命令
         * @param sql   insert int emp() values(?,?,?,?)
         * @param params
         */
        public static int executeUpdate(String sql,Object... params) {
            try {
                Connection conn = getConnection();
                PreparedStatement pstat = conn.prepareStatement(sql);
                if(params!=null) {
                    for(int i=0;i<params.length;i++) {
                        pstat.setObject(i+1, params[i]);
                    }
                }
                int count=pstat.executeUpdate();
                closeAll(null, pstat, conn);
                return count;
                
            } catch (Exception e) {
                e.printStackTrace();
            }
            return 0;
            
        }
    }

小结

1 单元测试

2 jdbc介绍 :

Java Database Connectity java数据库连接技术

定义一套连接数据的规范和标准。

3 jdbc包含两个部分

JDBC API

JDBC 驱动程序

4 JDBC的使用步骤

1 导入jar包

2 注册驱动

3 获取连接

4 创建命令

5 执行命令,处理结果

6 释放资源

5 JDBC的api

Driver 驱动

DriverManager 驱动管理类

Connection 负责连接数据库

Statement 负责执行命令

ResultSet 封装结果集

PreparedStatment 预编译命令

5 数据库工具类

DbUtils.java

1 注册驱动

2 获取连接

3 释放资源

4 执行命令 (增删改 DDL)

5 执行查询(反射)


第八天 JDBC高级操作和事务

第一节 JDBC批处理

Statement批处理

  • 1 注册驱动获取连接

  • 2 使用createStatement()方法创建Statement对象。

  • 3 使用setAutoCommit()将auto-commit设置为false 。(可选)

  • 4 使用addBatch()方法在创建的语句对象上添加您喜欢的SQL语句到批处理中。

  • 5 在创建的语句对象上使用executeBatch()方法执行所有SQL语句。

  • 6 使用commit()方法提交所有更改。(可选)

  • 7 释放资源

// Create statement object
Statement stmt = conn.createStatement();
​
// Set auto-commit to false
conn.setAutoCommit(false);
​
// Create SQL statement
String SQL = "INSERT INTO Employees (id, first, last, age) " +
             "VALUES(200,'Zia', 'Ali', 30)";
// Add above SQL statement in the batch.
stmt.addBatch(SQL);
​
// Create one more SQL statement
String SQL = "INSERT INTO Employees (id, first, last, age) " +
             "VALUES(201,'Raj', 'Kumar', 35)";
// Add above SQL statement in the batch.
stmt.addBatch(SQL);
​
// Create one more SQL statement
String SQL = "UPDATE Employees SET age = 35 " +
             "WHERE id = 100";
// Add above SQL statement in the batch.
stmt.addBatch(SQL);
​
// Create an int[] to hold returned values
int[] count = stmt.executeBatch();
​
//Explicitly commit statements to apply changes
conn.commit();

PrepareStatement批处理

  1. 使用占位符创建SQL语句。

  2. 使用prepareStatement() 方法创建PrepareStatement对象。

  3. 使用setAutoCommit()将auto-commit设置为false 。(可选)

  4. 使用addBatch()方法在创建的语句对象上添加您喜欢的SQL语句到批处理中。

  5. 在创建的语句对象上使用executeBatch()方法执行所有SQL语句。

  6. 最后,使用commit()方法提交所有更改。(可选)

// Create SQL statement
String SQL = "INSERT INTO Employees (id, first, last, age) " +
             "VALUES(?, ?, ?, ?)";
​
// Create PrepareStatement object
PreparedStatemen pstmt = conn.prepareStatement(SQL);
​
//Set auto-commit to false
conn.setAutoCommit(false);
​
// Set the variables
pstmt.setInt( 1, 400 );
pstmt.setString( 2, "Pappu" );
pstmt.setString( 3, "Singh" );
pstmt.setInt( 4, 33 );
// Add it to the batch
pstmt.addBatch();
​
// Set the variables
pstmt.setInt( 1, 401 );
pstmt.setString( 2, "Pawan" );
pstmt.setString( 3, "Singh" );
pstmt.setInt( 4, 31 );
// Add it to the batch
pstmt.addBatch();
​
//add more batches
​
//Create an int[] to hold returned values
int[] count = stmt.executeBatch();
​
//Explicitly commit statements to apply changes
conn.commit();
Statment批处理和PrepareStatment批处理区别:
(1)Statment批处理可以添加不同Sql语句,而PrepareStatment只能添加一种sql语句
(2)PrepareStatment效率比Statment高,而且更安全。

第二节 JDBC操作二进制

  • setAsciiStream():**此方法用于提供大的ASCII值。

  • setCharacterStream():此方法用于提供大型UNICODE值。

  • setBinaryStream():此方法用于提供较大的二进制值。

XML文件的内容

<?xml version="1.0" encoding="UTF-8"?>
<Employee>
  <id>100</id>
  <first>张</first>
  <last>无极</last>
  <Salary>10000</Salary>
  <Dob>18-08-1978</Dob>
</Employee>
// Import required packages
import java.sql.*;
import java.io.*;
import java.util.*;
​
public class JDBCExample {
   // JDBC driver name and database URL
   static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";  
   static final String DB_URL = "jdbc:mysql://localhost:3306/EMP";
​
   //  Database credentials
   static final String USER = "username";
   static final String PASS = "password";
   
   public static void main(String[] args) {
   Connection conn = null;
   PreparedStatement pstmt = null;
   Statement stmt = null;
   ResultSet rs = null;
   try{
      // Register JDBC driver
      Class.forName("com.mysql.jdbc.Driver");
      // Open a connection
      System.out.println("Connecting to database...");
      conn = DriverManager.getConnection(DB_URL,USER,PASS);
​
      //Create a Statement object and build table
      stmt = conn.createStatement();
      createXMLTable(stmt);
​
      //Open a FileInputStream
      File f = new File("XML_Data.xml");
      long fileLength = f.length();
      FileInputStream fis = new FileInputStream(f);
​
      //Create PreparedStatement and stream data
      String SQL = "INSERT INTO XML_Data VALUES (?,?)";
      pstmt = conn.prepareStatement(SQL);
      pstmt.setInt(1,100);
      pstmt.setAsciiStream(2,fis,(int)fileLength);
      pstmt.execute();
​
      //Close input stream
      fis.close();
​
      // Do a query to get the row
      SQL = "SELECT Data FROM XML_Data WHERE id=100";
      rs = stmt.executeQuery (SQL);
      // Get the first row
      if (rs.next ()){
         //Retrieve data from input stream
         InputStream xmlInputStream = rs.getAsciiStream (1);
         int c;
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
         while (( c = xmlInputStream.read ()) != -1)
            bos.write(c);
         //Print results
         System.out.println(bos.toString());
      }
      // Clean-up environment
      rs.close();
      stmt.close();
      pstmt.close();
      conn.close();
   }catch(SQLException se){
      //Handle errors for JDBC
      se.printStackTrace();
   }catch(Exception e){
      //Handle errors for Class.forName
      e.printStackTrace();
   }finally{
      //finally block used to close resources
      try{
         if(stmt!=null)
            stmt.close();
      }catch(SQLException se2){
      }// nothing we can do
      try{
         if(pstmt!=null)
            pstmt.close();
      }catch(SQLException se2){
      }// nothing we can do
      try{
         if(conn!=null)
            conn.close();
      }catch(SQLException se){
         se.printStackTrace();
      }//end finally try
   }//end try
   System.out.println("Goodbye!");
}//end main
​
public static void createXMLTable(Statement stmt) 
   throws SQLException{
   System.out.println("Creating XML_Data table..." );
   //Create SQL Statement
   String streamingDataSql = "CREATE TABLE XML_Data " +
                             "(id INTEGER, Data TEXT)";
   //Drop table first if it exists.
   try{
      stmt.executeUpdate("DROP TABLE IF EXISTS XML_Data");
      //Build table.
      stmt.executeUpdate(streamingDataSql);
   }catch(SQLException se){
   }// do nothing
  
}//end createXMLTable
}//end JDBCExample
package com.qf.day04;
​
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.ProcessBuilder.Redirect;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
​
/**
 * 把图片放入数据库
 * @author wgy
 *
 */
public class Demo4 {
    public static void main(String[] args) throws Exception{
        //write();
        read();
    }
    public static void write() throws Exception{
        Class.forName("com.mysql.jdbc.Driver");
        String url="jdbc:mysql://localhost:3306/school";
        Connection conn=DriverManager.getConnection(url, "root", "root");
        PreparedStatement pstat=conn.prepareStatement("insert into bigdata2(id,img) values(?,?)");
        FileInputStream fis=new FileInputStream("d:\\图片\\003.jpg");
        pstat.setInt(1, 1);
        pstat.setBinaryStream(2, fis);
        int count=pstat.executeUpdate();
        System.out.println(count);
        pstat.close();
        conn.close();
    }
    public static void read() throws Exception{
        Class.forName("com.mysql.jdbc.Driver");
        String url="jdbc:mysql://localhost:3306/school";
        Connection conn=DriverManager.getConnection(url, "root", "root");
        PreparedStatement pstat=conn.prepareStatement("select * from bigdata2 where id=1");
    
        ResultSet rs=pstat.executeQuery();
        if(rs.next()) {
            int id=rs.getInt("id");
            System.out.println(id);
            //处理图片
            InputStream is=rs.getBinaryStream("img");
            FileOutputStream fos=new FileOutputStream("d:\\haha.jpg");
            byte[] buf=new byte[1024];
            int len=0;
            while((len=is.read(buf))!=-1) {
                fos.write(buf,0,len);
            }
            fos.close();
            is.close();
            
        }
        rs.close();
        pstat.close();
        conn.close();
        System.out.println("读取完成");
    }
}

第三节 数据库事务

  • 概述

    一组要么同时执行成功,要么同时失败的SQL语句。是数据库操作的一个不能分割执行单元。

    事务开始于

    • 连接到数据库上,并执行一条DML语句insert、update或delete

    • 前一个事务结束后,又输入了另一条DML语句

    事务结束于

    • 执行commit或rollback语句。

    • 执行一条DDL语句,例如create table语句,在这种情况下,会自动执行commit语句。

    • 执行一条DDL语句,例如grant语句,在这种情况下,会自动执行commit。

    • 断开与数据库的连接

    • 执行了一条DML语句,该语句却失败了,在这种情况中,会为这个无效的DML语句执行rollback语句。

    3.2 事务的四大特点

    (ACID)

    • Atomicity(原子性)

        表示一个事务内的所有操作是一个整体,要么全部成功,要么全部失败

    • Consistency(一致性)

        表示一个事务内有一个操作失败时,所有的更改过的数据都必须回滚到修改前状态

    • Isolation(隔离性)

      事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。

    • Durability(持久性)

      持久性事务完成之后,它对于系统的影响是永久性的。

    案例:

    CREATE TABLE account(
        id INT PRIMARY KEY,
        NAME VARCHAR(20) NOT NULL,
        money DOUBLE(10,2)
    )
      
      
    public static void main(String[] args) {
            Connection connection=null;
            PreparedStatement pstat1=null;
            PreparedStatement pstat2=null;
            
            //1注册驱动
            try {
                Class.forName("com.mysql.jdbc.Driver");
                //2获取连接
                connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/school", "root", "root");
                //3创建命令
                //3.1开启事务 ,设置事务自动提交为false
                connection.setAutoCommit(false);
                pstat1=connection.prepareStatement("update account set money=money-1000 where name='张莎强'");
                pstat1.executeUpdate();
                //int c=10/0;
                pstat2=connection.prepareStatement("update account set money=money+1000 where name='小苍'");
                pstat2.executeUpdate();
                
                System.out.println("转账成功...");
                //3.2提交事务
                connection.commit();
                
            } catch (Exception e) {
                System.out.println("出现异常");
                try {
                    connection.rollback();//出现问题,要回滚(撤销事务做过的修改)
                    connection.commit();//可加也不不加
                } catch (SQLException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }finally {
                if(pstat1!=null){
                    try {
                        pstat1.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if(pstat2!=null){
                    try {
                        pstat2.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if(connection!=null){
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }

    Mysql支持的事务语句

    #开启事务
    START TRANSACTION;     # connection.setAutoCommit(false);
    UPDATE account SET money=money-1000 WHERE id=1;
    UPDATE account SET money=money+1000 WHERE id=2;
    #提交事务
    COMMIT;#connection.commit();
    #回滚
    ROLLBACK; #connection.rollback();

 

  • 事务隔离级别

    Read Uncommitted(读取未提交内容)

    在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。

    Read Committed(读取提交内容)

    这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别出现不可重复读(Nonrepeatable Read)问题,因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。

    Repeatable Read 可重读

    这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读(Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻读” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。

    Serializable 可串行化 ​ 这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。效率最低的。

    这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。

  • 脏读(Dirty Read):某个事务已更新一份数据未提交前,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。

    #修改事务的隔离级别:
    SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]
    #查看事务隔离级别
    SELECT @@tx_isolation;
  • 不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。

    # A方 买 本伟
    SELECT @@tx_isolation;
    START TRANSACTION;
    UPDATE account SET money=money-2000 WHERE id=1;
    UPDATE account SET money=money+2000 WHERE id=2;
    COMMIT;
    ROLLBACK;
    ​
    START TRANSACTION;
    UPDATE account SET money=money+1000 WHERE id=2;
    COMMIT;
    ​
    ​
    ​
    ​
    ​
    # B方  卖  郑帅
    #(修改隔离级别)
    SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
    #查看隔离级别
    SELECT @@tx_isolation;
    SELECT *FROM account;
    #发货
    #修改隔离级别
    SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
    SELECT *FROM account;
    ​
    #不可重复读
    ​
    START TRANSACTION;
        SELECT SUM(money) FROM account;
        SELECT SUM(money) FROM account;
        SELECT SUM(money) FROM account;
    COMMIT; 
    ​
    #再次修改隔离级别
    ​
    SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
    ​
    ​
    START TRANSACTION;
        SELECT SUM(money) FROM account;
        SELECT SUM(money) FROM account;
        SELECT SUM(money) FROM account;
    COMMIT; 
    ​

    幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。但是InnoDB存储引擎通过多版本并发控制机制解决了该问题。

  • JDBC中事务应用

    setAutoCommit()**方法。如果将boolean false传递给setAutoCommit(),则关闭自动提交。我们可以传递一个布尔值true来重新打开它。

  • 事务的提交和回滚

    conn.commit( );
    conn.rollback( );
    try{
       //开启事务
       conn.setAutoCommit(false);
       Statement stmt = conn.createStatement();
       
       String SQL = "INSERT INTO Employees  " +
                    "VALUES (106, 20, 'Rita', 'Tez')";
       stmt.executeUpdate(SQL);  
       //有可能出现异常
       String SQL = "INSERT IN Employees  " +
                    "VALUES (107, 22, 'Sita', 'Singh')";
       stmt.executeUpdate(SQL);
       // 没有错误提交
       conn.commit();
    }catch(SQLException se){
       //出现错误回滚
       conn.rollback();
       conn.commit();
    }
  • Savepoint

    • setSavepoint(String savepointName):**定义新的保存点。它还返回一个Savepoint对象。

    • releaseSavepoint(Savepoint savepointName):删除保存点。请注意,它需要一个Savepoint对象作为参数。此对象通常是由setSavepoint()方法生成的保存点。

    public static void main(String[] args) {
            Connection conn = null;
            Statement stmt = null;
            Savepoint savepoint1 = null;
            try {
                Class.forName("com.mysql.jdbc.Driver");
                conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/school", "root", "root");
                // Assume a valid connection object conn
                conn.setAutoCommit(false);
                stmt = conn.createStatement();
    ​
                // set a Savepoint
                String SQL = "INSERT INTO Employees " + "VALUES (106, 20, 'Rita', 'Tez');";
                stmt.executeUpdate(SQL);
                savepoint1 = conn.setSavepoint("Savepoint1");
                // Submit a malformed SQL statement that breaks
                SQL = "INSERT IN Employees " + "VALUES (107, 22, 'Sita', 'Tez')";
                stmt.executeUpdate(SQL);
                // If there is no error, commit the changes.
                conn.commit();
                System.out.println("执行成功");
    ​
            } catch (Exception se) {
                // If there is any error.
                try {
                    se.printStackTrace();
                    conn.rollback(savepoint1);
                    conn.commit();
                    System.out.println("回滚");
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

小结

1 批处理

Statement实现批处理

stat.addBatch(sql);// insert update delete

stat.executeBatch();

PreparetedStatement

pstat.addBatch();

pstat.executeBatch();

pstat.clearBatch();

2 jdbc操作大数据

大文本 tinytext text mediumtext longtext

setAsciiStream();

setCharacterStream();

setBinaryStream();

二进制tinyblob blob mediunblob longblob

setBinaryStream();

3 事务:一组要么同时执行成功,要么同时失败的SQL语句。是数据库操作的一个不能分割执行单元。

四个特性:

原子性 A: 不能分割

一致性 C:事务执行前后保持一致

隔离型 I: 事务与事务之间对数据的读取控制

持久性 D:事务提交或回滚之后,永久保存数据库。

4 修改隔离级别

#修改事务的隔离级别:
SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]
#查看事务隔离级别
SELECT @@tx_isolation;

java代码更改隔离级别

conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);

5 保存点

SavePoint


第九天 数据库连接池和DBUtils使用

第一节 工具类封装,DAO模式和自定义连接池

  • DAO设计模式(Database Access Object 数据库访问对象)

  • DAO模式的组成部分

    1 DAO接口(主要包 添加 修改 查询 删除方法)

    2 DAO实现类

    3 实体类 (domain、beans、entity、pojo、model)

    PO (VO)(Persistent Object, Value Object)

    VO (View Object)

    DTO (Data Transfer Object)

    --作用:用在数据访问代码和业务逻辑代码之间通过实体类来传输数据

    --实体类特征:

    ◦属性一般使用private修饰

    ◦提供public修饰的getter/setter方法

    ◦实体类提供无参构造方法,根据业务提供有参构造

    ◦实现java.io.Serializable接口,支持序列化机制

    4 数据库连接和关闭工具类

    设计的包名 :

    domain 存放实体类

    utils 存放工具类

    dao 存放接口

    dao.impl 存放实现类

    使用DAO设计模式实现emp表的查询、添加、删除、修改

  • 自定义实现连接池

    package Day20190827.Day9连接池和Dbutils.utils;
    ​
    import java.beans.PropertyDescriptor;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStream;
    import java.lang.reflect.Method;
    import java.sql.*;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Properties;
    ​
    /**
     * @Auther: xbh
     * @Date: 2019/8/26 14:28
     * @Description:
     * 四个功能
     * 1、注册驱动(一次)
     * 2、获取连接
     * 3、释放资源
     * 4、执行sql语句(增删改)
     */
    public class DbUtils {
        private static String driver;
        private static String url;
        private static String user;
        private static String password;
        //注册驱动(一次)
        static {
    //        driver="com.mysql.jdbc.Driver";
    //        url="jdbc:mysql://localhost:3306/day20190824?useSSL=true&characterEncoding=utf8";
    //        user="root";
    //        password="123456";
            //读取文件
            Properties properties = new Properties();
            FileInputStream fis = null;
            InputStream is = null;
            try {
                /*fis = new FileInputStream("src\\db.properties");
                properties.load(fis);
                driver=properties.getProperty("driver");*/
    ​
                //读取文件2,使用类加载器加载配置文件
                is = DbUtils.class.getClassLoader().getResourceAsStream("db.properties");
                properties.load(is);
                driver=properties.getProperty("driver");
                url=properties.getProperty("url");
                user=properties.getProperty("user");
                password=properties.getProperty("password");
                Class.forName(driver);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                System.out.println("注册驱动失败");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if(fis!=null) {
                        fis.close();
                    }
                    if(is!=null){
                        is.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        //获取连接
        public static Connection getConnection(){
            try {
                return DriverManager.getConnection(url, user, password);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return  null;
        }
        //释放资源
        public static void closeAll(Connection conn, Statement stat, ResultSet rs){
            if(rs!=null){
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(stat!=null){
                try {
                    stat.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        //sql语句
        public static int executeUpdate(String sql, Object...params){
            Connection conn = getConnection();
            PreparedStatement pstat = null;
            try {
                pstat = conn.prepareStatement(sql);
                //设置参数
                if(params!=null){
                    for (int i = 0; i < params.length; i++) {
                        pstat.setObject(i+1, params[i]);
                    }
                }
                return pstat.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                closeAll(conn,pstat,null);
            }
            return -1;
        }
    ​
        //返回list集合的方法
        public static <T>  List<T> findList(String sql,Class<T> class1, Object...params){
            List<T> list = new ArrayList<>();
            //从数据库查询数据
            Connection conn = null;
            PreparedStatement pstat = null;
            ResultSet rs = null;
            try{
                //获取连接
               conn = getConnection();
               //获取执行
               pstat = conn.prepareStatement(sql);
               //进行执行判断
               if(params != null){
                   for (int i = 0; i < params.length; i++) {
                       pstat.setObject(i+1, params[i]);
                   }
               }
               //执行语句
               rs = pstat.executeQuery();
               //获得表头
               ResultSetMetaData metaData = rs.getMetaData();
               while (rs.next()){
                   //获得对象
                   T t = convertToObject(metaData, rs, class1);
                   list.add(t);
               }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                closeAll(conn, pstat, rs);
            }
            return list;
        }
    ​
        //返回单个对象的方法
        public static <T> T findSingle(String sql, Class<T> class1, Object...params){
            T t = null;
            //从数据库查询数据
            Connection conn = null;
            PreparedStatement pstat = null;
            ResultSet rs = null;
            try{
                conn = getConnection();
                pstat = conn.prepareStatement(sql);
                if(params != null){
                    for (int i = 0; i < params.length; i++) {
                        pstat.setObject(i+1, params[i]);
                    }
                }
                rs = pstat.executeQuery();
                ResultSetMetaData metaData = rs.getMetaData();
                if (rs.next()){
                    t = convertToObject(metaData, rs, class1);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                closeAll(conn, pstat, rs);
            }
            return  t;
        }
    ​
        public static <T> T convertToObject(ResultSetMetaData metaData, ResultSet rs, Class<T> class1){
            try {
                //映射对象
                T t = class1.newInstance();
                for (int i = 0; i < metaData.getColumnCount(); i++) {
                    //获得表头
                    String columnLabel = metaData.getColumnLabel(i + 1);
                    //获得表头下的数据
                    Object value = rs.getObject(columnLabel);//empno ename
                    try{
                        //内省解析属性描述符
                        PropertyDescriptor pd = new PropertyDescriptor(columnLabel, class1);
                        if (pd != null) {//属性描述符不空
                            //获取set方法
                            Method writeMethod = pd.getWriteMethod();//setEmpno setEname
                            //加入数据到对象
                            writeMethod.invoke(t, value);
                        }
                    }catch (Exception e){
                        continue;
                    }
                }
                //返回对象
                return t;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    ​

第二节DBCP连接池

  • 配置文件

    #连接设置
    driverClassName=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/day20190824?useSSL=true&characterEncoding=utf8
    username=root
    password=123456
    #<!-- 初始化连接 -->
    initialSize=10
    #最大连接数量
    maxTotal=50
    #<!-- 最大空闲连接 -->
    maxIdle=20
    #<!-- 最小空闲连接 -->
    minIdle=5
    #<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
    maxWaitMillis=5000
  • 连接池

    package Day20190827.Day9连接池和Dbutils.utils;
    ​
    import org.apache.commons.dbcp2.BasicDataSource;
    import org.apache.commons.dbcp2.BasicDataSourceFactory;
    ​
    import java.beans.IntrospectionException;
    import java.beans.PropertyDescriptor;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStream;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.sql.*;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Properties;
    ​
    /**
     * @Auther: xbh
     * @Date: 2019/8/26 14:28
     * @Description:
     * 四个功能
     * 1、注册驱动(一次)
     * 2、获取连接
     * 3、释放资源
     * 4、执行sql语句(增删改)
     */
    public class DbUtils_DBCP {
        private static String driver;
        private static String url;
        private static String user;
        private static String password;
    ​
        private static BasicDataSource dataSource = null;
        //注册驱动(一次)
        static {
            Properties properties = new Properties();
            InputStream resourceAsStream = DbUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcp.properties");
            try {
                properties.load(resourceAsStream);
                dataSource = BasicDataSourceFactory.createDataSource(properties);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
            /*dataSource = new BasicDataSource();
            //设置四个基本属性
            dataSource.setDriverClassName("com.mysql.jdbc.Driver");
            dataSource.setUrl("jdbc:mysql://localhost:3306/day20190824?useSSL=true&characterEncoding=utf8");
            dataSource.setUsername("root");
            dataSource.setPassword("123456");
            //设置初始大小
            dataSource.setInitialSize(10);
            //设置最大个数
            dataSource.setMaxTotal(50);
            //设置最大空闲连接
            dataSource.setMaxIdle(10);
            //设置最小空闲连接
            dataSource.setMinIdle(5);
            //设置超时时间
            dataSource.setMaxWaitMillis(5000);*/
        }
        //获取连接
        public static Connection getConnection(){
            try {
                return  dataSource.getConnection();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }
        //释放资源
        public static void closeAll(Connection conn, Statement stat, ResultSet rs){
            if(rs!=null){
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(stat!=null){
                try {
                    stat.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        //sql语句
        public static int executeUpdate(String sql, Object...params){
            Connection conn = getConnection();
            PreparedStatement pstat = null;
            try {
                pstat = conn.prepareStatement(sql);
                //设置参数
                if(params!=null){
                    for (int i = 0; i < params.length; i++) {
                        pstat.setObject(i+1, params[i]);
                    }
                }
                return pstat.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                closeAll(conn,pstat,null);
            }
            return -1;
        }
    ​
        //返回list集合的方法
        public static <T>  List<T> findList(String sql,Class<T> class1, Object...params){
            List<T> list = new ArrayList<>();
            //从数据库查询数据
            Connection conn = null;
            PreparedStatement pstat = null;
            ResultSet rs = null;
            try{
                //获取连接
                conn = getConnection();
                //获取执行
                pstat = conn.prepareStatement(sql);
                //进行执行判断
                if(params != null){
                    for (int i = 0; i < params.length; i++) {
                        pstat.setObject(i+1, params[i]);
                    }
                }
                //执行语句
                rs = pstat.executeQuery();
                //获得表头
                ResultSetMetaData metaData = rs.getMetaData();
                while (rs.next()){
                    //获得对象
                    T t = convertToObject(metaData, rs, class1);
                    list.add(t);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                closeAll(conn, pstat, rs);
            }
            return list;
        }
    ​
        //返回单个对象的方法
        public static <T> T findSingle(String sql, Class<T> class1, Object...params){
            T t = null;
            //从数据库查询数据
            Connection conn = null;
            PreparedStatement pstat = null;
            ResultSet rs = null;
            try{
                conn = getConnection();
                pstat = conn.prepareStatement(sql);
                if(params != null){
                    for (int i = 0; i < params.length; i++) {
                        pstat.setObject(i+1, params[i]);
                    }
                }
                rs = pstat.executeQuery();
                ResultSetMetaData metaData = rs.getMetaData();
                if (rs.next()){
                    t = convertToObject(metaData, rs, class1);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                closeAll(conn, pstat, rs);
            }
            return  t;
        }
    ​
        public static <T> T convertToObject(ResultSetMetaData metaData, ResultSet rs, Class<T> class1){
            try {
                //映射对象
                T t = class1.newInstance();
                for (int i = 0; i < metaData.getColumnCount(); i++) {
                    //获得表头
                    String columnLabel = metaData.getColumnLabel(i + 1);
                    //获得表头下的数据
                    Object value = rs.getObject(columnLabel);//empno ename
                    try{
                        //内省解析属性描述符
                        PropertyDescriptor pd = new PropertyDescriptor(columnLabel, class1);
                        if (pd != null) {//属性描述符不空
                            //获取set方法
                            Method writeMethod = pd.getWriteMethod();//setEmpno setEname
                            //加入数据到对象
                            writeMethod.invoke(t, value);
                        }
                    }catch (Exception e){
                        continue;
                    }
                }
                //返回对象
                return t;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    ​

第三节 C3P0连接池

  • 配置文件

    c3p0.driverClass=com.mysql.jdbc.Driver
    c3p0.jdbcUrl=jdbc:mysql://localhost:3306/day20190824?useSSL=true&characterEncoding=utf8
    c3p0.user=root
    c3p0.password=123456
    c3p0.acquireIncrement=5
    c3p0.initialPoolSize=20
    c3p0.minPoolSize=10
    c3p0.maxPoolSize=40
  • 连接池

    package Day20190827.Day9连接池和Dbutils.utils;
    ​
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    import org.apache.commons.dbcp2.BasicDataSource;
    import org.apache.commons.dbcp2.BasicDataSourceFactory;
    ​
    import java.beans.IntrospectionException;
    import java.beans.PropertyDescriptor;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStream;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.sql.*;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Properties;
    ​
    /**
     * @Auther: xbh
     * @Date: 2019/8/26 14:28
     * @Description:
     * 四个功能
     * 1、注册驱动(一次)
     * 2、获取连接
     * 3、释放资源
     * 4、执行sql语句(增删改)
     */
    public class DbUtils_c3p0 {
        private static ComboPooledDataSource dataSource = null;
        //注册驱动(一次)
        static {
            try{
                //自动加载,不用引用,但是配置文件不能改
                dataSource = new ComboPooledDataSource();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        //获取连接
        public static Connection getConnection(){
            try {
                return  dataSource.getConnection();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }
        //释放资源
        public static void closeAll(Connection conn, Statement stat, ResultSet rs){
            if(rs!=null){
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(stat!=null){
                try {
                    stat.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        //sql语句
        public static int executeUpdate(String sql, Object...params){
            Connection conn = getConnection();
            PreparedStatement pstat = null;
            try {
                pstat = conn.prepareStatement(sql);
                //设置参数
                if(params!=null){
                    for (int i = 0; i < params.length; i++) {
                        pstat.setObject(i+1, params[i]);
                    }
                }
                return pstat.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                closeAll(conn,pstat,null);
            }
            return -1;
        }
    ​
        //返回list集合的方法
        public static <T>  List<T> findList(String sql,Class<T> class1, Object...params){
            List<T> list = new ArrayList<>();
            //从数据库查询数据
            Connection conn = null;
            PreparedStatement pstat = null;
            ResultSet rs = null;
            try{
                //获取连接
                conn = getConnection();
                //获取执行
                pstat = conn.prepareStatement(sql);
                //进行执行判断
                if(params != null){
                    for (int i = 0; i < params.length; i++) {
                        pstat.setObject(i+1, params[i]);
                    }
                }
                //执行语句
                rs = pstat.executeQuery();
                //获得表头
                ResultSetMetaData metaData = rs.getMetaData();
                while (rs.next()){
                    //获得对象
                    T t = convertToObject(metaData, rs, class1);
                    list.add(t);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                closeAll(conn, pstat, rs);
            }
            return list;
        }
    ​
        //返回单个对象的方法
        public static <T> T findSingle(String sql, Class<T> class1, Object...params){
            T t = null;
            //从数据库查询数据
            Connection conn = null;
            PreparedStatement pstat = null;
            ResultSet rs = null;
            try{
                conn = getConnection();
                pstat = conn.prepareStatement(sql);
                if(params != null){
                    for (int i = 0; i < params.length; i++) {
                        pstat.setObject(i+1, params[i]);
                    }
                }
                rs = pstat.executeQuery();
                ResultSetMetaData metaData = rs.getMetaData();
                if (rs.next()){
                    t = convertToObject(metaData, rs, class1);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                closeAll(conn, pstat, rs);
            }
            return  t;
        }
    ​
        public static <T> T convertToObject(ResultSetMetaData metaData, ResultSet rs, Class<T> class1){
            try {
                //映射对象
                T t = class1.newInstance();
                for (int i = 0; i < metaData.getColumnCount(); i++) {
                    //获得表头
                    String columnLabel = metaData.getColumnLabel(i + 1);
                    //获得表头下的数据
                    Object value = rs.getObject(columnLabel);//empno ename
                    try{
                        //内省解析属性描述符
                        PropertyDescriptor pd = new PropertyDescriptor(columnLabel, class1);
                        if (pd != null) {//属性描述符不空
                            //获取set方法
                            Method writeMethod = pd.getWriteMethod();//setEmpno setEname
                            //加入数据到对象
                            writeMethod.invoke(t, value);
                        }
                    }catch (Exception e){
                        continue;
                    }
                }
                //返回对象
                return t;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    ​

第四节 Druid连接池

  • 配置文件

    #连接设置
    driverClassName=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/day20190824?useSSL=true&characterEncoding=utf8
    username=root
    password=123456
    #<!-- 初始化连接 -->
    initialSize=10
    #最大连接数量
    maxActive=50
    #<!-- 最小空闲连接 -->
    minIdle=5
    #<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
    maxWait=5000
  • 连接池

    package Day20190827.Day9连接池和Dbutils.utils;
    ​
    import com.alibaba.druid.pool.DruidDataSource;
    import com.alibaba.druid.pool.DruidDataSourceFactory;
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    import org.apache.commons.dbcp2.BasicDataSource;
    import org.apache.commons.dbcp2.BasicDataSourceFactory;
    ​
    import java.beans.IntrospectionException;
    import java.beans.PropertyDescriptor;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStream;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.sql.*;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Properties;
    ​
    /**
     * @Auther: xbh
     * @Date: 2019/8/26 14:28
     * @Description:
     * 四个功能
     * 1、注册驱动(一次)
     * 2、获取连接
     * 3、释放资源
     * 4、执行sql语句(增删改)
     */
    public class DbUtils_Druid {
        private static DruidDataSource dataSource = null;
    ​
        //注册驱动(一次)
        static {
            Properties properties=new Properties();
    ​
            try{
                properties.load(DbUtils_Druid.class.getClassLoader().getResourceAsStream("druid.properties"));
                //自动加载,不用引用,但是配置文件不能改
                dataSource = (DruidDataSource)DruidDataSourceFactory.createDataSource(properties);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        //获取连接
        public static Connection getConnection(){
            try {
                return  dataSource.getConnection();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }
        //释放资源
        public static void closeAll(Connection conn, Statement stat, ResultSet rs){
            if(rs!=null){
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(stat!=null){
                try {
                    stat.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        //sql语句
        public static int executeUpdate(String sql, Object...params){
            Connection conn = getConnection();
            PreparedStatement pstat = null;
            try {
                pstat = conn.prepareStatement(sql);
                //设置参数
                if(params!=null){
                    for (int i = 0; i < params.length; i++) {
                        pstat.setObject(i+1, params[i]);
                    }
                }
                return pstat.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                closeAll(conn,pstat,null);
            }
            return -1;
        }
    ​
        //返回list集合的方法
        public static <T>  List<T> findList(String sql,Class<T> class1, Object...params){
            List<T> list = new ArrayList<>();
            //从数据库查询数据
            Connection conn = null;
            PreparedStatement pstat = null;
            ResultSet rs = null;
            try{
                //获取连接
                conn = getConnection();
                //获取执行
                pstat = conn.prepareStatement(sql);
                //进行执行判断
                if(params != null){
                    for (int i = 0; i < params.length; i++) {
                        pstat.setObject(i+1, params[i]);
                    }
                }
                //执行语句
                rs = pstat.executeQuery();
                //获得表头
                ResultSetMetaData metaData = rs.getMetaData();
                while (rs.next()){
                    //获得对象
                    T t = convertToObject(metaData, rs, class1);
                    list.add(t);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                closeAll(conn, pstat, rs);
            }
            return list;
        }
    ​
        //返回单个对象的方法
        public static <T> T findSingle(String sql, Class<T> class1, Object...params){
            T t = null;
            //从数据库查询数据
            Connection conn = null;
            PreparedStatement pstat = null;
            ResultSet rs = null;
            try{
                conn = getConnection();
                pstat = conn.prepareStatement(sql);
                if(params != null){
                    for (int i = 0; i < params.length; i++) {
                        pstat.setObject(i+1, params[i]);
                    }
                }
                rs = pstat.executeQuery();
                ResultSetMetaData metaData = rs.getMetaData();
                if (rs.next()){
                    t = convertToObject(metaData, rs, class1);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                closeAll(conn, pstat, rs);
            }
            return  t;
        }
    ​
        public static <T> T convertToObject(ResultSetMetaData metaData, ResultSet rs, Class<T> class1){
            try {
                //映射对象
                T t = class1.newInstance();
                for (int i = 0; i < metaData.getColumnCount(); i++) {
                    //获得表头
                    String columnLabel = metaData.getColumnLabel(i + 1);
                    //获得表头下的数据
                    Object value = rs.getObject(columnLabel);//empno ename
                    try{
                        //内省解析属性描述符
                        PropertyDescriptor pd = new PropertyDescriptor(columnLabel, class1);
                        if (pd != null) {//属性描述符不空
                            //获取set方法
                            Method writeMethod = pd.getWriteMethod();//setEmpno setEname
                            //加入数据到对象
                            writeMethod.invoke(t, value);
                        }
                    }catch (Exception e){
                        continue;
                    }
                }
                //返回对象
                return t;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    ​

第五节 DBUtils使用

5.1 DBUtils简介

DBUtils是java编程中的数据库操作实用工具,小巧简单实用,

1.对于数据表的读操作,可以把结果转换成List,Array,Set等java集合,便于程序员操作。

2.对于数据表的写操作,也变得很简单(只需写sql语句)。

DBUtils包括主要类

DbUtils类:启动类

ResultSetHandler接口:转换类型接口

--ArrayHandler类:实现类,把记录转化成数组

--ArrayListHandler类:把记录转化成数组,并放入集合中

--ColumnListHandler类:取某一列的数据。封装到List中。

--ScalarHandler类:适合获取一行一列数据。

--BeanHandler类:实现类,把记录转成对象。

--BeanListHandler类:实现类,把记录转化成List,使记录为JavaBean类型的对象

QueryRunner类:执行SQL语句的类

完整项目

  • StudentDao

    package Day20190826.Day8Task.impl;
    ​
    import Day20190826.Day8Task.domain.Student;
    ​
    import java.util.List;
    ​
    /**
     * @Auther: xbh
     * @Date: 2019/8/27 19:24
     * @Description:
     */
    public interface StudentDao {
        public List<Student> findList();
    ​
        public Student findById(Integer sid);
    ​
        public void add(Student student);
    ​
        public void update(Student student);
    ​
        public void delete(Integer sid);
    }
  • StudentDaoImpl

    package Day20190826.Day8Task.dao;
    ​
    import Day20190826.Day8Task.domain.Student;
    import Day20190826.Day8Task.impl.StudentDao;
    import Day20190826.Day8Task.utils.DbUtils_Druid;
    ​
    import java.util.List;
    ​
    /**
     * @Auther: xbh
     * @Date: 2019/8/27 19:35
     * @Description:
     */
    public class StudentDaoImpl implements StudentDao {
    ​
        @Override
        public List<Student> findList() {
            List<Student> list = DbUtils_Druid.findList("select * from student",Student.class, null);
            return list;
        }
    ​
        @Override
        public Student findById(Integer sid) {
            Student student = DbUtils_Druid.findSingle("select * from emp where empno=?", Student.class, sid);
            return student;
        }
    ​
        @Override
        public void add(Student student) {
            Object[] params = {student.getSid(), student.getSname()};
            int i = DbUtils_Druid.executeUpdate("insert into student(sid, sname) values(?,?)", params);
            System.out.println(i);
        }
    ​
        @Override
        public void update(Student student) {
            Object[] params = {student.getSid(), student.getSname()};
            int i = DbUtils_Druid.executeUpdate("update student set sname=? where sid=?", params);
            System.out.println(i);
        }
    ​
        @Override
        public void delete(Integer sid) {
            int i = DbUtils_Druid.executeUpdate("delete from student where sid=?", sid);
            System.out.println(i);
        }
    }
    ​
  • Student

    package Day20190826.Day8Task.domain;
    ​
    /**
     * @Auther: xbh
     * @Date: 2019/8/27 19:25
     * @Description:
     */
    public class Student {
        int sid;
        String sname;
    ​
        public Student() {
        }
    ​
        public Student(int sid, String sname) {
            this.sid = sid;
            this.sname = sname;
        }
    ​
        public int getSid() {
            return sid;
        }
    ​
        public void setSid(int sid) {
            this.sid = sid;
        }
    ​
        public String getSname() {
            return sname;
        }
    ​
        public void setSname(String sname) {
            this.sname = sname;
        }
    ​
        @Override
        public String toString() {
            return "Student{" +
                    "sid=" + sid +
                    ", sname='" + sname + '\'' +
                    '}';
        }
    }
    ​
  • DbUtils_Druid

    package Day20190826.Day8Task.utils;
    ​
    import com.alibaba.druid.pool.DruidDataSource;
    import com.alibaba.druid.pool.DruidDataSourceFactory;
    ​
    import java.beans.PropertyDescriptor;
    import java.lang.reflect.Method;
    import java.sql.*;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Properties;
    ​
    /**
     * @Auther: xbh
     * @Date: 2019/8/27 19:36
     * @Description:
     */
    public class DbUtils_Druid {
        private static DruidDataSource dataSource = null;
    ​
        //注册驱动(一次)
        static {
            Properties properties=new Properties();
    ​
            try{
                properties.load(DbUtils_Druid.class.getClassLoader().getResourceAsStream("studruid.properties"));
                //自动加载,不用引用,但是配置文件不能改
                dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        //获取连接
        public static Connection getConnection(){
            try {
                return  dataSource.getConnection();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }
        //释放资源
        public static void closeAll(Connection conn, Statement stat, ResultSet rs){
            if(rs!=null){
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(stat!=null){
                try {
                    stat.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        //sql语句
        public static int executeUpdate(String sql, Object...params){
            Connection conn = getConnection();
            PreparedStatement pstat = null;
            try {
                pstat = conn.prepareStatement(sql);
                //设置参数
                if(params!=null){
                    for (int i = 0; i < params.length; i++) {
                        pstat.setObject(i+1, params[i]);
                    }
                }
                return pstat.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                closeAll(conn,pstat,null);
            }
            return -1;
        }
    ​
        //返回list集合的方法
        public static <T> List<T> findList(String sql, Class<T> class1, Object...params){
            List<T> list = new ArrayList<>();
            //从数据库查询数据
            Connection conn = null;
            PreparedStatement pstat = null;
            ResultSet rs = null;
            try{
                //获取连接
                conn = getConnection();
                //获取执行
                pstat = conn.prepareStatement(sql);
                //进行执行判断
                if(params != null){
                    for (int i = 0; i < params.length; i++) {
                        pstat.setObject(i+1, params[i]);
                    }
                }
                //执行语句
                rs = pstat.executeQuery();
                //获得表头
                ResultSetMetaData metaData = rs.getMetaData();
                while (rs.next()){
                    //获得对象
                    T t = convertToObject(metaData, rs, class1);
                    list.add(t);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                closeAll(conn, pstat, rs);
            }
            return list;
        }
    ​
        //返回单个对象的方法
        public static <T> T findSingle(String sql, Class<T> class1, Object...params){
            T t = null;
            //从数据库查询数据
            Connection conn = null;
            PreparedStatement pstat = null;
            ResultSet rs = null;
            try{
                conn = getConnection();
                pstat = conn.prepareStatement(sql);
                if(params != null){
                    for (int i = 0; i < params.length; i++) {
                        pstat.setObject(i+1, params[i]);
                    }
                }
                rs = pstat.executeQuery();
                ResultSetMetaData metaData = rs.getMetaData();
                if (rs.next()){
                    t = convertToObject(metaData, rs, class1);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                closeAll(conn, pstat, rs);
            }
            return  t;
        }
    ​
        public static <T> T convertToObject(ResultSetMetaData metaData, ResultSet rs, Class<T> class1){
            try {
                //映射对象
                T t = class1.newInstance();
                for (int i = 0; i < metaData.getColumnCount(); i++) {
                    //获得表头
                    String columnLabel = metaData.getColumnLabel(i + 1);
                    //获得表头下的数据
                    Object value = rs.getObject(columnLabel);//empno ename
                    try{
                        //内省解析属性描述符
                        PropertyDescriptor pd = new PropertyDescriptor(columnLabel, class1);
                        if (pd != null) {//属性描述符不空
                            //获取set方法
                            Method writeMethod = pd.getWriteMethod();//setEmpno setEname
                            //加入数据到对象
                            writeMethod.invoke(t, value);
                        }
                    }catch (Exception e){
                        continue;
                    }
                }
                //返回对象
                return t;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    ​
    • EmpDaoImpl

      package Day20190827.Day9Dutils.dao;
      ​
      import Day20190827.Day9Dutils.Impl.EmpDao;
      import Day20190827.Day9Dutils.domain.Emp;
      import Day20190827.Day9Dutils.utils.DataSourseUtils;
      import org.apache.commons.dbutils.QueryRunner;
      import org.apache.commons.dbutils.handlers.*;
      ​
      import java.sql.SQLException;
      import java.util.List;
      ​
      /**
       * @Auther: xbh
       * @Date: 2019/8/28 09:32
       * @Description:
       */
      public class EmpDaoImpl implements EmpDao {
      ​
          @Override
          public List<Emp> findAll() {//ctrl + H 查看实现类
              QueryRunner qr = new QueryRunner(DataSourseUtils.getDataSource());
              try {
                  return  qr.query("select * from emp", new BeanListHandler<Emp>(Emp.class));
              } catch (SQLException e) {
                  e.printStackTrace();
                  throw new RuntimeException("查询失败");
              }
          }
      ​
          @Override
          public Emp findByEmpno(Integer empno) {
              QueryRunner qr = new QueryRunner(DataSourseUtils.getDataSource());
              try {
                  return  qr.query("select * from emp where empno=?", new BeanHandler<Emp>(Emp.class),empno);
              } catch (SQLException e) {
                  e.printStackTrace();
                  throw new RuntimeException("查询失败");
              }
          }
      ​
          @Override
          public void add(Emp emp) {
              //创建查询执行器
              QueryRunner qr = new QueryRunner(DataSourseUtils.getDataSource());
              Object[] params = {emp.getEmpno(), emp.getEname(),emp.getJob(),emp.getMgr(),emp.getHiredate(),emp.getSal(),emp.getComm(),emp.getDeptno()};
              try {
                  qr.update("insert into emp values(?,?,?,?,?,?,?,?)", params);
              } catch (SQLException e) {
                  e.printStackTrace();
              }
          }
      ​
          @Override
          public void update(Emp emp) {
              QueryRunner qr = new QueryRunner(DataSourseUtils.getDataSource());
              Object[] params = {emp.getEname(),emp.getJob(),emp.getMgr(),emp.getHiredate(),emp.getSal(),emp.getComm(),emp.getDeptno(),emp.getEmpno()};
              try {
                  qr.update("update emp set ename=?,job=?,mgr=?,hiredate=?,sal=?,comm=?,deptno=? where empno=?", params);
              } catch (SQLException e) {
                  e.printStackTrace();
              }
          }
      ​
          @Override
          public void delete(Integer empno) {
              //"delete from emp where empno=?", empno
              QueryRunner qr = new QueryRunner(DataSourseUtils.getDataSource());
              try {
                  qr.update("delete from emp where empno=?", empno);
              } catch (SQLException e) {
                  e.printStackTrace();
              }
          }
      ​
          @Override
          public long getCount() {
              QueryRunner qr = new QueryRunner(DataSourseUtils.getDataSource());
              Long count = null;
              try {
                  count = (Long)qr.query("select count(*) from emp", new ScalarHandler<>());
                  return count;
              } catch (SQLException e) {
                  e.printStackTrace();
              }
              return count;
          }
          @Override
          public Object[] findArrayEmp(Integer empno){
              QueryRunner qr = new QueryRunner(DataSourseUtils.getDataSource());
              try {
                  return qr.query("select * from emp where empno=?", new ArrayHandler(),empno);
              } catch (SQLException e) {
                  e.printStackTrace();
                  new RuntimeException("查询失败");
              }
              return null;
          }
          @Override
          public List<Object[]> findArrayListEmp(){
              QueryRunner qr = new QueryRunner(DataSourseUtils.getDataSource());
              try {
                  return qr.query("select * from emp", new ArrayListHandler());
              } catch (SQLException e) {
                  e.printStackTrace();
                  new RuntimeException("查询失败");
              }
              return null;
          }
          @Override
          public List<String> findNames(){
              QueryRunner qr = new QueryRunner(DataSourseUtils.getDataSource());
              try {
                  return qr.query("select * from emp", new ColumnListHandler<String>("ename"));
              } catch (SQLException e) {
                  e.printStackTrace();
              }
              return null;
          }
      }
      ​
    • DataSourseUtils

      package Day20190827.Day9Dutils.utils;
      ​
      import com.alibaba.druid.pool.DruidDataSource;
      import com.alibaba.druid.pool.DruidDataSourceFactory;
      ​
      import java.io.IOException;
      import java.io.InputStream;
      import java.util.Properties;
      ​
      /**
       * @Auther: xbh
       * @Date: 2019/8/28 09:24
       * @Description:
       */
      public class DataSourseUtils {
          private static DruidDataSource dataSource;
          static {
             try{
                 Properties properties = new Properties();
                 InputStream is = DataSourseUtils.class.getClassLoader().getResourceAsStream("druid.properties");
                 properties.load(is);
                 dataSource = (DruidDataSource)DruidDataSourceFactory.createDataSource(properties);
             } catch (IOException e) {
                 e.printStackTrace();
             } catch (Exception e) {
                 e.printStackTrace();
             }
          }
      ​
          public static  DruidDataSource getDataSource(){
              return dataSource;
          }
      }
      ​

       

小结

1 封装工具类

2 Dao设计模式: 把数据访问代码抽离出来。降低代码的耦合性和提高扩展性。

dao接口

dao实现

实体类

数据库工具类

3 连接池

dbcp

c3p0

druid重点

4 Dbutils工具


第十天 Tomcat配置及创建web项目

第一节 Web应用的演变

  • 自定义web服务器

    package com.qf.day10;
    ​
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    ​
    /**
     * 自定义服务器
     * @author wgy
     *
     */
    public class MyServer {
        public static void main(String[] args) {
            try {
                //1创建侦听套接字
                ServerSocket listener=new ServerSocket(10086);
                //2接收客户端请求
                System.out.println("客户端已启动....");
                Socket socket=listener.accept();
                //3获取输出流
                OutputStream os=socket.getOutputStream();
                
                //4创建FileInputStream
                FileInputStream fis=new FileInputStream("d:\\mywork\\hello.html");
                
                byte[] buf=new byte[1024*4];
                int len=0;
                while((len=fis.read(buf))!=-1) {
                    os.write(buf,0,len);
                    os.flush();
                }
                //5关闭
                fis.close();
                os.close();
                socket.close();
                listener.close();
                
                System.out.println("服务器执行完毕...");
                
                
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

第二节 Tomcat服务器搭建

  • tomcat目录介绍

    1、bin:该目录下存放的是二进制可执行文件,如果是安装版,那么这个目录下会有两个exe文件:tomcat9.exe、tomcat9w.exe,前者是在控制台下启动Tomcat,后者是弹出UGI窗口启动Tomcat;如果是解压版,那么会有startup.bat和shutdown.bat文件,startup.bat用来启动Tomcat,但需要JDK的配置,shutdawn.bat用来停止Tomcat;
    ​
    2、conf:这是一个非常非常重要的目录,这个目录下有四个最为重要的文件:
    ​
    server.xml:配置整个服务器信息。例如修改端口号,添加虚拟主机等;
    ​
    tomcatusers.xml:存储tomcat用户的文件,这里保存的是tomcat的用户名及密码,以及用户的角色信息。可以按着该文件中的注释信息添加tomcat用户,然后就可以在Tomcat主页中进入Tomcat Manager页面了;
    ​
    web.xml:部署描述符文件,这个文件中注册了很多MIME类型,即文档类型。这些MIME类型是客户端与服务器之间说明文档类型的,如用户请求一个html网页,那么服务器还会告诉客户端浏览器响应的文档是text/html类型的,这就是一个MIME类型。客户端浏览器通过这个MIME类型就知道如何处理它了。当然是在浏览器中显示这个html文件了。但如果服务器响应的是一个exe文件,那么浏览器就不可能显示它,而是应该弹出下载窗口才对。MIME就是用来说明文档的内容是什么类型的!
    ​
    context.xml:对所有应用的统一配置,通常我们不会去配置它。
    ​
    3、lib:Tomcat的类库,里面是一大堆jar文件。如果需要添加Tomcat依赖的jar文件,可以把它放到这个目录中,当然也可以把应用依赖的jar文件放到这个目录中,这个目录中的jar所有项目都可以共享之,但这样你的应用放到其他Tomcat下时就不能再共享这个目录下的Jar包了,所以建议只把Tomcat需要的Jar包放到这个目录下;
    ​
    4、logs:这个目录中都是日志文件,记录了Tomcat启动和关闭的信息,如果启动Tomcat时有错误,那么异常也会记录在日志文件中。
    ​
    5、temp:存放Tomcat的临时文件,这个目录下的东西可以在停止Tomcat后删除!
    ​
    6、webapps:存放web项目的目录,其中每个文件夹都是一个项目;如果这个目录下已经存在了目录,那么都是tomcat自带的项目。其中ROOT是一个特殊的项目,在地址栏中没有给出项目目录时,对应的就是ROOT项目。http://localhost:8080/examples,进入示例项目。其中examples就是项目名,即文件夹的名字。
    ​
    7、work:运行时生成的文件,最终运行的文件都在这里。通过webapps中的项目生成的!可以把这个目录下的内容删除,再次运行时会生再次生成work目录。当客户端用户访问一个JSP文件时,Tomcat会通过JSP生成Java文件,然后再编译Java文件生成class文件,生成的java和class文件都会存放到这个目录下。
    ​
    8、LICENSE:许可证。
    ​
    9、NOTICE:说明文件。
  • idea 关联tomcat

    1. 添加tomcat服务

      file->setting->Build,Execution,Deployment->Application Servers->点击+添加tomcat

    2. new project->Java Enterprise->JavaEE7 并且勾选Web Application创建成功

  • idea打war包

    1. file->ProjectStructure->Project Setting->Artifacts->点击+->Web Application Archive->for XXX:war exploded

    2. Build->Build Project

第三节xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
​
    <!--配置项目名称-->
    <display-name>project2_2</display-name>
    <!--web应用描述-->
    <description>this is my first web</description>
    <!--配置网站首页,默认有index.html-->
    <welcome-file-list>
        <welcome-file>hello.html</welcome-file>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
​
    <!--网站错误页面-->
    <error-page>
        <error-code>404</error-code>
        <!--别忘了加 / -->
        <location>/404.html</location>
    </error-page>
​
    <error-page>
        <error-code>500</error-code>
        <!--别忘了加 / -->
        <location>/500.jsp</location>
    </error-page>
</web-app>

 

转载于:https://my.oschina.net/mumaniu/blog/3097800

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值