posts - 78, comments - 34, trackbacks - 0, articles - 1
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

2009年12月1日

好快,已经是12月份了,11月5日开的班。就快学习一个月了,总学习时间是四个月。过年休息9天,这样到明年3月14日课程就结束了。好好学习,回去找个好工作!

今日是JDBC的第一天,JDBC的基础应用。以后在WEB开发中的使用方式。课程中,方老师上午在讲解JDBC基础的同时做了一个JDBC练习程序,对JDBC的基础应用。下午,方老师做了一个使用数据库的WEB应用,用户注册、登录、用户信息修改。

先让我们来了解一下JDBC(Java Data Base Connectivity)基础吧!

我们都知道数据库都提供一些接口,用户使用这些接口操作数据库。这就是数据库驱动!常见的数据库有MySQL、Oracle、SQLServer、DB2等,这些数据库提供的接口都不一样,难道开发人员使用不同的数据库就要学习不同的驱动接口吗?JDBC正是为统一数据库访问接口而实现的,SUN公司提出了这一接口。数据库公司都去实现这一接口。大大方便了,编程人员对数据库的操作:

clip_image002

在工程中使用JDBC,必须导入相应的JAR包。比如使用MySQL数据库,必须导入MySQL实现的JDBC jar包。可以到http://dev.mysql.com/downloads/下载。

使用JDCB进行数据访问的基本流程,见代码:

隐藏行号 复制代码 这是一段程序代码。
  1. import java.sql.Connection;
        
  2. import java.sql.DriverManager;
        
  3. import java.sql.ResultSet;
        
  4. import java.sql.SQLException;
        
  5. import java.sql.Statement;
        
  6. 
        
  7. public class JDBCTemp {
        
  8. 
        
  9.     public static void main(String[] main) throws Exception {
        
  10.         // 1.装
        
  11.         DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        
  12.         /*
        
  13.          * 因om.mysql.jdbc.Driver在
        
  14.          * 上om.mysql.jdbc.Driver,
        
  15.          * 所
        
  16.          */
        
  17.         Class.forName("com.mysql.jdbc.Driver");
        
  18.         // 2.连
        
  19.         Connection conn = DriverManager.getConnection(
        
  20.                 "jdbc:mysql://localhost:3306/databasename", "username",
        
  21.                 "password");
        
  22.         // 3.创QL语tatement对
        
  23.         Statement sta = conn.createStatement();
        
  24.         // 4.执QL语
        
  25.         boolean ok = sta.execute("select * from user;");
        
  26.     
  27.         // 5.遍
        
  28.         ResultSet rs = null;
        
  29.         if(ok){
        
  30.             rs = sta.getResultSet();
        
  31.             while(rs.next()){
        
  32.                 rs.getInt(1);
        
  33.                 //...
        
  34.             }
        
  35.         }
        
  36.     
  37.         // 6.释esultSet、tatement、onnection这
        
  38.         // 必
        
  39.         // 下
        
  40.         if(rs != null){
        
  41.             try {
        
  42.                 rs.close();
        
  43.             } catch (SQLException e) {
        
  44.                 e.printStackTrace();
        
  45.             }
        
  46.             rs = null;
        
  47.         }
        
  48.     
  49.         if(sta != null){
        
  50.             try {
        
  51.                 sta.close();
        
  52.             } catch (SQLException e) {
        
  53.                 e.printStackTrace();
        
  54.             }
        
  55.             sta = null;
        
  56.         }
        
  57.     
  58.         if(conn != null){
        
  59.             try {
        
  60.                 conn.close();
        
  61.             } catch (SQLException e) {
        
  62.                 e.printStackTrace();
        
  63.             }
        
  64.             conn = null;
        
  65.         }
        
  66.     }
        
  67. }
        
  68. 
        

 

上面的代码只为演示,继续向下学习就会发现其中的一些问题。

其中

DriverManager.getConnection("jdbc:mysql://localhost:3306/databasename", "username","password");

GetConnection的第一个参数“jdbc:mysql://localhost:3306/databasename

”,它的各段含义如下:

Jdbc:协议

Mysql:子协议

localhost:主机

3306:端口

databasename:数据库名

常见的URL如下:

Oracle :jdbc:oracle:thin:@localhost:1521:sid

SQLServer:jdbc:microsoft:sqlserver//localhost:1433; DatabaseName=sid

MYSQL:jdbc:mysql://localhost:3306/sid

如果把上面的代码用于用户登录或查询数据时,会造成一个严重的安全漏洞——SQL注入!

