20145215《Java程序设计》第9周学习总结

20145215《Java程序设计》第九周学习总结

教材学习内容总结

整合数据库

JDBC入门

  • JDBC是用于执行SQL的解决方案,开发人员使用JDBC的标准接口,数据库厂商则对接口进行操作,开发人员无须接触底层数据库驱动程序的差异性。

  • 数据库本身是个独立运行的应用程序,你撰写的应用程序是利用通信协议对数据库进行指令交换,以进行数据的增删查找。通常你的应用程序会利用一组专门与数据库进行通信协议的链接库,以简化与数据库沟通时的程序撰写。

  • 我们有时需要更换数据库,应用程序跨平台也是经常的需求,JDBC基本上就是用来解决这些问题的。JDBC是Java联机数据库的标准规范。具体而言,它定义了一组标准类与接口,应用程序需要联机数据库时调用这组标准API,而标准API中的接口由数据库厂商操作,通常称为JDBC驱动程序。

  • JDBC标准主要分为两个部分:JDBC应用程序开发者接口以及JDBC驱动程序开发者接口。如果应用程序需要联机数据库,就是调用JDBC应用程序开发者接口,相关API主要在java.sqljavax.sql两个包中,JDBC驱动程序开发者接口是数据库厂商操作驱动程序时的规范。

  • 厂商依操作方式可将JDBC驱动程序分为四种类型:

  1. JDBC-ODBC Bridge Driver
  2. Native API Driver
  3. JDBC-Net Driver
  4. Native Protocal Driver
  • 为了要连接数据库系统,必须要有厂商操作的JDBC驱动程序,必须在CLASSPATH中设定驱动程序JAR文档,关于教材中连接数据库的操作,详情请见教材学习中的问题和解决过程。
  • 取得联机等与数据库来源相关的行为规范在java.sql.DataSource接口中,实际如何取得Connection则由操作接口的对象来负责。Connection是数据库连接的代表对象,接下来要执行SQL的话,必须取得java.sql.Statement操作对象,它是SQL描述的代表对象。
  • Statement的execute()可以用来执行SQL,并可以测试SQL是执行查询或更新,返回true表示SQL执行将返回ResultSet作为查询结果,此时可以使用getResultSet()取得ResultSet对象。视需求而定,Statement或者ResultSet在不使用时,可以使用close()将之关闭,以释放相关资源。Statement关闭时,所关联的ResultSet也会自动关闭。
  • 如果有些操作只是SQL语句当中某些参数会有所不同,其余的SQL子句皆相同,则可以使用java.sql.PreparedStatement。可以使用Connection的PreparedStatement()方法建立好预先编译的SQL语句,当中参数会变动的部分,先指定“?”这个占位字符。
  • 在JDBC里要表示日期,是使用java.sql.Date,其日期格式是“年、月、日”,要表示时间的话则是使用java.sql.Time,其时间格式为“时、分、秒”,如果要表示“时、分、秒、微秒”的格式,你可以使用java.sql.Timestamp

JDBC进阶

  • SimpleConnectionPoolDataSource操作了DataSource接口,其中使用List实例维护可重用的Connection,联机相关信息可以使用.properties设定。
  • 在ResultSet时,默认可以使用next()移动数据光标至下一笔数据,而后使用getXXX()方法来取得数据。结果集类型可以指定3种设定:ResultSet.TYPEFORWARDONLY(默认)、ResultSet.TYPESCROLLINSENSITIVE、ResultSet.TYPESCROLLSENSITIVE。更新设定可以有两种指定:ResultSet.CONCURREADONLY(默认)、ResultSet.CONCUR_UPDATABLE。
  • 每一次执行executeUpdate(),其实都会向数据库发送一次SQL,如果大量更新的SQL有一万笔,就等于通过网络进行了一万次的信息传送,网络传送信息实际上必须打开I/O、进行路由等动作。所以最好就是所有收集的SQL,最后会串为一句SQL,然后传送给数据库,既然是批次更新,顾名思义,就是仅用在更新上,所以批次更新的限制是,SQL不能是SELECT,否则会抛出异常。
  • 如果要将文档写入数据库,可以在数据库表格字段上使用BLOB或CLOB数据类型,BLOB用于存储大量二进制数据,像是图档、影音档等,CLOB用于存储大量的文字数据。
  • 交易的四个基本要求是原子性、一致性、隔离行为与持续性。当多个交易并行时,可能引发的数据不一致问题:
  1. 更新遗失:基本上就是指某个交易对字段进行更新的信息,因另一个交易的介入而遗失更新效力。
  2. 脏读:两个交易同时进行时,其中一个交易更新数据但未确认,另一个交易就读取数据,就有可能发生脏读问题。
  3. 无法重复的读取:某个交易两次读取同一字段的数据并不一致。
  4. 幻读:同一交易期间,读取到的数据笔数不一致。
  • JDBC定义了java.sql.RowSet接口,用以代表数据的列集合,这里的数据并不一定是数据库中的数据,可以是电子表格数据、XML数据或任何具有列集合概念的数据源。RowSet定义了列集合基本行为,其下有JdbcRowSet、CachedRowSet、FilteredRowSet、JoinRowSet、WebRowSet五个标准列集合子接口,定义在javax.sql.rowset包中。

