
【项目需求】 在整个考试系统中,我们可将其分为三个部分:考试前、考试中以及考试后。最近一周都在做考试前的配置,我负责的是题库模块,学生考试时是需要从题库中抽题的。而题库,又有不同的题型,单选题、多选题等等。但还有填图题,音频题,这些题目的图片和音频都需要存在Mongo数据库中,所以,我开始了我的Mongo实践之旅。 【Mongo入门】 1.什么是MongoDB MongoDB是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。 MongoDB将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB文档类似于JSON对象。字段值可以包含其他文档,数组及文档数组。 2.MongoDB的特点 MongoDB的提供了一个面向文档存储,操作起来比较简单和容易。 Mongo支持丰富的查询表达式。查询指令使用JSON形式的标记,可轻易查询文档中内嵌的对象及数组。 GridFS是MongoDB中的一个内置功能,可以用于存放大量小文件。 MongoDB允许在服务端执行脚本,可以用Javascript编写某个函数,直接在服务端执行,也可以把函数的定义存储在服务端,下次直接调用即可。 MongoDB支持各种编程语言:RUBY,PYTHON,JAVA,C++,PHP,C#等多种语言。 MongoDB安装简单...... 3.MongoDB的下载与安装 参考教程:http://www.runoob.com/mongodb/mongodb-window-install.html 【开发环境】 VS2012、MongoDB for Windows 64-bit、MVC框架、EasyUI 【项目实现】 对Mongo有了一些了解之后,那么下面就实战一下,看看如何实现文件的批量上传。 因为需要实现批量上传,所以需要借助Uploadify插件。 我们先从前台页面布局样式开始: 1.添加Mongo批量上传插件的引用 @* 引用EasyUI样式 *@ <link rel="stylesheet" type="text/css" href="../Content/jquery-easyui-1.3.2/themes/default/easyui.css"> <link rel="stylesheet" type="text/css" href="../Content/jquery-easyui-1.3.2/themes/icon.css"> <link rel="stylesheet" type="text/css" href="../Content/jquery-easyui-1.3.2/demo/demo.css"> <script type="text/javascript" src="../Content/jquery-easyui-1.3.2/jquery-1.8.0.min.js"></script> <script type="text/javascript" src="../Content/jquery-easyui-1.3.2/jquery.easyui.min.js"></script> @*引用mongo批量上传的插件*@ <link href="../Scripts/uploadify-v3.1/uploadify.css" rel="stylesheet"> <script src="../../Scripts/uploadify-v3.1/jquery.uploadify-3.1.min.js"></script> <script src="../Content/jquery-easyui-1.3.2/locale/easyui-lang-zh_CN.js"></script> 2.前台页面布局设计<div style="margin-left:700px;margin-top:-600px;"> <div id="q" data-options="iconCls:' icon-save'" class="easyui-panel" title="音频图片文件管理" style="width: 400px; height: 500px; padding: 20px;"> @* 批量上传文件到Mongo按钮 *@ <div style="margin-left:20px;margin-top:20px;"> <input type="file" id="file_upload" name="file_upload" value="添加文件"/> </div> <div style="margin-top: 5px;margin-left:20px;"> <a id="upload" class="easyui-linkbutton" data-options="iconCls:'icon-export'" style="padding-left: 30px;margin-top:10px;" >上传</a><br /> <a id="cancel" class="easyui-linkbutton" data-options="iconCls:'icon-cancel'" style="padding-left: 30px;margin-top:10px;">取消</a> </div> </div> </div> 3.按钮样式的设置<style> .uploadify-button{ color:#444; border: 1px solid #b7d2ff; filter: none; background: #eaf2ff; height:25px; width:90px; } .uploadify:hover .uploadify-button{ background:#eaf2ff; color:#000000 } .center { width: 1000px; margin: 5px auto; } </style> 前台布局样式确定了,下面就真正开始功能的实现。 1.Client端 使用MongoDB,需要先在客户端添加三个引用,MongoDB、MongoDB Bson和MongoDB Driver。 2.Controller: 在MVC框架下的Controller中,类似于写了一个MongoHelper类,其中可接受前台传来的四种操作,"LIST"(获取文件列表);"DELETE"(删除文件);"UPLOAD"(上传文件);"DOWNLOAD"(下载文件)。本篇博客,仅看上传文件方法: public class MongodbHelpController : Controller { // // GET: /MongodbHelp/ //全局变量 private static MongoDatabase DB; public static string fileTable = "fs";//相当于我们需要操作的表的名称 //Sets up the environment. public void Init() { //连接本地数据库 string ConnectionString = "127.0.0.1"; //ConfigurationManager.AppSettings["mondoDbConnection"]; if (String.IsNullOrEmpty(ConnectionString)) { throw new ArgumentNullException("Connection string not found."); } MongoServerSettings mongoSetting = new MongoServerSettings(); mongoSetting.MaxConnectionPoolSize = 15000;//设定最大连接池 mongoSetting.WaitQueueSize = 500;//设定等待队列数 mongoSetting.Server = new MongoServerAddress(ConnectionString, 27017); int count = MongoServer.MaxServerCount; MongoServer server = MongoServer.Create(mongoSetting);//创建连接数据文件 DB = server.GetDatabase("DBTest");//创建数据库连接 } public void ProcessRequest() { Init();//initialize the mongo //获取前台页面的action值 string action = Request.Form["action"]; switch (action) { case "LIST": GetFileList(); break; //获取文件列表 case "UPLOAD": Upload(); break; //上传文件 case "DELETE": Delete(); break;//删除文件 case "DOWNLOAD": DownFile(); break; //下载文件 } } public bool IsReusable { get { return false; } } //上传文件 public void Upload() { try { //设置一次只上传一个文件,值为File //设置上传多个文件,值为Filedata; HttpPostedFileBase file = (HttpPostedFileBase)Request.Files["Filedata"]; //获取文件 int nFileLen = file.ContentLength; MongoGridFSSettings fsSetting = new MongoGridFSSettings() { Root = fileTable }; MongoGridFS fs = new MongoGridFS(DB, fsSetting); byte[] myData = new Byte[nFileLen]; file.InputStream.Read(myData, 0, nFileLen); //调用Write、WriteByte、WriteLine函数时需要手动设置上传时间 //通过Metadata 添加附加信息 MongoGridFSCreateOptions option = new MongoGridFSCreateOptions(); option.UploadDate = DateTime.Now; //创建文件,文件并存储数据 using (MongoGridFSStream gfs = fs.Create(file.FileName, option)) { gfs.Write(myData, 0, nFileLen); gfs.Close(); } } catch (Exception e) { Response.Write(0); } Response.End(); } } 3.JavaScript: 在Controller中写好了方法,下面我们只需要在前台页面写JS调用即可。下面是JS代码: //================上传文件到Mongo-胡志婷-2016年3月29日14:28:26================// $("#file_upload").uploadify({ 'auto': false, //是否自动上传 'buttonText': '添加文件', //按钮显示文本 'successTimeout': 99999, //成功等待时间 'swf': '../../Scripts/uploadify-v3.1/uploadify.swf', //uploadify路径 'uploader': '/MongodbHelp/ProcessRequest', //定义服务器端上传数据处理脚本文件swf的路径 'multi': true, //允许选择多个文件 'fileSizeLimit': '1600MB', //文件最大的大小 'queueSizeLimit': 10, //一次最多可选择的文件数量 'progressData': 'speed', //上传文件显示的样式,进度条 'onSelectError': function (file, errorCode, errorMsg) { //出错提示 switch (errorCode) { case -100: alert("上传的文件数量已经超出系统限制的" + jQuery('#file_upload').uploadify('settings', 'queueSizeLimit') + "个文件!"); break; case -110: alert("文件 [" + file.name + "] 大小超出系统限制的" + jQuery('#file_upload').uploadify('settings', 'fileSizeLimit') + "大小!"); break; case -120: alert("文件 [" + file.name + "] 大小异常!"); break; case -130: alert("文件 [" + file.name + "] 类型不正确!"); break; } }, 'onQueueComplete': function (queueData) { //所有文件被处理完成时触发该事件 getFiles(); alert("文件上传成功!"); return; } }); //上传按钮 $("#upload").click(function () { $("#file_upload").uploadify('settings', 'formData', { action: 'UPLOAD' }); $("#file_upload").uploadify('upload', '*'); }); //取消按钮 $("#cancel").click(function () { $("#file_upload").uploadify('cancel', '*'); }); 整个功能,实现的代码也就完成了,下面看看实现过程中的效果: 点击添加文件,选择需要上传的文件: 点击上传,文件开始上传: 上传的功能应该说是学习Mongo必须有的一个实践,通过这样一个实践,其它的需求,如下载,查询等,实现就更加简单了。在此也不一一列举了。 【项目感悟】 1.学习既需要广度,也需要深度。在上一版ITOO项目中,自己每天都会利用些时间去了解项目中的技术点,所以对于Mongo的学习,前面有过一些了解,也有一些简单的实践,那可以算是广度上的学习。这一次,项目中再遇到,可以算是一次深度的学习了。 2.站在巨人的肩膀上。在自己身边,总会有一些已经接触或是学习过,自己正在或正要接触或学习的东西。不妨适当的问问他们,也可以帮助自己快速找到解决方案或是达到自己的学习目标。 3.什么东西都需要去做。没有做之前,可能只会觉得难。又是一个新东西,又不知道如何开始,一个又一个的疑问,不停地怀疑自己,只会耽误自己的效率。
【背景介绍】 在使用SQL Server数据库期间,想必大家一定都有过解决各种问题的经历了,很多时候,都会在大家的博客中看到问题与解决方案。现在开发使用的是MySQL数据库,现在来看,发现自己在MySQL中的经历越来越多。前两天,自己电脑的MySQL数据库出问题了,折腾了我好几个小时~~ 这篇博客就将把之前遇到的和这次遇到的错误记录下来,以后也可以更好更快的找到解决办法吧。 【常见错误】 (1) windows mysql提示:1045 access denied for user'root'@'localhost' using password yes 参考链接:http://blog.csdn.net/so1127/article/details/6619844 因为在解决这个问题的时候,需要用到my.ini文件,安装完后并没有这个文件,从网上查的是可以自己创建,于是我就自己创建了一个这样的文件。内容如下: # For advice on how to change settings please see # http://dev.mysql.com/doc/refman/5.6/en/server-configuration-defaults.html # *** DO NOT EDIT THIS FILE. It's a template which will be copied to the # *** default location during install, and will be replaced if you # *** upgrade to a newer version of MySQL. [mysqld] # Remove leading # and set to the amount of RAM for the most important data # cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%. # innodb_buffer_pool_size = 128M # Remove leading # to turn on a very important data integrity option: logging # changes to the binary log between backups. # log_bin # These are commonly set, remove the # and set as required. basedir = E:\MySQL\mysql-5.6.24-winx64 datadir = E:\MySQL\mysql-5.6.24-winx64\data # port = 8099 # server_id = sa # Remove leading # to set options mainly useful for reporting servers. # The server defaults are faster for transactions and fast SELECTs. # Adjust sizes as needed, experiment to find the optimal values. # join_buffer_size = 128M # sort_buffer_size = 2M # read_rnd_buffer_size = 2M sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION" skip-grant-tables default-character-set=utf8 这个问题就解决了,在加上这个文件后,我尝试建立新用户,又出现了一个新的问题。 (2) ERROR 1364(HY000):Field 'ssl_cipher' doesn't have a default value 参考博客:http://xiejianglei163.blog.163.com/blog/static/12472762014424048216/ 我照着博客的内容将my.ini文件中的一句话改了: sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION" 修改为 sql-mode="NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION" 此后,我也成功创建了用户。 这两个问题解决了,我在学习网上商城的时候也就一切顺利。 但前两天,重启电脑后,数据库又出现了下面的一系列问题了。 (3) 启动MySQL服务,出现错误1067: 参考链接:http://jingyan.baidu.com/article/d5c4b52bee6e69da560dc5ec.html 出现这个问题,我采取的办法是方法二,将my.ini文件删除,这样MySQL服务就可以正常启动了。 但将my.ini文件删除后,一直出现1045的错误,就这样,两个问题好像死循环了,一直都解决不了。无奈之下,卸载了mysql,重新安装了一次。 在这里卸载/安装的过程就不说了,下面继续看几个遇到的MySQL的错误: (4) 2003-Can't connect to MySQL server on 'localhost'(10061) 出现这个错误的原因,是MySQL服务没有启动,可输入service.msc窗口命令,进入到服务管理,将MySQL服务启动就行。或者使用mysql命令启动也可以。 (5) Host "localhost" is not allowed to connect to mysql server 这是在本地都不能登录到MySQL数据库。 参考链接:http://www.cnblogs.com/ycsfwhh/archive/2011/02/18/1957980.html 首先,停止mysql服务:sc stop mysql 然后,mysqld --skip-grant-tables 另开一个终端,继续,mysqlcheck --check-upgrade --all-databases --auto-repair 再输入mysql,终于提示连接成功了。 本地可以连接成功了,下面别人在远程自己的数据库时,可能又会遇到1045的错误。 (6) Access denied for user 'root'@'localhost' (using password:YES) 解决方法: 方案一:改表 use [databasename]; select user,host,password from user; update user set host = '%' where user='root'; 方案二:授权 GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456' WITH GRANT OPTION; FLUSH PRIVILEGES;(任何主机都可以连接到mysql服务器) (7) 中文乱码问题 在做ITOO项目的时候,从代码中直接插入记录到数据库中,中文便是乱码了。第一版思修考试的时候,时间紧张,没有完全解决这个问题,部分可以导入中文,部分又导入的是乱码。在接下来的这一版开发中,终于找到了问题的根源。 乱码缘由: 不同的编码格式会导致同一字符,在不同字符集下的编码会不同。同样同一编码在不同的字符集中代码的字符也不相同。当你的MySQL返回的字符串的编码格式(字符集)与你的客户工具程序(mysql, php, query browser, ...)当前使用的字符集不同时,就会造成乱码。 乱码后需要检查的信息: 1. 数据库表中字段的字符集设置 。 show create table TableName 或 show full columns from tableName 2. 当前联接系统参数 show variables like 'char%' 提示: 中文,应确保表中该字段的字符集为中文兼容,具体包含以下四种: big5 | Big5 Traditional Chinese gb2312 | GB2312 Simplified Chinese gbk | GBK Simplified Chinese utf8 | UTF-8 Unicode 乱码原因: 上图是我在检查上面两条信息的结果,很明显,所连接的数据库设置的字符集为latin1,所以,导入数据的时候就变成乱码了。 解决方案: 用Navicat软件打开对应的数据库,将其数据库属性的字符集设置为utf8. 【错误总结】 很多情况下,都遇到1045的错误,在查资料的过程中,发现普遍的原因有以下两点: 1.可能是mysql用户表中存在不完整的记录; 2.可能是没有给mysql用户表中的用户授予权限。 因为mysql数据库不像sql server数据库那样,可以在可视化的界面进行操作,在mysql中,各种操作都是需要通过各种命令去完成的,下面,就总结一些常用的命令,以便提高后期的工作效率。 服务启动与停止 net stop mysql net start mysql 登录mysql mysql -r root -p 回车 输入密码 显示数据库列表 show databases; 选择数据库和显示数据表 use mysql; show tables; 建库、删库 create database dbName; drop database dbName; 备份 mysqldump -u [数据库用户名] -p [要备份的数据库名称]>[备份文件的保存路径] 例子:mysqldump -u root -p test>E:\tt.sql 还原 mysql -u root -p<[备份文件的保存路径] 【学习心得】 1.数据库的备份很重要。因为不知道什么时候,什么原因,自己的数据库就不能用了,等到发生了,后悔也来不及了。 2.没有什么解决不了的问题,最坏的办法也就是重头再来。遇到问题了,第一次感觉还好,但遇到了一些没在自己意料之中的问题,遇到了以前的解决方案不再适用这一次的问题,心情就有些不一样了。最后,我还是自己把数据库给弄好了,事实证明,不要放弃,最坏的办法也就是重头再来。3.学习是一个漫长的、不断补充、不断积累的过程。实际上,解决中文乱码的问题是后来补充的,因为一直都在使用mysql,一直处在不断学习地过程中,后面的学习或者偶尔的遇见,才使得自己把之前的问题解决了,所以,学习前后是一个互为补充的阶段。
【项目概要】 最近进入了一个新的项目,手机移动端的开发。微信平台,现在是家喻户晓。而自己没想到,这么快,就可以亲身接触到这样一个微信平台开发项目中。如何使得我们写HTML页面去适应各种手机,这就是在这个项目中,需要我们去做处理的一方面。 【项目基础】 HTML,大家都有很长一段时间的接触了,前台页面,一直是比较薄弱和不重视的地方。如果在面试时,让自己手写一段HTML代码,恐怕是难以下笔。而这一次,加入到项目组中,是让我们先从前台页面开始,HTML5+JS,实现手机移动端的开发。 HTML5,其实,对于我们来说,并不算是一种新的语言。它和HTML之间有着深厚的渊源。如下所述: 与HTML相比,HTML5具有更多的优点,在保留了html优势的基础上去其糟粕,加入新元素,比如:图形的绘制,多媒体内容,更好的页面结构,更好的形式处理,和几个api拖放元素,定位,包括网页应用程序缓存,存储,网络工作者等,让网站的制作更简单,同时更便于工作人员的维护。 【项目实战】 而在了解了HTML5之后,便开始自己着手写前台页面了。 这一次开发,和以前最大的不同在于:之前我们都是将各种内边距、外边距之类的写成固定值,以适应我们在电脑上的观看。这一次,因为是手机端开发,各种品牌手机的屏幕大小不同,如果将值写成固定值,那么开发出来的页面兼容性效果会很差,难以适应各种主流手机。所以,开发手机端的工作重点核心就在于:如何使得自己编写的代码,适应各种不同类型的移动端。 至此,我们对手机端的开发也熟悉了不少,下面我将结合着自己的开发经历来说说开发中的那些事。 刚进入组织,就好比看热闹看新鲜,又不时感叹不可思议,莫名其妙,什么东西都是陌生的,什么东西都是高大上的。手足无措、一脸茫然,很确切地可以形容自己刚进入组织的那一天。但凭借着师姐的精心指导,加上自己之前的调试经验,慢慢上手了的感觉。 其实,手写了一些代码之后,便慢慢清楚了自己要做的是什么了。就拿自己做的页面来说,看起来很复杂,其实在宏观上控制好每个部分,就很容易实现了。 如上图所示:我将整个页面划分成了个数不等、大小相等的派单,每个派单也划分为了六个部分,将各个部分的大小进行适当布局,这就使得页面上的整体布局不会乱。整体上布局没问题了,再细化到各个小部分,最终的效果也就可以达到了。 整个页面下来,HTML代码+JS代码有1000多行,也不全部展示了,下面以上图的第1(文字)+第2(图片)部分为例,让大家看看如何编写代码。 左边的1部分,每一行都是一个div样式,右边的2部分,放置的是一个img框和一个存放星星的div。 <!-- 左上部分样式设置 --> <div class="containerLeftUp" style="float:left;"> <!-- 每行字体样式设置 --> <div class="container1-1" style="text-align:left;color;#3e3a39;font-family:PingFangSC-Medium, sans-serif;">派单号:201505068584</div> <div class="container1-2" style="text-align:left;color:#ffffff;font-family: PingFangSC-Regular, sans-serif;">名称型号:格力空调GL/5036</div> <div class="container1-3" style="text-align:left;color:#ffffff;font-family: PingFangSC-Regular, sans-serif;">保养内容:空调清洗</div> <div class="container1-4" style="text-align:left;color:#ffffff;font-family: PingFangSC-Regular, sans-serif;">位置:客厅</div> <div class="container1-5" style="text-align:left;color:#ffffff;font-family: PingFangSC-Regular, sans-serif;">申请时间:2015-5-6 10:16</div> <span style="white-space:pre"> </span><!-- 右上部分图片样式设置 --> <div class="containerRightUp"> <!-- 图片框 --> <img class="img01" src="img/023.png"> <!-- 星星图片样式设置 --> <div> <img class="img02" src="img/23-1.png" style="float:left"> <img class="img03" src="img/23-1.png" style="float:left;"> <img class="img04" src="img/23-1.png" style="float:left"> <img class="img05" src="img/23-2.png" style="float:left"> <img class="img06" src="img/23-2.png" style="float:left"> </div> </div> </div> 在以上HTML代码中,达到的目的是实现页面布局,其中设置一些固定不变的属性,如字体颜色、对齐方式和浮动样式等。对于高度、宽度和边距等需要随手机变化而变化的属性,就需要在js代码中编写。 部分js代码: //自适应设置,左上部分DIV var len=document.getElementsByClassName("containerLeftUp").length; for(i=0;i<len;i++){ document.getElementsByClassName("containerLeftUp").item(i).style.height=260/1334 * windowHeight + "px"; //设置高度 document.getElementsByClassName("containerLeftUp").item(i).style.width=470/750 * windowWidth + "px"; //设置宽度 } //自适应设置,每行字体DIV var len =document.getElementsByClassName("container1-1").length; for(i=0;i<len;i++){ document.getElementsByClassName("container1-1").item(i).style.marginTop=30/1334 * windowHeight + "px"; //顶部外边距 document.getElementsByClassName("container1-1").item(i).style.marginLeft=30/750 * windowWidth + "px"; //左部外边距 document.getElementsByClassName("container1-1").item(i).style.fontSize=(32*windowWidth/750)+"px";//字体大小 } //自适应设置,图片样式设置 var len =document.getElementsByClassName("img01").length; for(i=0;i<len;i++){ document.getElementsByClassName("img01").item(i).style.marginTop=60/1334 * windowHeight + "px"; document.getElementsByClassName("img01").item(i).style.height=140/1334 * windowHeight + "px"; document.getElementsByClassName("img01").item(i).style.marginLeft=8/750 * windowWidth + "px"; } var len =document.getElementsByClassName("img02").length; for(i=0;i<len;i++){ document.getElementsByClassName("img02").item(i).style.marginTop=10/1334 * windowHeight + "px"; document.getElementsByClassName("img02").item(i).style.marginBottom=2/1334 * windowHeight + "px"; document.getElementsByClassName("img02").item(i).style.height=25/1334 * windowHeight + "px"; document.getElementsByClassName("img02").item(i).style.width=25/1334 * windowHeight + "px"; } 依据此方法,将每个DIV都添加对应的自适应设置,就可以较好地实现页面布局适应手机屏幕了。但手机品牌不同,对代码的解析也是有不同的处理结果,所以为了更好地适应各个品牌的手机,在网上找到了分辨手机品牌的代码,根据手机品牌,调用不同的js方法,从而使得所有手机都可以很好地适应了。 辨别手机品牌的js代码:<script language="javascript"> window.onload = function () { var u = navigator.userAgent; if (u.indexOf('Android') > -1 || u.indexOf('Linux') > -1) {//安卓手机 alert("安卓手机"); } else if (u.indexOf('iPhone') > -1) {//苹果手机 alert("苹果手机"); } else alert("安卓手机");//不能辨别的,默认为安卓手机 } </script> 【项目感悟】 1.全局认识是第一位。拿到一个页面,首先要考虑的就是应该把这个界面分为多少个部分。这样才会使得整体布局不会乱。 2.精益求精。做一个页面,花的时间真的很多,因为UI是个特别细致的工作,他们的要求很高,也许我们开发人员觉得页面已经做的很好,但他们也会觉得有很多不完美的地方。 3.前端基础知识积累。这一次,在调试整个前端的时候,对以前不熟悉的前台样式属性更加熟悉了,同时,也接触到了很多之前没有接触过的样式设置。 4.勇于尝试,快速进入状态。刚接触一个新东西的时候,难免会觉得陌生,如何快速进入工作状态,也是对自己的一个考验。我们只有敢于尝试,快速迈出第一步,才会让自己更快地找到得心应手的感觉。
【学习概要】 在上篇博客中,介绍了两个Web层的规范,本篇博客,继续J2EE十三个规范的学习,下面要介绍的便是数据层的JDBC。 【学习笔记】 一.什么是JDBC JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。 二.JDBC的优势 1.有了JDBC API,就不必为Sybase数据库专门写一个程序,为Oracle数据库又专门写一个程序等等。程序员只要用JDBC API写一个程序就行,它可以向相应数据库发送SQL调用。同时,将java语言和JDBC结合起来使程序员不必为不同的平台编写不同的应用程序。 2.JDBC可扩展了java的功能。用java和JDBC API可以发布含有applet的网页,而改applet使用的信息可能来自远程数据库。企业也可以用JDBC通过Intranet将所有支援镰刀一个或多个内部数据库中,即使他们之间所用的操作系统不同。 3.java和JDBC的结合,使得信息传播变得容易和经济。企业可以继续使用他们安装好的数据库,并能便捷地存取信息,即使信息在不同的数据库管理系统上。 三.JDBC的用途 简单地说,JDBC可做以下四件事: 1.使得连接到数据库 2.创建SQL或MySQL语句 3.执行SQL或MySQL的查询数据库 4.查看和修改结果记录 四.JDBC的架构 JDBC API支持两层和三层处理模型进行数据库访问,但在一般的JDBC体系结构由两层组成: 1.JDBC API:提供了应用程序对JDBC的管理连接。 2.JDBC Driver API:支持JDBC管理到驱动器连接。 以下是一种结构图,它显示了JDBC驱动程序和Java应用程序的位置: 五.JDBC的创建 创建JDBC应用程序有以下6个步骤: 1.导入数据包 . 需要包括含有需要进行数据库编程的JDBC类的包。大多数情况下,使用 import java.sql.* 就可以了. 2.注册JDBC驱动程序. 需要初始化驱动程序,可以与数据库打开一个通信通道。 3.打开连接. 需要使用DriverManager.getConnection() 方法创建一个Connection对象,它代表与数据库的物理连接。 4.执行查询 . 需要使用类型声明的对象建立并提交一个SQL语句到数据库。 5.从结果集中提取数据 . 要求使用适当的关于ResultSet.getXXX()方法来检索结果集的数据。 6.清理环境. 需要明确地关闭所有的数据库资源相对依靠JVM的垃圾收集。 下面是一个创建JDBC的完整代码: //STEP 1. Import required packages import java.sql.*; public class FirstExample { // JDBC driver name and database URL static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; static final String DB_URL = "jdbc:mysql://localhost/EMP"; // Database credentials static final String USER = "username"; static final String PASS = "password"; public static void main(String[] args) { Connection conn = null; Statement stmt = null; try{ //STEP 2: Register JDBC driver Class.forName("com.mysql.jdbc.Driver"); //STEP 3: Open a connection System.out.println("Connecting to database..."); conn = DriverManager.getConnection(DB_URL,USER,PASS); //STEP 4: Execute a query System.out.println("Creating statement..."); stmt = conn.createStatement(); String sql; sql = "SELECT id, first, last, age FROM Employees"; ResultSet rs = stmt.executeQuery(sql); //STEP 5: Extract data from result set while(rs.next()){ //Retrieve by column name int id = rs.getInt("id"); int age = rs.getInt("age"); String first = rs.getString("first"); String last = rs.getString("last"); //Display values System.out.print("ID: " + id); System.out.print(", Age: " + age); System.out.print(", First: " + first); System.out.println(", Last: " + last); } //STEP 6: Clean-up environment rs.close(); stmt.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(conn!=null) conn.close(); }catch(SQLException se){ se.printStackTrace(); }//end finally try }//end try System.out.println("Goodbye!"); }//end main }//end FirstExample 【学习比较】 在很早之前,我们就知道了ODBC,而JDBC和ODBC间又有什么样的联系和不同呢。 目前,Microsoft 的 ODBC API 可能是使用最广的、用于访问关系数据库的编程接口。它能在几乎所有平台上连接几乎所有的数据库。然而,为什么java不使用ODBC呢。答案是可以使用,但不适合直接使用。 因为ODBC是用C语言接口,从java调用本地C代码再安全性、实现、坚固性和移植性方面都有缺陷。此外,java中没有指针,而ODBC对指针的应用很广泛。 JDBC API是建立在ODBC基础上的,它保留了ODBC的基本设计特征。它们之间最大的区别在于:JDBC以java风格与优点为基础并进行优化,因此更加易于使用。【学习感悟】 对于数据层JDBC的学习,感觉就好像要轻松一些。因为对ODBC有一定的了解,并且对数据库的操作,也是固定的几件事:连接、执行、查询等。不过现在的学习还是很零散的,后面系统的学习与编程相信会更有共鸣。
【学习概要】 这是关于J2EE十三个规范的第三篇博客,在前两篇博客中,我们了解的是Web层和数据访问层的规范,本篇博客将介绍更加复杂的业务逻辑层的规范——EJB。 【学习笔记】 一.EJB是什么? 百度百科: EJB是J2EE服务器端组件模型,设计目标与核心应用是部署分布式应用程序。简单来说就是把已经编写好的程序(即:类)打包放在服务器上执行。凭借java跨平台的优势,用EJB技术部署的分布式系统可以不限于特定的平台。 二.EJB与J2EE EJB (Enterprise JavaBean)是J2EE(javaEE)的一部分,定义了一个用于开发基于组件的企业多重应用程序的标准。其特点包括网络服务支持和核心开发工具(SDK)。 在J2EE里,Enterprise Java Beans(EJB)称为Java 企业Bean,是Java的核心代码,分别是会话Bean(Session Bean),实体Bean(Entity Bean)和消息驱动Bean(MessageDriven Bean)。 通过对以上两点的了解,对EJB的理解好像还是有些含糊,不妨看看下面的一张图,从图中去回答到底EJB是什么,有那么神秘吗? 有了上面这张图,首先明确的一点是:EJB属于J2EE体系中的业务逻辑部分 下面再看一张关于EJB的结构图: 用更加通俗的话说,EJB就是“把你编写的软件中那些需要执行制定的任务的类,不放到客户端软件上了,而是给他打成包放到一个服务器上了”。 三.EJB的三个组件 1.Session Bean,它可以是有状态的,也可以是无状态的。每当客户端请求时,容器就会选择一个SessionBean来为客户端服务。Session Bean可以直接访问数据库,但更多时候,它会通过Entity Bean实现数据访问。 2.Entity Bean,用于实现O/R映射,负责将数据库中的表记录映射为内存中的Entity对象,事实上,创建一个Entity Bean对象相当于新建一条记录,删除一个Entity Bean会同时从数据库中删除对应记录,修改一个Entity Bean时,容器会自动将Entity Bean的状态和数据库同步。 3.MessageDriven Bean,它基于JMS消息,只能接收客户端发送的JMS消息然后处理。MDB实际上是一个异步的无状态SessionBean,客户端调用MDB后无需等待,立刻返回,MDB将异步处理客户请求。这适合于需要异步处理请求的场合,比如订单处理,这样就能避免客户端长时间的等待一个方法调用直到返回结果。 四.EJB的优势 选择使用EJB,可以完成复杂的工作,例如: 1.开发人员只关注业务逻辑的实现,而不是底层的实现机制。 2.支持事务处理,多个业务操作要么同时成功,要么全部失败。 3.可根据应用的增长而扩展。 4.提供了负载均衡。 5.提供资源的访问权限控制。 【学习感悟】 第一次接触这么庞大的EJB,对于其概念,自己也是一遍又一遍地去阅读仅有几行的文字解释,看完后,感觉自己清楚了不少,但回过头去想,又觉得自己还是不明白。第一遍的学习,自己也只能总结成这样了,大部分的东西都还是来自于巨人的肩膀,自己的理解不透彻,还是以多看看资料为主。