例,根据提交的用户名查找用户:

"select id,name,password from user where name='"+name+"'";

如果用户提交的用户名是:“’ or 1=1 or 1=‘”,会发生什么问题?因为在where过滤时使用了or逻辑,其有的1=1返回真,结果可以正常通过验证。这是一个十分严重的安全漏洞!

为此Java为我们提供了PreparedStatement接口,表示预编译的 SQL 语句的对象。SQL 语句被预编译并存储在 PreparedStatement 对象中,然后可以使用此对象多次高效地执行该语句。PreparedStatement的使用:

PreparedStatement ps = conn.prepareStatement("select id,name,password form user where name=? and passowrd=?");

ps.setString(1, name);

ps.setString(2, password);

这样就可以解决SQL注入的漏洞,同时也可以高效的执行SQL语句。上面的使用方法一眼就看出来了,一个“?”对应下边的ps.setXXX方法,按照“?”先后,对应ps.setXXX第一个参数的索引!

我们使用Statement. execute执行了查询语句,Statement还有其他以execute开头的方法,具体针对查询和增加、删除、修改的方法,在此就不一一说明了。JDK手册里边有详细说明。

查询成功后,在Statement对象中,可以获得记录集对象ResultSet,查询的结果全都保存在ResultSet中吗?仔细想想,好像是。如果有1亿条记录符合查询条件,同时有1000个用户调用同一查询,那服务器不烧了吗!所以查询的结果并未保存在ResultSet中,而是保存在数据库中,ResultSet指向数据库的引用。这样很方便也很快捷!那数据库会不会被充爆了?当然不会,数据本身就保存在数据库中,数据库的查询结果顶多就保存的指向数据的“指针”。

ResultSet对象内部有一个游标,游标初始位置是第一条记录前。必须调用它的next()方法,才会到第一条记录,依次向下。如果不存在记录,或者已经到记录尾,则返回false。存在记录返回true。然后我们可以通过调用它的getObject、getInt、getString…方法调用相应的值,如果只使用getObject获取记录值,必须使用强转将它转换为我们需要的类型。

下面是常用数据类型转换表(老方整理的,嘿嘿):

SQL类型

Jdbc对应方法

返回类型

BIT

getBoolean()

Boolean

TINYINT

getByte()

Byte

SMALLINT

getShort()

Short

int

getInt()

Int

BIGINT

getLong()

Long

CHAR,VARCHAR,LONGVARCHAR

getString()

String

Text Blob

getColb() getBlob()

Clob blob

DATE

getDate()

Java.sql.Date

TIME

getTime()

Java.sql.Time

TIMESTAMP

getTimestamp()

Java.sql.Timestamp

关于使用JDBC进行CURD的操作比较简单,因为昨天已经学习了在控制台有使用这些操作,在此就不多进行复习了。但一定要记住每次使用完数据库连接时,一定要释放。一是因为数据库有同时连接数量限制,二是因为数据连接会占用服务器资源。安全释放这些连接,参看上边的释放代码。常规的项目开发中,会将对数据库的操作封装到一个类中,这样方便使用。

在常规项目开发中,我们需要编写操作数据的DAO类。因为对数据库的一些操作需要处理异常,为了查错直观一些。我们在环绕这些异常时,将它们包装一下再抛出。如何包装异常?JAVA的包装类很多,我们的包装也是通过这个方法实现的。编写一个继承处Exception类的子类,然后将接收的异常存到父亲类中,我们也可以在自定义类中添加些自己的提示信息。这样当程序运行时抛出的异常,可以直观的定位到错误类。这是一个十分好的方法,用在其他地方。也有相当的功效!

最后一个问题,数据库中的中文乱码问题。其实并不是数据库的原因 ,因为我们在创建数据库时可以指定它的编码为utf8、gb2312或gbk等支持中文的编码。WEB应用读写数据库时造成的乱码,主要是由于WEB应用使用的编码与数据库使用的编码不统一。统一一下,就可以解决了!

老方有给大家留作业,今天的作业内容较多。主要是为了练习数据库的操作和数据库与WEB的组合应用。之前都是使用XML或配置文件做为伪数据库与WEB组合练习的,从今天起用上数据库了。虽然并不是十分兴奋,但离框架和项目练习越来越近了,这让我感觉很好!

