JAVA(六)数据库/网络编程/新IO
成鹏致远 | lcw.cnblog.com |2014-02-05
数据库
1.JDBC概述
- JDBC(Java Database Connectivity,Java数据库连接)提供了一种与平台无关的用于执行 SQL语句的标准 Java API,可以方便的实现多种关系型数据库的统一操作,它由一组用 Java语言编写的类和接口组成
- 在 JDBC中提供的是一套标准的接口,这样,各个支持 JAVA的数据库生产商只要按照此接口提供相应的实现,则就可以使用 JDBC进行操作,极大的体现了 JAVA的可移植性设计思想
- 在 JDBC中所有的类和接口都保存在 java.sql包中,在此包中规定了大量的接口
- JDBC本身提供的是一套数据库操作标准,而这些标准又需要各个数据库厂商实现,所以针对于每一个数据库厂商都会提供一个 JDBC的驱动程序,目前比较常见的 JDBC驱动程序可以分为四类
- JDBC-ODBC桥驱动
- JDBC本地驱动
- JDBC网络驱动
- 本地协议纯JDBC驱动
- 但是一般在开发中会将以上的四类简单的分为三类
- JDBC-ODBC
- 纯 JDBC连接
- 网络的 JDBC连接
- JDBC-ODBC桥驱动
- 是 SUN提供的一个标准的 JDBC操作,直接利用微软的 ODBC进行数据库的连接操作
- 这个操作性能较低
- 通常情况下不推荐使用这种方式进行操作
- JDBC本地驱动
- 直接使用各个数据库生产商提供的 JDBC驱动程序,因为只能应用在特定的数据库上,会丧失掉程序的可移植性,但是这样的操作的性能较高
- JDBC本身提供的是一组类和接口,那么各个数据库生产商要实现这些接口,所以这些驱动程序都是需要单独配置的,往往是以一组 jar包(zip包)的形式出现的,如果要使用的话,则肯定要配置 classpath
- 在开发中大部分情况都是基于一种数据库的开发,所以一般使用此种模式是最多的
- JDBC网络驱动
- 这个驱动将 JDBC转换为与 DBMS无关的网络协议,之后这种协议又被某个服务器转换为一种 DBMS协议
- 这种网络服务器中间件能够将它的纯 Java客户机连接到多种不同的数据库上
- 所用的具体协议取决于提供者
- 通过,这是最为灵活的 JDBC驱动程序
- 本地协议纯 JDBC驱动
- 这种类型的驱动程序将 JDBC调用直接转换为 DBMS所使用的网络协议
- 这将允许从客户机机器上直接调用 DBMS服务器,是 Internet访问的一个很实用的解决方法
- 数据库的操作过程
- 打开数据库的服务
- 连接数据库,连接的时候一般都要输入用户名和密码
- 操作数据库:创建表、查询表、更新记录
- 关闭
- Java操作类
- DriverManager:是一个最常用的类,使用此类可以取得一个数据库的连接
- Connection:每一个 Connection的实例化对象都表示一个数据库连接
- 数据库的操作:Statement、PreparedStatement
- 数据库的查询:ResultSet
- 调用存储过程:CallableStatement
- 小结
- JDBC的概念及作用
- JDBC的主要分类
- 主要操作类和接口
2.Mysql数据库
- 数据库的端口号是 3306,以后的 JDBC要想连接数据库的时候必须使用此端口
- 手工选择配置的数据库编码是 GBK
- 小结
- 会安装及配置 MySQL数据库(服务、命令、编码)
- 基本的命令(连接、建库、建表、删除库、删除表)
3.SQL语法基础
- SQL(Structured Query Language,结构查询语言)
- SQL功能强大,概括起来,可以分成以下几组
- DML(Data Manipulation Language,数据操作语言):用于检索或者修改数据
- DDL(Data Definition Language,数据定义语言):用于定义数据的结构,如创建、修改或者删除数据库对象
- DCL(Data Control Language,数据控制语言):用于定义数据库用户的权限
- MySQL中的数据类型
- 对于数据库操作而言,查询是最复杂的,查询分为以下几种
- 简单查询
- 限定查询,指定查询的条件
- 多表查询
- 分组查询
- 子查询
- 父、并、补
- 在开发中,有一种情况:查询部分数据,这在系统的分布程序中经常使用:Limit
- 小结
- 熟练掌握增加、修改、删除、简单查询的语句
- LIMIT语句,可以执行部分的查询
4.JDBC操作步骤及数据库连接操作
- JDBC本身是一个标准,所以其操作步骤是固定的,以后只需要修改很少的一部分代码就可以达到不同数据库间的连接转换功能
- JDBC操作步骤
- 加载数据库驱动程序
- 连接数据库
- 使用语句进行数据库操作
- 关闭数据库连接
- 配置数据库的驱动程序
- 数据库的驱动程序是由各个数据库生产商提供,只要在 JAVA中要想连接数据库,则肯定各个 DB要有所支持
- 将下载好的驱动程序放在 C盘目录中,所以此时直接修改 CLASSPATH即可,在 windows中的环境变量中直接修改即可,如果没有 classpath则自己增加一个新的
- 加载驱动程序
- 通过 Class.forName()语句可以加载一个驱动程序
- Class实例化需要一个完整的包.类名称,此:“包.类”名称的路径就应该是驱动程序的名称
- 如果出现找不到类,就表示 classpath配置有问题,查看 classpath的配置
- 连接及关闭数据库
- 在连接的时候肯定需要一个连接地址,这些连接地址将由各个数据库生产商提供
- DriverManager说明
- 在 DriverManager中,提供的主要操作就是得到一个数据库的连接
- getConnection()方法就是取得连接对象,此方法返回的类型是 Connection对象
- 不管使用哪种方式连接,都必须提供一个数据库的连接地址,如果在连接数据库的时候需要用户名和密码,则还需要将用户名和密码设置上
- 数据库连接地址的形式
- JDBC虽然提供了与平台无关的数据库操作,但是各个数据库的连接地址是有差异的,JDBC的连接地址实际上是由以下的三个部分组成
- jdbc协议:JDBC URL中的协议总是 jdbc
- 子协议:驱动程序名或数据库连接机制(这种机制可由一个或多个驱动程序支持)的名称,例如:mysql
- 子名称:一种标识数据库的方法。必须遵循“//主机名:端口/子协议”的标准 URL命名约定,例如://localhost:3306/mysql_db
- Connection
- 通过 DriverManager取得 Collection对象之后,实际上就表示数据库连接上了,连接上了数据库之后就可以进行数据库的更新及查询操作
- 操作的最后数据库连接必须关闭
- 小结
- JDBC连接各个数据库必须配置驱动程序
- JDBC的操作步骤
- 数据的连接操作,连接之后数据必须关闭
5.执行数据库更新操作
- Statement接口
- 数据库连接之后,下面就可以进行数据库的具体操作了,如果要想对数据库进行操作,则肯定要使用 Statement接口完成
- 此接口可以使用 Connection接口中提供的 createStatement()方法实例化
- 所有的操作都必须从连接展开,通过连接取得操作接口的实例
- 小结
- 总结出 JDBC的操作的流程
- 观察 Statement进行数据库更新的操作:增加、修改、删除
6.ResultSet接口
- 数据库的操作主要是分为更新和查询操作,查询操作时候会将全部的查询结果返回给用户
- ResultSet接口
- 使用 SQL中的 Select语句可以将数据库的全部结果查询出来,在 JDBC的操作中数据库的所有查询记录将使用 ResultSet进行接收,并使用 ResultSet显示内容
- 在操作的时候使用 Statement中的 executeQuery()方法进行数据库的查询操作,此方法的返回值就是 ResultSet接口
- 小结
- ResultSet查询时是将全部的查询结果以 ResultSet的形式返回
- 通过 ResultSet接口依次取出里面的全部内容
- 所有的查询结果实际上最终都是保存在内存之中,所以对于数据库的查询操作来讲,尽量不要全部查询
7.PreparedStatement接口
- PreparedStatement是 Statement的子接口,属于预处理操作
- 与直接使用 Statement不同的是:PreparedStatement在操作时,是先在数据表之中准备好了一条 SQL语句,但是此 SQL语句的具体内容暂不设置,而是之后再进行设置
- 通过连接对象 Connection得到一个 PreparedStatement的接口实例:PreparedStatement prepareStatemet(String sql) throws SQLException
- 之后使用一系列的 setXxx()方法设置内容,根据位置设置
- 如果执行更新语句的话,则会返回更新数据的记录数
- 【注意】关于日期的输入问题:在正常情况下都使用 java.util.Date表示日期,但是在 PreparedStatement中如果要想使用日期则必须使用 java.sql.Date类型
- 如果只是查询,不需要设置任何内容的话,只需要创建完 PreparedStatement对象后直接查询即可
- 【问题】在开发中到底是使用 PreparedStatement还是使用 Statement接口呢
- 实际上在开发应用中是不会使用 Statement接口的
- 因为其采用的是拼凑的 SQL语句形式,那么这样一来就可以造成 SQL的注入漏洞
- 小结
- PreparedStatement的基本工作原理,插入时,先点位,之后再设置内容
- 开发中建议不要使用 Statement接口,而使用 PreparedStatement接口完成
8.事务处理
- 事务:就是保证操作的一致性,所有的操作要么全部成功,要么全部失败
- 事务本身具有:原子性、一致性、隔离性或独立性、持久性四个特征,也被称为 ACID特征
- 原子性:事务的最小的单元,是不可再分割的单元,相当于一个个小的数据库操作,这些操作必须同时完成,如果有一个失败了,则一切的操作将全部失败
- 一致性:指在库操作的前后是完全一致的,保证数据的有效性,如果事务正常操作则系统会维持有效性,如果事务出现了错误,则回到最原始状态,也要维持其有效性,这样保证事务开始时和结束时系统处于一致状态
- 隔离性:多个事务可以同时进行且彼此之间无法访问,只有当事务完成最终操作的时候,才可以看见结果
- 持久性:当一个系统崩溃时,一个事务依然可以坚持提交,当一个事务完成后,操作的结果保存在磁盘中,永远不会被回滚
- MySQL对事务的支持
- 操作事务步骤
- 取消掉自动提交:每次执行数据库更新的时候实际上发出 SQL命令之后就已经提交上去
- 开始事务
- 进行一系列的操作
- 如果操作全部合格,则提交事务
- 如果发现有一个地方有问题,则可以进行回滚
- 或者设置一个 SAVEPOINT保存事务的提交点
- 默认情况下所有的回滚,就是将全部的操作取消掉,而通过 SavePoint可以设置回退的位置
- 小结
- 事务的基本概念,如何在数据库中处理事务
- JDBC操作事务的步骤
- 取消掉自动提交
- 执行多条 SQL语句
- 如果没有异常,则提交事务
- 否则则进行事务的回滚操作
- 保存点操作一般来说不是很常用
网络编程
1.IP(InternetProtocol)与InetAddress
- 在 java中支持网络通讯程序的开发,主要提供了两种通讯协议:TCP协议、UDP协议
- 可靠的连接传输,使用三方握手的方式完成通讯
- 不可靠的连接传输,传输的时候接收方不一定可以接收的到
- 在 java中的所有网络程序的开发类都在 java.net包中存在
- 对于网络上,每一台计算机也有自己名字,那么这个名字就称为 IP地址
- IP地址格式
- IP地址=网络地址 +主机地址
- 网络号:用于识别主机所在的网络
- 主机号:用于识别该网络中的主机
- IP地址中存在掩码的功能主要是区分网络号和主机号
- 在实际中可以使用 127.0.0.1表示本机地址,或者直接使用 localhost也代表本机
- InetAddress类主要表示 IP地址,这个类有两个子类
- Inet4Address:表示 IPV4协议
- Inet6Address:表示 IPV6协议
- InetAddress类的构造方法被隐藏起来了
- 小结
- 了解 IP地址的作用
- 掌握 InetAddress类的使用
2.URL与URLConnection
- URL(Uniform Resource Locator)统一资源定位符,可以直接使用此类找到互联网上的资源(如:一个简单的网页)
- 构造方法:public URL(String protocol, String host, int port, String file) throws MalformedURLException
- 取得整个页面的输入流:public final InputStream openStream() throws IOException
- URLConnection
- 是封装访问远程网络资源一般方法的类
- 通过它可以建立与远程服务器的连接,检查远程资源的一些属性
3.UTLEncoder与URLDecoder
- Encoder最早是从电报中而来
- 使用 Encoder进行编码
- 使用 Decoder进行解码
- 在网络中经常存在编码和解码的操作
- 一般在进行网络程序开发时,传递中文的时候往往会需要进行编码和解码的操作
4.TCP
- 在 Java中使用 Socket(即套接字)完成 TCP程序的开发,使用此类可以方便的建立可靠的、双向的、持续的、点对点的通讯连接
- 在 Socket的程序开发中,服务器端使用 ServerSocket等待客户端的连接,对于 Java的网络程序来讲,每一个客户端都使用一个 Socket对象表示
- 在 JAVA的网络程序中,客户端只要符合连接的通讯协议,那么服务器端都可以进行接收
- ServerSocket:主要用在服务器端程序的开发上,用于接收客户端的连接请求
- 在服务器端每次运行时都要使用 aceept()方法等待客户端连接,此方法执行之后服务器端进入阻塞状态,直到客户端连接之后程序才可以向下继续执行,此方法的返回值类型是 Socket,每一个 Socket都表示一个客户端对象
- 实例化 Socket类的时候要指定服务器的主机地址和端口号
- 服务器/客户端程序需要编写两套代码才可以完成网络的开发,那么实际上这个就表示的是 C/S架构,服务器/客户端,所以一般这种程序要同时维护两套代码
- 还有另外一套架构:B/S,浏览器/服务器,WEB开发的时候,这样的程序只需要维护一套代码即可
- 小结
- TCP程序的开发
- 服务器端的输出就是客户端的输入,客户端的输出就是服务器端的输入
- 多线程在实际开发中的作用
5.UDP
- 在 TCP的所有操作都必须建立可靠的连接,这样一来肯定会浪费大量的系统性能,为了减少这种开销,在网络中又提供了另外一种传输协议:UDP
- UDP:不可靠的连接,这种协议在各个聊天工具中被广泛的应用
- UDP开发中使用 DatagramPacket包装一条要发送的信息,之后使用 DatagramSocket用于完成信息的发送操作
- UDP中主要是使用数据报协议发送的
- 包含真实的要发送的信息,称为数据报
- 小结
- UDP属于不可靠的连接协议,服务器发送的信息客户端未必接收得到
- UDP采用数据报的协议发送
- DatagramSocket和 DatagramPacket类的作用
新IO
1.缓冲区与Buffer
- 在 JDK1.4之后为了提升 IO的操作性能,也就是说为了提升服务器操作的性能,提供了一个新的开发包,NIO,此包定义在 java.nio.*中
- 在整个 Java中,已有的 IO操作大部分都属于阻塞操作,例如:键盘输入数据,必须一直等待用户输入数据,否则程序无法向下继续执行,还有 Socket程序中所有的服务器必须通过 accept()方法一直等待用户的连接,那么这样一来肯定会造成大量的系统资源浪费,所以在 Java的 JDK1.4之后增加了 NIO,在整个新 IO的操作中基本上都是使用缓冲区完成的
- 在整个 Java的新 IO中,所有的操作都是以缓冲区进行的,既然使用了缓冲区,则操作的性能将是最高的
- 新 IO基本上都是针对于基本数据类型的操作,但是没有 boolean类型
- 在使用缓冲区的时候里面有一个变量是非常有用处的
- position、limit、capacity
- 这三个变量完成了缓冲区的操作代码
- position:表示下一个缓冲区读取或写入的操作指针,每向缓冲区中写入数据的时候此指针就会改变,指针永远放到写入的最后一个元素之后
- limit:表示还有多少数据需要存储或读取,position<=limit
- capacity:表示缓冲区的最大容量,limit<=capacity。此值在分配缓冲区时被设置,一般不会更改
- 可以在一个缓冲区中创建子缓冲区:slice(),长度为 position与 limit之间
- 子缓冲区是可以修改数据的
- 如果创建的缓冲区不希望被修改,则可以创建只读缓冲区:asReadOnlyBuffer()
- 在缓冲区还有一种称为直接缓冲区:如果创建了直接缓冲区,则 JVM将尽最大努力直接对其执行本机的 IO操作:public static ByteBuffer allocateDirect(int capacity)
- 小结
- NIO中都是以缓冲区进行操作的
- 缓冲区针对于各个基本数据类型都有实现,除了 Boolean类型之外
- 缓冲区中存在 position、limit、capacity三个状态变量
- 缓冲区的操作中通过 allocate()创建缓冲区,或使用只读、直接缓冲区
2.通道(Channel)
- 在新 IO中通道是一个可以用读取和写入数据的一种形式
- 通道可以用来读取和写入数据,通道类似于之前的输入/输出流,但是程序不会直接操作通道的,所有的内容都是先读到或写入到缓冲区之中,再通过缓冲区中取得或写入的
- 通道与传统的流操作不同,传统的流操作是分为输入或输出流的,而通道本身是双向操作的,即可以完成输入也可以完成输出的,即:通道都是操作缓冲区完成全部的功能的
- 可以使用 FileChannel()完成文件的双向操作
- 通道可以完成双向的输入和输出操作
- 在通道中还有一种方式称为内存映射
- 在几种读入的方式中
- RandomAccessFile:较慢
- FileOutputStream:较慢
- 缓冲读取:速度较快
- 内存映射:速度最快
- MappedByteBuffer:使用此种方式读取的内容是最快的
- 需要将一个输入的操作流绑定在内存映射
- 内存映射在读取的时候是最快的,但是执行写入操作则有可能是非常危险的,因为仅仅只是改变数组中的单个元素这种简单的操作,就可以会直接修改磁盘上的文件,因为修改数据与将数据保存在磁盘上是一样的
- 小结
- 通道的作用,明白通道是双向的,可读、可写
- 内存映射读取的时候速度是最快的
- 通道的操作都是以缓冲区为主的
3.文件锁:FileLock
- 在 Java新 IO中提供了文件锁的功能,这样不一个线程将文件锁定之后,其它线程是无法操作此文件的
- 要想进行文件的锁定操作,则要使用 FileLock类完成,此类的对象需要依靠 FileChannel进行实例化操作
- 关于锁定的方式:
- 共享锁:允许多个线程进行文件的读取操作
- 独占锁:只允许一个线程进行文件的读/写操作
- 小结
- FileLock类的基本操作
- 通过通道取得 FileLock的实例化对象
4.字符集
- 在整个 nio中,对于不同的平台的编码操作,java都可以进行自动的适应,因为可以使用字符集进行字符编码的转换操作
- 字符集:Charset
- 在 Java语言中所有的信息都是以 UNICODE进行编码的
- 但是在计算机的世界里并不只单单存在一种编码,而是多个,而且要是对编码处理不好的,则就有可能产生乱码
- 在 Java的新 IO包中提供了 Charset类来负责处理编码的问题,该类还包含了创建编码器(CharsetEncoder)和创建解码器(CharsetDecoder)的操作
- 一般在读取文件的时候会按照指定的格式解码,之后将解码后的文件内容重新编码后输出
- 小结
- Charset类的作用
- 编码和解码的操作
5.Selector
- 之前的 Socket程序在运行的时候,服务器必须始终等待着客户端的连接,那么此时就会造成大量的资源浪费,所以引入了非阻塞的 IO操作,此时就可以通过 Selector完成
- 实际上在 NIO中主要的功能是解决服务器端的通讯性能
- 使用 Selector可以构建一个非阻塞的网络服务
- 在新 IO中实现网络程序需要依靠 ServerSocketChannel类与 SocketChannel类
- 小结
- 在实际开发中使用 Selector较少
- 但是对于服务器性能提高的操作代码上使用较多
- 使用 nio可以改善服务器性能