你是否会觉得奇怪?每次通过IDE运行的tomcat,让应用进行启动调试,发现他的页面都比我的钱包还干净,为什么呢,我之前添加了的好多项呢,说好的三点钟看书呢?
持久化基础
这时候,终于轮到持久化技术出场了,所谓持久化就是把数据转换为持久状态,如存储在文件或数据库中,以便能够持久的保存,这里介绍一下使用jdbc来进行数据库操作的方法,顺便在这时介绍一下jsp的bean。
jdbc是一个专用的数据库链接桥接的方法。提供里一套数据库操作的接口,然后由各个厂商对此进行实现,同时,各种的orm操作,实际上也可以说就是对jdbc的各种封装,也就是说,熟悉了一jdbc这种数据库操作的方法,也就几乎可以了解任意一种数据库操作的方式。
一般来说,对于基础数据库操作,统一成为crud才做,即Create(创建)、Read(读取)、Update(更新)和Delete(删除)的操作,现在大部分的业务应用,基本都是不同逻辑下的crud操作,对于这个项目来说,我们主要使用的操作为C和R,也就是:
- 插入一条todo项
- 读取todo列表
这样,即使服务重启,也可以从db中获取已经存在的信息,首先用mysql来实现这样一个功能.
mysql当然可以使用纯命令行的方式,但我们毕竟不是dba,我还是建议你使用一个ide,我使用的是SQLyog,具体的操作步骤以下几步:
创建数据库jtodos
CREATE DATABASE `jtodos` ;
创建数据库todos
CREATE TABLE `todos` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`item` varchar(100) DEFAULT NULL,
`createtime` datetime DEFAULT NULL,
`userid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
都非常简单,需要注意的是表内有userid字段,这个字段暂时不要了解,以后会使用。
最后,还要在maven库中找到jdbc的相关库,并添加到pom.xml中:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
dao操作
dao(Data Access Object)是数据访问对象的简称,我们使用此对象来封装db操作的api,在进行数据库操作之前,先封装一个数据库操作的工具类,以便在之后的代码里可以专注于逻辑实现,这个工具类放在com.niufennan.jtodos.utils
包内,类名为DatabaseHelper,是一个静态类,代码如下:
public static Connection getConnection(){
Connection connection=null;
try {
Class.forName(com.mysql.jdbc.Driver.class.getName());
connection= DriverManager.getConnection("jdbc:mysql://localhost:3306/sstest?serverTimezone=GMT%2b8","root","1234");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
public static void close(ResultSet rs, Statement statement, Connection connection){
if(rs!=null)
{
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement!=null)
{
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
这个类以后会复杂的多,但目前为止,只有获取链接和关闭链接两个方法即可。
需要说明的有三点:
- Class.forName(com.mysql.jdbc.Driver.class.getName());
加载jdbc驱动。
- connection= DriverManager.getConnection("jdbc:mysql://localhost:3306/jtodos?serverTimezone=GMT%2b8","root","1234");
建立链接,三个参数分别为链接数据库使用的url,数据库的用户名,数据库密码,注意url中的serverTimezone参数,这个是配置程序所使用的时区,这里显示使用的为东八区。即北京所在时区。
- 关闭链接需按顺序分别关闭。
然后是正常的数据库查询的业务类TodoDao
,这个类在com.niufennan.jtodos.dao
包内,此类只有两个方法,分别对应我们所需的操作,即C和R源代码如下:
public class TodoDao {
public List<Todo> getAll(){
Connection connection= null;
Statement statement=null;
ResultSet resultSet=null;
List<Todo> list=new ArrayList<Todo>();
try{
connection =DatabaseHelper.getConnection();
statement= connection.createStatement();
resultSet=statement.executeQuery("select * from todos");
while (resultSet.next()){
Todo todo=new Todo();
todo.setId(resultSet.getInt("id"));
todo.setItem(resultSet.getString("item"));
todo.setCreateTime(resultSet.getDate("createtime"));
todo.setUserId(resultSet.getInt("userid"));
list.add(todo);
}
}catch (SQLException ex){
new RuntimeException(ex);
}
finally {
DatabaseHelper.close(resultSet,statement,connection);
}
return list;
}
public void save(Todo todo){
Connection connection=null;
PreparedStatement statement=null;
try {
connection = DatabaseHelper.getConnection();
statement=connection.prepareStatement("INSERT INTO todos (item,createtime,userid)VALUES(?,?,?);");
statement.setString(1,todo.getItem());
statement.setDate(2,new Date(todo.getCreateTime().getTime()));
statement.setInt(3,todo.getUserId());
statement.executeUpdate();
}catch (SQLException ex){
throw new RuntimeException(ex);
}finally {
DatabaseHelper.close(null,statement,connection);
}
}
}
此类需要作为jsp内的javabean使用,所以必须具有javabean所需的特征:
1 必须是公开的和具体的
2 必须具有无参的构造函数
3 所有独立字段(如有)必须通过公开的get和set方法暴露
此类完全符合javabean的条件,所以他可以作为javabean使用
需注意两点:
1 todos表内id为自增长id,在insert的时候不需要也不允许设置
2 注意在插入时候的createtime字段,db中时间输入必须使用setTimestamp,否则会损失时分秒的部分,这时需要以时刻为参数,重新创建一个java.sql.Timestamp
输入。
jsb Bean
好,数据库操作类也完成,下面所要做的就是在jsp页面中使用它了,jsp页面中使用javabean的方法为jsp:useBean标签,继续修改index.jsp内的代码(貌似已经修改的千疮百孔了)
<jsp:useBean id="todoDao" class="com.niufennan.jtodos.dao.TodoDao"></jsp:useBean>
这样,jsp页面中就引入了TodoDao方法,id指的是在jsp中使用的句柄,class指向这个bean的全路径。
继续修改jsp中的代码块为:
<jsp:useBean id="todoDao" class="com.niufennan.jtodos.dao.TodoDao"></jsp:useBean>
<%
request.setCharacterEncoding("utf-8");
if(request.getParameter("todo")!=null){
Todo todo=new Todo();
todo.setCreateTime(new Date());
todo.setItem(request.getParameter("todo"));
todo.setUserId(0);
todoDao.save(todo);
}
List<Todo> todos=todoDao.getAll();
pageContext.setAttribute("todos",todos);
%>
可以看到,不在对application进行访问,而是直接使用todoDao,对数据库进行操作,并且,感觉代码都清爽了好多,运行一下:
ok 运行效果和之前一模一样,停止服务器再次运行,效果还是这样,故不再贴图。
最后再说几句
首先,我们使用了useBean的标签,他的作用域其实是application级别的,也就是说,他和之前我们使用的ArrayList一样,是存储在application中。
还有,现在这个应用是每次数据库操作都创建一个数据库链接,实际上数据库链接的开销非常大,一般来说都是使用数据库连接池,而现在很多的orm都是使用的数据库连接池操作。
从代码中可以看到了,数据库操作的代码都是又臭又长,非常容易出错和难以维护,哪怕执行一条select语句都要写一大度代码,还必须各种try catch,并且很多问题都不会引起编译错误,只有运行时的偶然因素才会引起错误,所以这块一般都是使用orm和各种数据库工具库,比如Apache common里就有dbutils的工具类,但现在我们暂时先这样,以后会慢慢的进行修改维护。
现在我所有的计划列表都已经存储到了db中,即使重启服务器,重启pc等任何操作也不会改变计划,但是,我做的应用仅仅是为了自己使用么?如果其他人也同样使用这个应用会怎么样呢?下一章将解答这个问题.
感谢您的观看!