以前并未使用JAVA开发过项目,虽然学习JAVA对我已经没什么难度。但上课这些天来,有时用到IO和集合,还是让我卡了一下。因为我并未系统的学习过它们,我应该系统的学习一下它们了。越是学习应该越是快乐,越学习应该越是简单。没有学习基础那么枯燥,就围绕那基础搞来搞去,用起来了才舒服。因为基础学习好了,所以感觉应用就简单的。其实应用并不简单,即使不说基础,应用中的模式与框架是相当重要的,有使用过程语言开发的同志,我想对此有很大的感想!

我要学好项目的架构,文档的编写与项目管理,这在以后工作中是相当重要的。

posted @ 2009-12-01 22:26 長城 阅读(231) | 评论 (0)编辑 收藏

2009年11月30日

方老师今日讲解数据库入门,主要内容是对数据库操作的SQL语句,仅涉及单表操作。内容虽然枯燥,但也学习了很多知识。

什么是SQL?structred query language(结构化查询语言),在数据库中它是通用的。我之前并未深入使用数据库。对此还有些模糊,但今日的学习让我有了深入了解。其实我也应该早就想到,对数据的一些操作通过SQL语句就可以完成,程序直接拿结果就可以了。

方老师以MySQL5.0数据库,给我们做了讲解。是为了下一课学习JDBC做准备。前面的对数据库的简介和MySQL5.0的安装及配置,我就不写出来了。下面是用户、服务器、数据库和表的关系图:

clip_image001

在配置数据库时选中:clip_image002,或手动将MySQL安装目录添加到Windows环境变量Path中。使用控制台连接MySQL数据库:mysql –u 用户名 –p 密码。

下面是常用的SQL语句,只针对单表使用,有关语句的具体信息请查询MySQL的手册:

一、数据库相关SQL语句:

1. 创建数据库:
CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name [create_specification [, create_specification] ...]

其中create_specification是:

[DEFAULT] CHARACTER SET charset_name | [DEFAULT] COLLATE collation_name
例,创建一个名为“ccdb”,字符集为UTF-8的数据库:
create database ccdb character set utf8;
clip_image003

2. 查看、删除数据库:
显示数据库:
SHOW CREATE {DATABASE | SCHEMA} db_name
例,查看服务器中所有的数据库:
 clip_image004
显示数据库创建语句:
SHOW {DATABASES | SCHEMAS} [LIKE 'pattern']
例,查看创建的“ccdb”数据库的创建语句:
clip_image005
删除数据库:
DROP {DATABASE | SCHEMA} [IF EXISTS] db_name
例,删除创建的数据库“ccdb”:
clip_image006

3. 修改数据库:
ALTER {DATABASE | SCHEMA} [db_name] alter_specification [, alter_specification] ...
其中alter_specification是:
[DEFAULT] CHARACTER SET charset_name | [DEFAULT] COLLATE collation_name

例,更改数据库“ccdb”的字符编码为“gbk”:

clip_image008

二、数据表相关SQL语句:

1. 创建表:
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)] [table_options] [select_statement]
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(] LIKE old_tbl_name [)];
其中create_definition、table_options等,请查看手册。
例,在数据库“ccdb”中创建一个“user”表:
在创建表之前,必须选择当前库。否则服务器不知道在哪个数据库中创建表,或者当前已经有被选择的其他数据库,就会创建到别的库。

clip_image009

clip_image010

 
MySQL常用数据类型(拿方老师的,嘿嘿):
分类
数据类型
说明
 
 
 
 
数值类型
BIT
TINYINT [UNSIGNED] [ZEROFILL] 
BOOL,BOOLEAN 
SMALLINT [UNSIGNED] [ZEROFILL] 
INT [UNSIGNED] [ZEROFILL] 
BIGINT [UNSIGNED] [ZEROFILL] 
FLOAT[(M,D)][UNSIGNED] [ZEROFILL] 
DOUBLE[(M,D)][UNSIGNED] [ZEROFILL] 
范围为从1到64。
带符号的范围是-128到127。无符号0到255。
使用0或1表示真或假
2的16次方
2的32次方
2的64次方
M指定长度,d指定小数位数
表示比float精度更大的小数
 
 
文本类型
CHAR(size)
VARCHAR(size)
BLOB   LONGBLOB
TEXT   LONGTEXT
固定长度字符串
可变长度字符串
二进制数据
大文本
时间日期
DATE/DATETIME/TimeStamp
日期类型(YYYY-MM-DD)  (YYYY-MM-DD HH:MM:SS),TimeStamp表示时间戳,它可用于自动记录insert、update操作的时间
 

2. 修改表:
ALTER [IGNORE] TABLE tbl_name alter_specification [, alter_specification] ...

