如果你想开发一个应用(1-5)

你是否会觉得奇怪?每次通过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();
        }
    }
}

这个类以后会复杂的多,但目前为止,只有获取链接和关闭链接两个方法即可。

需要说明的有三点:

  1. Class.forName(com.mysql.jdbc.Driver.class.getName());

加载jdbc驱动。

  1. connection= DriverManager.getConnection(“jdbc:mysql://localhost:3306/jtodos?serverTimezone=GMT%2b8”,”root”,”1234”);

建立链接,三个参数分别为链接数据库使用的url,数据库的用户名,数据库密码,注意url中的serverTimezone参数,这个是配置程序所使用的时区,这里显示使用的为东八区。即北京所在时区。

  1. 关闭链接需按顺序分别关闭。

然后是正常的数据库查询的业务类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等任何操作也不会改变计划,但是,我做的应用仅仅是为了自己使用么?如果其他人也同样使用这个应用会怎么样呢?下一章将解答这个问题.

感谢您的观看!