反射与类加载器

运用反射

  • Java真正需要某个类时才会载入对应的.class文档,java.lang.Class的实例代表Java应用程序运行时载入的.class文档,Class类没有公开(public)构造函数,实例是由JVM自动产生,可以通过Object的getClass()方法,或者是透过.class常量取得每个对象对应的Class对象。
  • 可以使用Class.forName()方法实现动态加载类,Class.forName()方法在找不到指定类时会抛出ClassNotFoundException异常。
  • Class对象加载的.class文档,取得Class对象后,就可以取得.class文档中记载的信息,每个类型都会有对应的类型,如果事先不知道类名称,可以利用Class.forName()动态加载.class文档,取得Class对象之后,利用其newInstance()方法建立类实例。

了解类加载器

  • 类加载指的是将类的class文件读入JVM,并为之创建一个Class对象。
  • JVM预定义的三种类型类加载器,当一个JVM启动的时候,开始使用如下三种类型类装入器:
  1. 启动(Bootstrap)类加载器:引导类装入器是用本地代码实现的类装入器,它负责将 <Java_Runtime_Home>/lib下面的核心类库或-Xbootclasspath选项指定的jar包加载到内存中。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。
  2. 扩展(Extension)类加载器:扩展类加载器是由Sun的ExtClassLoader(sun.misc.Launcher$ExtClassLoader)实现的。它负责将< Java_Runtime_Home >/lib/ext或者由系统变量-Djava.ext.dir指定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器。
  3. 系统(System)类加载器:系统类加载器是由 Sun的 AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的。它负责将系统类路径java -classpath或-Djava.class.path变量所指的目录下的类库加载到内存中。开发者可以直接使用系统类加载器。
  • Bootstrap Loader、Extended Loader与System Loader在程序启动后,就无法再改变它们的搜索路径。如果在程序运行过程中,打算动态决定从其他路径加载类,就要产生新的类加载器,新的类加载器建立后,父加载器会设为System Loader。

自定义泛型、枚举与注释

自定义泛型

  • 泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在调用时传入具体的类型(类型实参)。
  • 泛型也可以仅定义在方法上,可在方法返回类型前使用定义泛型,之后就可以使用T来定义返回类型、参数类型,或在方法内声明变量、转换类型等,在定义泛型时,使用extends限制指定T实际类型时,必须是某类的子类。
  • 如果B是A的子类,而Node(B)可视为一种Node(A),则称Node具有逆变性。Java泛型并不支持逆变性,可以使用类型通配字符?与super来声明,以达到类似逆变性的效果。

自定义枚举

  • 创建枚举类型要使用 enum 关键字,隐含了所创建的类型都是 java.lang.Enum 类的子类(java.lang.Enum 是一个抽象类)。枚举类型符合通用模式 Class Enum<E extends Enum>,而 E 表示枚举类型的名称。枚举类型的每一个值都将映射到 protected Enum(String name, int ordinal) 构造函数中,在这里,每个值的名称都被转换成一个字符串,并且序数设置表示了此设置被创建的顺序。
  • 定义enum时可以自定义构造函数,条件是不得为公开(public)构造函数,也不可以在构造函数中调用super(),定义enum时有个特定值类本体语法,可用于操作接口或重新定义父类方法。

注释

  • Java提供了一些标准注释,我们经常看到的@Override就是标准注释。举个例子来说,现在有Son和Parent两个类,且类型Son将会重写类型Parent的getName函数,但是由于我们的马虎,一不小心写成了下面的代码:
public class Parent{
  public String getName(){
     return "Parent";
  }
}

public class Son extends Parent{
   public String getNames(){
     return "Son";
   }
}