其中alter_specification,请查看手册。

修改表“user”名为“userinfo”:
clip_image011
修改表“userinfo”的字符集为“gb2313”,并将字符集校对设置为与“gb2313”相应的校对:
clip_image013
可以在控制台输入:SHOW CHARACTER SET;,列出可用的字符集。也可以在手册中查找“Character sets”,查找手册中的字符集列表。
可以在控制台输入:SHOW COLLATION LIKE 'gb%';,查看以gb开头的所有字符集。
先将表“userinfo”恢复名称为“user”,查看表“user”:
clip_image014
查看表“user”的结构:
clip_image015
添加列“photo”:

clip_image016

修改列“sex”属性-类型为“bit”:

clip_image017

修改列“email”名称为“address”:

clip_image018

删除列“address”:

clip_image019

3. 数据库CURD语句:

Insert语句:

INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);

例,向“user”表中插入一条新数据:

clip_image021

Update语句:

UPDATE tbl_name  SET col_name1=expr1 [, col_name2=expr2 ...] [WHERE where_definition]

例,将“sex”为1的人的“name”修改为“changcheng”:

clip_image022

clip_image023

Delete语句:

delete from tbl_name [WHERE where_definition]

例,删除刚才添加的新记录:

clip_image024

如果没有后边的where条件,则删除表中所有的数据。

truncate table tbl_name;是删除表,然后立即创建一个新表。

clip_image025

4. Select查询语句(因为它是重点,所以单独拿出来):

1. 基本select语句:

SELECT [DISTINCT] *|{column1, column2. column3..} FROM table;

例,我们新创建了一个sutdent表,查看表中的所有记录:

clip_image026

例,查询表中所有学生姓名和他的数学成绩:

clip_image027

例,过滤表中的重复数据(distinct):

clip_image028

2. 在select语句中可使用表达式对查询的列进行运算:

SELECT *|{column1|expression, column2|expression,..} FROM table;

例,将所有学习的数学加上10分:

clip_image029

例,统计学生的总分:

clip_image030

3. 在select语句中可使用as语句:

SELECT column as 别名 from 表名;

例,修改统计学生总分的列名:

clip_image031

4. 在select语句中加上where条件,进行过滤查询:

例,查询总分大于260分的学生:

clip_image033

5. where经常使用的运算符:

比较运算符

> < <= >= = <>

大于、小于、大于(小于)等于、不等于

BETWEEN ...AND...

显示在某一区间的值

IN(set)

显示在in列表中的值,例:in(100,200)

LIKE ‘pattern’

模糊查询,Like语句中,% 代表零个或多个字符,_ 代表一个字符,例first_name like ‘_a%’;

IS NULL

判断是否为空

逻辑运算符

and

多个条件同时成立

or

多个条件任一成立

not

不成立,例:where not(salary>100);

例,查询数学成绩在80-90之间的学生:

clip_image034

例,查询数据成绩为90、80、78的学生:

clip_image036

例,查询所有名字以“a”开头的学生的数学成绩:

clip_image037

6. 使用order by 子句排序查询结果:

SELECT column1, column2. column3.. FROM table order by column asc|desc

clip_image039

5. 合计函数:

1. Count返回满足where子句条件的行的总数:

Select count(*)|count(列名) from tablename [WHERE where_definition]

例,查询共有多少学生:

clip_image040

例,查询总分大于250分的人数:

clip_image041

2. Sum函数返回满足where条件的行的和:

Select sum(列名){,sum(列名)…} from tablename [WHERE where_definition] 

注意:sum仅对数值起作用,否则会报错。

例,统计本班数学成绩的平均分:

clip_image042

例,统计各科总成绩:

clip_image043

3. AVG函数返回满足where条件的一列的平均值:

Select avg(列名){,avg(列名)…} from tablename [WHERE where_definition] 

例,求数学的平均分:

clip_image044

例,求总平均分:

clip_image045

4. Max/min函数返回满足where条件的一列的最大/最小值:

Select max(列名) from tablename [WHERE where_definition]

例,查询数学成线最高分和最低分:

clip_image046

6. 分组与过滤:

1. 使用group by 子句对列进行分组:

SELECT column1, column2. column3.. FROM table group by column

例,按照ID分组并对数据成绩求和:

clip_image047

2. 使用having 子句过滤:

SELECT column1, column2,column3 ... FROM table group by column having ...

Having和where均可实现过滤,但在having可以使用合计函数,having通常跟在group by后,它作用于组。

