Java中的集合对象就像是一个容器,它用来存放Java类的对象。java.util包中提供了一些集合类,这些集合类又被称为容器。集合类与数组的区别是:数组的长度是固定的,集合的长度是可变的;数组用来存放基本类型,集合用来存放对象的引用。
常用的集合有List集合、Set集合和Map集合。List与Set继承了Collection接口。
List集合包括List接口以及List接口的所有实现类。List集合中的元素允许重复,各元素的顺序就是对象插入的顺序,用户可以通过使用索引(元素在集合中的位置)来访问集合中的元素。List集合是以线性方式存储对象的。List接口的常用方法有:
方法 | 返回值 | 功能描述 |
---|---|---|
add(int index,Object obj) | void | 用来向集合中的指定索引位置添加对象,集合的索引位置从0开始,其他对象的索引位置相对向后移一位。 |
allAll(int index, Collection coll) | boolean | 向集合的指定索引位置添加指定的集合对象 |
remove(int index) | Object | 用来移除集合中指定索引位置的对象 |
get(int index) | Object | 用于获取指定索引位置的对象 |
indexOf(Object obj) | int | 该方法返回列表中对象第一次出现的索引位置,如果集合中不包含该元素,则返回-1 |
lastIndexOf(Object obj) | int | 该方法返回列表中对象最后一次出现的索引位置,如果集合中国不包含该元素,则返回-1 |
subList(int formIndex, int to Index) | List | 获取从索引formIndex到toIndex之间的元素对象 |
set(int index,E element) | Object | 用指定元素替换列表中指定位置的元素,返回以前在指定位置的元素 |
listIterator() | ListIterator | 用来获得一个包含所有对象的ListIterator列表迭代器 |
要使用List集合,通常先声明为List类型,之后通过List接口的实现类来对集合进行实例化。List接口的实现类常用的有ArrayList与LinkedList。另一种遍历集合对象的方式是创建集合对象的迭代器,通过遍历迭代器获取集合中的元素。注意区分add(int index,Object obj)方法与set(int index,Object obj)方法。
ArrayList类实现了可变的数组,允许包含所有元素,包括NULL。使用它可以根据索引位置对集合进行快速的随机访问,缺点是向指定的索引位置插入对象或删除对象的速度较慢。
Set集合中的对象不按特定的方式排序,只是简单地将对象加入集合中,但set集合中不能包含重复对象。Set集合由Set接口和Set接口的实现类组成。Set接口继承了Collection接口。Set接口的常用方法有:
方法 | 返回值 | 功能描述 |
---|---|---|
add(Object obj) | boolean | 如果此Set集合中尚未存在指定的元素,则添加此元素 |
addAll(Collection coll) | boolean | 将参数集合中的所有元素添加到此Set集合的尾部 |
remove(Object obj) | boolean | 将指定的参数对象移除 |
retainAll(Collection c) | boolean | 只保存Set集合中的包含在指定Collection集合中的内容 |
removeAll(Collection c) | boolean | 在Set集合中移除包含在指定Collection中的元素 |
clear() | void | 移除此Set中所有元素 |
iterator() | Iterator | 返回此Set中的元素上进行迭代的迭代器 |
size() | int | 返回此Set集合中的所有元素数 |
isEmpty() | boolean | 如果Set不包含元素,则返回true |
要使用Set集合,先声明为Set类型,然后通过Set接口的实现类来实例化。Set接口的实现类常用的有HashSet和TreeSet类。要获得Set集合对象,可以通过iterator()对象,获取Iterator实例,通过遍历迭代器来获取集合中的对象。由于Set集合中不允许存在重复值,因此可以使用Set集合中的addAll()方法,将Collection集合添加到Set集合中,以除掉重复值。
HashSet类实现了Set接口,由哈希表(实际上是一个HashMap实例)支持。它不保证Set的迭代顺序,特别是它不保证该顺序恒久不变。此类允许使用null元素。添加到由HashSet类实现的Set集合中的对象,需要重新实现equals()方法。从而保证插入集合中对象的标识的唯一性。由于Set集合中的对象是无序的,遍历Set集合的结果与插入Set集合的顺序并不相同。
Map没有继承Collection接口,其提供的是key到value的映射。Map中不能包含相同的key值,每个key只能映射一个value。key还决定了存储对象在映射中的存储位置,但不是key对象本身决定的,而是通过散列技术进行处理,可产生一个散列码的整数值,散列码通常用作一个偏移量,该偏移量对应分配给映射的内存区域的起始位置,从而确定存储对象在映射中的存储位置。Map集合包括Map接口以及Map接口的所有实现类。Map接口提供了将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。Map接口中同样提供了集合的常用方法,如clear()、isEmpty()、size()等,除此之外还有:
方法 | 返回值 | 功能描述 |
---|---|---|
put(key k,value v) | Object | 向集合中添加指定的key与value的映射关系 |
containskey(Object key) | boolean | 如果此映射包含指定键的映射关系,则返回true |
containsValue(Object value) | boolean | 如果此映射将一个或多个键映射到指定值,则返回true |
get(Object key) | Object | 如果存在指定的键对象,则返回该对象对应的值,否则返回null |
keySet() | Set | 返回该集合中的所有键对象组成的Set集合 |
values() | Collection | 返回该集合中所有值对象形成的Collection集合 |
要使用Map集合,先声明为Map类型,然后通过Map接口的实现类来进行实例化。Map接口的实现类常用的有HashMap和TreeMap类。由于Map集合中的元素是通过key、value进行存储的,要获取集合中指定的key值或value值,需要先通过相应的方法获取key集合或value集合,在遍历key集合或value集合获取指定值。
HashMap是基于哈希表的Map接口实现的。HashMap通过哈希码对其内部的映射关系进行快速查找,此实现提供了所有可选的映射操作,并允许使用null值和null键,但必须保证键的唯一性。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
TreeMap中的映射关系存在一定的顺序。如果希望Map集合中的对象存在一定的顺序,应该使用TreeMap类实现Map集合。否则建议使用HashMap实现类实现Map集合,因为由HashMap类实现的Map集合对于添加和删除映射关系效率更高。TreeMap类不仅实现了Map接口,还实现了java.util.SortedMap接口,因此集合中的映射关系具有一定的顺序。但是在添加、删除和定位映射关系上,TreeMap类比HashMap类的性能差一些。由于TreeMap类实现的Map集合中的映射关系是根据键对象按照一定的顺序排列的,因此不允许键对象是null。
数据库具有以下主要特点:实现数据共享、减少数据的冗余度、数据的独立性(包括数据库的逻辑结构和应用程序相互独立,也包括数据物理结构的变化不影响数据的逻辑结构)、数据实现集中控制、数据一致性和可维护性(安全性控制、完整性控制、并发控制、故障的发现和恢复)。数据库系统基板基于某种数据模型分为层次性(类似于树结构,是一组通过链接而相互联系在一起的记录)、网状型(使用网络结构表示实体类型、实体间联系的数据模型)、面向对象型和关系型。
JDBC-ODBC技术介绍:JDBC是一种用于执行SQL语句的JavaAPI,是连接数据库和Java应用程序的一个纽带。JDBC-ODBC桥是一个JDBC驱动程序,它完成了从JDBC操作到ODBC操作之间的转换工作,java利用JDBC-ODBC桥几乎可访问所有的数据库。JDBC-ODBC桥连接数据库的方法,步骤如下:
(1)首先加载JDBC-ODBC桥的驱动程序:Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Class类是java.lang包的一个类,通过该类的静态方法forName()可加载sun.jdbc.odbc包中的JdbcOdbcDriver类来建立JDBC-ODBC桥连接器。
(2)使用java.sql包中的Connection接口,并通过DriverManager类的静态方法getConnection()创建连接对象:
Connection conn = DriverManager.getConnection("jdbc:odbc:数据源名字","user name","password");
数据源名称必须配置成功,否则不会连接成功。数据源必须给出一个简短的描述名。
(3)向数据库发送SQL语句。使用Statement接口声明一个SQL语句对象,并通过刚才创建的连接数据库对象conn的createStatement()方法创建这个SQL对象:Statement sql = conn.createStatement();
JDBC并不能直接访问数据库,需要借助于数据库厂商提供的JDBC驱动程序。
JDBC技术中常用的类和接口,都位于java.sql包中。
DriverManager类用来管理数据库中的所有驱动程序,是JDBC的管理层,作用与用户和驱动程序之间,跟踪可用的驱动程序,并在数据库的驱动程序之间建立连接。此外,DriverManager类也处理诸如驱动程序登录时间限制及登录和跟踪信息的显示灯事务。DriverManager类中的方法都是静态方法,所以在程序中无须对它进行实例化,直接通过类名就可以调用。
方法 | 功能描述 |
---|---|
getConection(String url,String user,String password) | 指定3个入口参数,依次是连接数据库的URL、用户名、密码,以获取与数据库的连接 |
setLoginTimeout() | 获取驱动程序试图登录到某一数据库时可以等待的最长时间,以秒为单位 |
println(String message) | 将一条消息打印到当前JDBC日志流中 |
Connection接口代表与特定的数据库的连接。要对数据表中的数据进行操作,首先要获取数据库连接。Connection实例就像在应用程序与数据库之间开通了一条渠道。通过DriverManager类中的getConnection()方法可获取Connection实例。Connection接口的常用方法有:
方法 | 功能描述 |
---|---|
createStatement() | 创建Statement对象 |
createStatement(int resultSetType,int result SetConcurrency) | 创建一个Statement对象,该对象将生成具有给定类型、并发性和可保存性的ResultSet对象 |
prepareStatement() | 创建预处理对象PreparedStatement |
isReadOnly() | 查看当前Connection对象的读取模式是否是只读形式 |
setReadOnly() | 设置当前Connection对象的读写模式,默认为非只读模式 |
commit() | 使所有上一次提交、回滚后进行的更改成为持久更改,并释放此Connection对象当前持有的所有数据库锁 |
roolback() | 取消在当前事务中进行的所有更改,并释放此Connection对象当前持有的所有数据库锁 |
close() | 立即释放此Connection对象的数据库和JDBC资源,而不是等待他们被自动释放 |
Statement实例用于在已经建立连接的基础上向数据库发送SQL语句。该接口用来执行静态的SQL语句,例如执行INSERT、UPDATE、DELETE语句可以调用该接口的executeUpdate()方法,执行SELECT语句可调用该接口的executeQueue()方法。Statement实例可以通过Connection实例的createStatement()方法获取。Statement接口的常用方法有:
方法 | 功能描述 |
---|---|
execute(String sql) | 执行静态的SELECT语句,该语句可能返回多个结果集 |
executeQuery(String sql) | 执行给定的SQL语句,该的语句返回单个ResultSet对象 |
clearBatch() | 清空此Statement对象的当前SQL命令列表 |
executeBatch() | 将一批命令提交给数据库执行,如果全部命令执行成功,则返回更新计数组成的数组。数组元素的排序与SQL语句的添加顺序对应 |
executeUpdate() | 执行给定的SQL语句,该语句可以为INSERT、UPDATE或DELETE语句 |
addBatch(String sql) | 将给定的SQL命令添加到此Statement对象的当前命令列表中。如果驱动程序不支持批量处理将抛出异常 |
close() | 释放Statement实例占用的数据库和JDBC资源 |
PreparedStatement接口继承Statement,用于执行动态的SQL语句,通过PreparedStatement实例执行SQL语句,将被预编译保存到PreparedStatement实例中,从而可以反复地执行该SQL语句。可以通过Connection类的preparedStatement()方法获取PreparedStatement对象。PreparedStatement接口的常用方法有:
方法 | 功能说明 |
---|---|
execute() | 在此PreparedStatement对象中执行SQL语句,该语句可以是任何类型的SQL语句 |
executeQuery() | 在此PreparedStatement对象中执行SQL查询语句,返回结果为查询结果集ReaultSet对象 |
executeUpdate() | 在此PreparedStatement对象中执行SQL语句,该语句必须是一个INSERT、UPDATE、DELETE语句,或者是没有返回值的DDL语句 |
setByte(int pIndex,byte bt) | 将参数pIndex位置上设置为给定的byte型参数bt |
setDouble(int pIndex,double dou) | 将参数pIndex位置上设置为给定的double型参数dou |
setInt(int pIndex,int x) | 将参数pIndex位置上设置为给定的int型参数x |
setObject(int pIndex,Object o) | 将参数pIndex位置上设置为给定的Object型参数值 |
setString(int pIndex,String str) | 将参数pIndex位置上设置为给定的String型参数值 |
ResultSet接口类似于一张数据表,用来暂时存放数据库查询操作所获得的结果集。ResultSet实例具有指向当前数据行的指针,指针开始的位置在查询结果第一条记录的前面。在获取查询结果集时,可通过next()方法将指针向下移。如果存在下一行该方法会返回true,否则返回false。
ResultSet接口提供了从当前行检索不同类型列值的getXXX()方法,通过该方法的不同重载形式,可实现分别通过列的索引编号和列的名称检索列值。此外,该接口提供了一组更新方法updateXXX(),可通过列的索引号和列的名称更新当前行的指定列。但是该方法并未将操作同步到数据库中,需要执行updateRow()或insertRow()方法完成同步操作。该接口的常用方法有:
方法 | 功能描述 |
---|---|
getInt() | 以int形式获取此ResultSet对象的当前行中的指定列值。如果列值为NULL,则返回值是0 |
getFloat() | 以float形式获取此ResultSet对象的当前行中的指定列值。如果列值为NULL,则返回值是0 |
getDate() | 以Data形式获取此ResultSet对象的当前行中的指定列值。如果列值为NULL,则返回值是null |
getBoolean() | 以boolean形式获取此ResultSet对象的当前行中的指定列值。如果列值为NULL,则返回值是null |
getString() | 以String形式获取此ResultSet对象的当前行中的指定列值。如果列值为NULL,则返回值是null |
getObject() | 以Object形式获取此ResultSet对象的当前行中的指定列值。如果列值为NULL,则返回值是null |
first() | 将指针移到当前记录的第一行 |
last() | 将指针移到当前记录的最后一行 |
next() | 将指针向下移一行 |
beforeFirst() | 将指针移到集合的开头(第一行位置) |
afterLast() | 将指针移到集合的尾部(最后一行位置) |
absolute(int index) | 将指针移到ResultSet指定编号的行 |
isFirst() | 判断指针是否位于当前ResultSet集合的第一行。如果是则返回true,否则返回false |
isLast() | 判断指针是否位于当前ResultSet集合的最后一行。如果是则返回true,否则返回false |
updateInt() | 用int值更新指定列 |
updateFloat() | 用float值更新指定列 |
updateLong() | 用指定的long值更新指定列 |
updateString() | 用指定的String值更新指定列 |
updateObject() | 用Object值更新指定列 |
updateNull() | 将指定的列值修改为NULL |
updateDate() | 将指定的Date值更新指定列 |
updateDouble() |
如果要访问数据库,首先要加载数据库驱动,数据库驱动只需在第一次访问数据库时加载一次。然后在每次访问数据库时创建一个Connection实例,获取数据库连接,这样就可以执行操作数据库的SQL语句。最后在完成数据库操作时,释放与数据库的连接。
Java程序与SQL Server2000数据库建立连接,需要在程序中加载驱动包msbase.jar、mssqlserver.jar、msutil,jar或jtds.jar,连接SQL Server 2005数据库应用的驱动程序为sqljdbc.jar,与MySQL数据库建立连接需要在程序中加载驱动包mysql-connectot-java.jar等。
将下载的数据库驱动文件添加到项目后,首先需要加载数据库驱动程序,才能进行数据库操作。Java加载数据库驱动的方法是调用Class类的静态方法forName()。在进行数据库操作时,只需要在第一次访问数据库时加载数据库驱动,以后每次访问数据时,创建一个Connection对象后即可执行操作数据库的SQL语句。通过DriverManager类的getConnection()方法可创建Connection实例。
数据库 | 驱动 | URL |
---|---|---|
SQL Server 2000 | com.microsoft.jdbc.sqlserver.SQLServerDriver | jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=数据库名称 |
SQL Server 2005 | com.microsoft.jdbc.sqlserver.SQLServerDriver | jdbc:sqlserver://localhost:1433;DatabaseName=数据库名称 |
建立数据库连接的目的是与数据库进行通信,实现方式为执行SQL语句,但Connection实例并不能执行SQL语句。此时需要通过Connection接口的createStatement()方法获取Statement对象。
Statement接口的executeUpdate()方法或executeQuery()方法可以执行SQL语句。executeUpdate()方法用于执行数据的插入、修改或删除操作,返回影响数据库记录的条数;executeQuery()方法用于执行SELECT查询语句,将返回一个ResultSet型的结果集。通过遍历查询结果集的内容,可以获取SQL语句执行的查询结果。ResultSet对象的getXXX()方法可获取查询结果集中的数据,由于在ResultSet中以表的形式保存数据,因此可通过使用getXXX()方法指定列的序号与列的名称来获取数据。在进行数据库访问时,Connection、Statement、ResultSet实例都会占用一定的系统资源,因此在每次访问数据库后,及时地释放这些对象占用的资源。Connection、Statement、ResultSet实例都提供了close()方法用于释放对象占用的数据库和JDBC资源。
如果通过DriverManager类的getConnection()方法获取Connection实例,那么通过关闭Connection实例,就可同时关闭Statement实例和ResultSet实例。当采用数据库连接池时,close()方法并没有释放Connection实例,而是将其放入连接池中,又可被其他连接调用。此时,如果没有调用Statement与ResultSet实例的close()方法。它们在Connection中会越来越多,虽然JVM(Java虚拟机)会定时清理缓存,但当数据库连接达到一定数量时,清理不够及时,就会严重影响数据库和计算机的运行速度。
执行静态SQL语句需要Statement接口,该接口的execute()方法与executeUpdate()方法都可执行INSERT语句,实现添加数据操作。execute()方法执行INSERT语句,结果返回false,如果想获取影响数据表中数据的行数,需要调用Statement接口的getUpdateTime()方法。Statement接口的executeUpdate()方法可执行INSERT语句,并返回受影响数据的行数。该方法执行CREATE TABLE、ALTER TABLE等DDL语句,此时返回值为0。在程序中删除数据表的数据,也可通过Statement接口的execute()方法与executeUpdate()方法实现,在删除数据操作时,如果DELETE语法没有WHERE子句指定删除数据的条件,会将数据表中的全部数据删除。DELETE语句删除表中的数据后会保留表,而DROP TABLE命令则会将整张表删除。要获取SELECT语句返回的查询结果,必须通过遍历查询结果集(ResultSet对象)。
向数据库发送一个SQL语句,数据库中SQL解释器负责把SQL语句生成底层的内部命令,然后执行该命令完成相关的数据操作。如果不断地向数据库提交SQL语句肯定会增加数据库的SQL解释器的负担,从而影响执行的速度。
对于JDBC,可以通过Connection对象的prepareStatement(String sql)方法对SQL语句进行编译预处理,生成数据库底层的内部命令,并将该命令封装在PreparedStatement对象中。通过调用该对象的相应方法执行底层数据库命令,这样应用程序能针对连接的数据库将SQL语句解释为数据库底层的内部命令,然后让数据库执行这个命令,这样可以减轻数据库的负担,从而提高访问数据库的速度。
对SQL进行预处理时可以通过使用通配符“?”来代替任何的字段值。在执行预处理语句前,必须通过相应方法来设置通配符所表示的值。为预编译语句赋值可以使用PreparedStatement的setXXX()方法。使用预处理语句可以使应用程序更容易动态地改变SQL语句中关于字段值条件的设定。通过setXXX()方法为SQL语句中的参数赋值时,建议使用与参数匹配的方法,也可以使用setObject方法为各种类型的参数赋值。使用预编译语句,传入的任何内容都不会和原来的SQL语句发生匹配关系,这样就大大地增强了程序的安全性。进行模糊查询需要使用关键字“LIKE”。在使用“LIKE”关键字进行模糊查询时,可以使用通配符“%”来代表0个或多个字符,也可使用下换线“_”代替一个字符。