当我们用上@Override注释时,就不会再发生这样的问题,子类函数添加 @Override 后,该函数重写父类中签名相同的函数,否则将会编译失败。

  • 默认会将注释信息存储于.class文档,可被编译程序或位码分析工具读取,但执行时期无法读取注释信息,在执行时期读取注释信息,可以使用java.lang.annotation.Retention搭配java.lang.annotation.RetentionPolicy枚举指定。 RetentionPolicy为RUNTIME的时机,在于让注释在执行时期提供应用程序信息,可使用java.lang.reflect.AnnotatedElement接口操作对象取得注释信息。 JDK 8中新增了getDeclaredAnnotation()、getDeclaredAnnotationsByType()、getAnnotationsByType()三个方法。 getDeclaredAnnotation()可以让你取回指定的标注,在指定@Repeatable的标注时,会寻找收集重复标注的容器。 getDeclaredAnnotationsByType()、getAnnotationsByType()就不会处理@Repeatable的标记。

教材学习中的问题和解决过程

  1. 一开始运行代码,发现抛出异常:

  2. 这是因为没有导入MySQL的驱动包,因此我们先需要下载MySQL JDBC,这里给大家提供一个下载地址

  3. 进入下载页面之后找到JDBC Driver for MySQL,点击Download

  4. 接着选择下面那个,即下载ZIP压缩包

  5. 直接下载即可

  6. 下载完成之后解压,将mysql-connector-java-5.1.38-bin.jar放到你的JDK中lib目录下

  7. 接着,在IDEA中导入这个jar包,选中External Libraries< 1.8 >,然后右键打开Open Library Settings

  8. 点击右边的绿色"+",找到mysql-connector-java-5.1.38-bin.jar添加进来

  9. 这时,再次运行程序会发现抛出了新的异常,这是因为我们还没有安装MySQL,数据库自然也就无法联机了

  10. 先下载娄老师上传到QQ群里的XAMPP,这是一个集Apache、MySQL、PHP、PERL为一体的功能强大的建站集成软件包,下载完成之后解压,然后双击setup_xampp.bat进行配置,这样能使配置文件中的路径信息得到更新。

  11. 接着打开xampp-control.exe,点击start打开MySQL

  12. 一开始我本来想点击admin,直接创建数据库,但是点开之后发现无法访问网页

  13. 于是,只好点开Shell命令窗口,先输入指令mysql -uroot(ps:由于我的代码中没有设密码,因此,在这里输入指令时也不需要输入密码,如果有密码的话可以用指令mysql -uroot -p

  14. 为了防止出现乱码问题,我们还要设置数据库使用UTF-8进行编码,于是输入指令SET NAMES utf8;

  15. 然后输入指令CREATE DATABASE lesson,创建数据库

  16. 这时再运行程序,便能成功开启数据库联机

在此大家可以参考一下常见的MySQL数据库命令

心得体会

本周学习的重点在于MySQL的学习,刚刚接触的时候感觉有点无从下手,中间花了比较长的时间去摸索XAMPP软件,后来通过在网上搜集资料慢慢对XAMPP有所了解,并且建立起了一个简单的数据库。一开始我想不太明白Java和数据库之间到底有什么联系,但是我慢慢意识到Java应用的主流应该是在网络方向,尤其是大规模的企业级应用,这必然导致要与大批量的数据发生关系,因此用数据库来对这些数据进行管理对于一些用Java开发的大规模应用来说是非常有必要的,这也就更加说明了数据库对Java的重要性,如果我们能够学好数据库,那么对于今后一些项目的开发也会非常有帮助。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时 编写了Hello Java代码
第一周 100/100 2/2 12/12 编写了Hello Java代码
第二周 200/300 2/4 15/27 理解了printf和println的区别
第三周 450/750 1/5 22/49 对对象有了更深层次的理解
第四周 869/1619 1/6 28/77 对对象的三大特征有了更全面的认识
第五周 1123/2742 1/7 25/102 学会了异常处理
第六周 863/3605 2/9 30/132 理解了线程
第七周 505/4110 2/11 28/160 掌握了日期和时间的运用
第八周 490/4600 2/13 26/186 掌握了git托管的节奏
第九周 591/5191 2/15 30/216 初步学会使用MySQL

【附1】本周学习的代码已经成功托管,截图如下:

【附2】利用wc统计代码行数,截图如下:

参考资料

posted @ 2016-05-01 19:42  L.X.M  阅读(403)  评论(2编辑  收藏  举报