例,按id分组,查询数学成绩组总和大于100的组:

clip_image048

例,查询数据成绩>=90的学生:

clip_image049

7. 时间日期相关函数:

ADDTIME (date2 ,time_interval )

将time_interval加到date2

CURRENT_DATE (  )

当前日期

CURRENT_TIME (  )

当前时间

CURRENT_TIMESTAMP ( )

当前时间戳

DATE (datetime )

返回datetime的日期部分

DATE_ADD (date2 , INTERVAL d_value d_type )

在date2中加上日期或时间

DATE_SUB (date2 , INTERVAL d_value d_type )

在date2上减去一个时间

DATEDIFF (date1 ,date2 )

两个日期差

NOW (  )

当前时间

YEAR|Month|DATE (datetime )

年月日

8. 字符串相关函数:

CHARSET(str)

返回字串字符集

CONCAT (string2  [,... ])

连接字串

INSTR (string ,substring )

返回substring在string中出现的位置,没有返回0

UCASE (string2 )

转换成大写

LCASE (string2 )

转换成小写

LEFT (string2 ,length )

从string2中的左边起取length个字符

LENGTH (string )

string长度

REPLACE (str ,search_str ,replace_str )

在str中用replace_str替换search_str

STRCMP (string1 ,string2 )

逐字符比较两字串大小,

SUBSTRING (str , position  [,length ])

从str的position开始,取length个字符

LTRIM (string2 ) RTRIM (string2 )

去除前端空格或后端空格

9. 数学相关函数:

ABS (number2 )

绝对值

BIN (decimal_number )

十进制转二进制

CEILING (number2 )

向上取整

CONV(number2,from_base,to_base)

进制转换

FLOOR (number2 )

向下取整

FORMAT (number,decimal_places )

保留小数位数

HEX (DecimalNumber )

转十六进制

LEAST (number , number2  [,..])

求最小值

MOD (numerator ,denominator )

求余

RAND([seed])

RAND([seed])

10. 定义表的约束:

1. 定义主键:

Primary key,在预定义主键的列后边加上此属性。

例,创建student表时,将id设为主键:

clip_image050

删除、添加主键属性:

clip_image051

2. 定义非空约束:

not null,在预定义主键的列后边加上此属性:

例,将name列设置为非空:

clip_image052

此时,当向表中添加新数据时,name必须指定值。可以使用“is null”判断某一记录的值是否为空。

3. 定义列值自动增长:

Auto_increment,在预定义主键的列后边加上此属性:

例,定义id为主键且自动增长:

clip_image053

4. 定义外键约束:

这个是今天课程中,唯一涉及到两个表的SQL语句操作。

constraint ordersid_FK foreign key(ordersid) references orders(id),在预定义外键的列后边加上此属性:

例,定义一个classes表,然后再定义一个students表:

创建classes表:

clip_image054

创建students表:

clip_image056

当向students表中添加一条记录时,如果指定的class_id值在classes表中不存在,添加就会失败!如果对应的classes表中的id值被修改了,那么也需要手动修改students表中的class_id值。

如果创建库和表,以及对它们的操作过多的话,逐条手动键入SQL语句是一件痛苦的事。SQL的脚本文件(*..sql)可以为我们解决这一难题。Sql文本文件中保存的是我们要手动键入所有的SQL语句,使用source filename语句,导入sql脚本文件。比如:“source C:\test.sql”。

OK,终于搞完了!也当做练习了,不过是按照老方的PPT一步步来的,有点侵权的感觉。不过我想没问题的,老方对此会很高兴的。

SQL语句本身并不复杂,做为程序员并不需要完全掌握数据库。数据库的优化上全由DBA来做。我们需要掌握对数据库的增、删、改、查这些SQL语句即可!

今日的课程没有多深的理论与实践,主要就是讲解SQL语句。同学们学习效果很好!

posted @ 2009-11-30 14:39 長城 阅读(858) | 评论 (0)编辑 收藏

2009年11月29日

     摘要:            今日的课程内容是JavaWEB国际化和EL表达式,EL表达式在之前的课程中有使用过,但并未深入。今日的内容整体上比较轻松,当我看到JavaWEB国际化时,还以为内容很多。国际化吗!以为在某些编写操作上有什么国际化的特殊要求?呵呵,其实我们的编写方式本身就已经是国际化的了。这里的国际化是...  阅读全文

posted @ 2009-11-29 18:55 長城 阅读(974) | 评论 (1)编辑 收藏