数据库API的封装

来源:互联网 发布:阿拉善see基金会 知乎 编辑:程序博客网 时间:2024/06/05 01:00

对于要使用数据库的应用来说,一般会由数据库的开发人员提供一套封装好的API而非直接操作数据库,这样上层应用便不太需要关心如何进行数据的存取等细节问题,更好的代码的封装有利于提高其重用性、可维护性等。当然,对此问题Hibernate[hbnt]已提供了足够的支持,它提供分页[hbpg]、缓存机制[hbch]。但若由于各种原因,不能或不想使用hibernate的话,可自己提供一套。

1       Hibernate

先简单了解下hibernate做的工作,那么自己要写的接口也是类似的。

Hibernate会根据表的字段,生成一个数据库表到Java对象的映射文件,据此映射文件再生成对应的Java类及DAODataAccess Objects,数据访问对象)。

对于一个简单 Student表,生成的映射文件如下:

<?xml version="1.0"encoding="utf-8"?>

<!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<!--

   Mapping file autogenerated by MyEclipse Persistence Tools

-->

<hibernate-mapping>

   <class name="examble.hibernatemap.Student" table="STUDENT"schema="COLLEGE">

       <id name=" id" type="java.lang.String">

            <column name="ID"length="40" />

            <generatorclass="assigned" />

       </id>

       <property name="name" type="java.lang.String">

            <column name="NAME"length="40" not-null="true" />

       </property>

       <set name="courses"inverse="true">

           <key>

               <column name="SID" length="40" />

           </key>

            <one-to-many class="sample.hibernatemap.StudentCourse"/>

       </set>

 </class>

</hibernate-mapping>

 

注:

如果还存在一对多/多对多关系的话,如一个学生可选择多个课程,Student StudentCourse存在一对多关系,则在property元素之后还会有一个set元素,如上面xml文件中的灰色阴影部分。

DAO的接口如下(增加了一个简单的测试),仍对应数据库中的增删查改:

public class StudentDAO {

 //添加一个学生

            publicstatic boolean save(Student  aStudent) {…}

           

            //添加一个学生

            publicstatic boolean update(Student  aStudent){…}

           

            //删除一个学生

            publicstatic boolean deleteById(String id) {…}

           

            //获取所有学生

            publicstatic List<Student> findAll() {..}

           

//获取某个学生

            publicstatic Student findById(String id) {…}

                       

            //根据某个属性获取学生

            publicstatic List< Student > findByField(String fieldname, String fieldvalue) {

                                   

//根据特定查询语句获取学生

            publicstatic List< Student > findBySql(String sqlStr) {…}

                       

            //一个简单的测试

            public staticvoid main(String[] args) {

                        //增加一名学生

                        Studentstudent = new Student(“001”, “Zhang San”);

                        booleanresident = StudentDAO.save(student);

 

                        System.out.println(“save:  ” + result);                     

}

}

 

下面是一个实际的例子:

2       代码1 ,数据库操作:(这里是Oracle数据库)

package ling.sample.db;

 

import java.sql.*;

import javax.sql.*;

 

import java.util.UUID;

 

import java.io.*;

import java.util.Properties;

 

//DataSource

import oracle.jdbc.pool.*;

import javax.naming.Context;

import javax.naming.InitialContext;

 

public class DB

{          

            //格式为"jdbc:oracle:thin:@ip:port:dbName";

           

            privatestatic String url = "jdbc:oracle:thin:@192.168.0.110:1521:myoracle";

            privatestatic String userName = "myoracle";

            privatestatic String password = "myoracle";

           

            publicstatic final String ORACLE_DRIVER ="oracle.jdbc.driver.OracleDriver";

 

            publicstatic Connection createConection()

            {          

                        try

                        {

                                    //加载Driver

                                    Class.forName(DB.ORACLE_DRIVER);

                                   

                                    Connectionconnection = DriverManager.getConnection(url, userName, password);

                                   

                                    returnconnection;

                        }

                        catch(Exceptionex)

                        {

                                    System.out.println(ex.getMessage());

                        }

                       

                        returnnull;

 

            }

           

            publicstatic void closeConnecion(Connection connection)

            {

                        if(connection!= null)

                        {

                                    try

                                    {

                                                connection.close();

                                    }

                                    catch(Exceptionex)

                                    {

                                                System.out.println(ex.getMessage());

                                    }

                        }

                       

            }

           

            publicstatic void closeStatement(Statement statement)

            {

                        if(statement!= null)

                        {

                                    try

                                    {

                                                statement.close();

                                    }

                                    catch(Exceptionex)

                                    {

                                               

                                    }

                        }

            }

           

            publicstatic void closeResultSet(ResultSet resultSet)

            {

                        if(resultSet!= null)

                        {

                                    try

                                    {

                                                resultSet.close();

                                    }

                                    catch(Exceptionex)

                                    {

                                                System.out.println(ex.getMessage());

                                    }

                        }

            }

           

           

            publicstatic ResultSet executeQuery(Connection connection, String sql)

                        throwsSQLException

            {                      

                        Statementstatement = connection.createStatement();

                        ResultSetresultSet = statement.executeQuery(sql);

                       

                        returnresultSet;

            }

           

            publicstatic ResultSet executeQuery(String sql)

            {

                        Connectionconnection = DB.createConection();

                        ResultSetresultSet = null;

                        try

                        {

                                    resultSet= DB.executeQuery(connection, sql);

                        }

                        catch(SQLExceptionex)

                        {

                                   

                        }

                        finally

                        {

                                    DB.closeConnecion(connection);

                        }

                       

                        returnresultSet;

            }

           

            publicstatic boolean executeUpdate(Connection connection, String sql)                       

            {

                        intresult = 0;

                        Statementstatement = null;

                       

                        try

                        {

                                    statement= connection.createStatement();

                                    result= statement.executeUpdate(sql);

                        }

                        catch(Exceptionex)

                        {

                                   

                        }

                        finally

                        {

                                    DB.closeStatement(statement);

                        }

                       

                        returnresult > 0;

                       

            }

           

            publicstatic boolean executeUpdate(String sql)                

            {                      

                        Connectionconnection = DB.createConection();                

                       

                        if(connection== null)

                        {

                                    returnfalse;

                        }

                       

                        try

                        {

                                    returnDB.executeUpdate(connection, sql);                        

                        }

                        catch(Exceptionex)

                        {

                                   

                        }

                        finally

                        {                                  

                                    DB.closeConnecion(connection);

                        }

                       

                        returnfalse;

                       

            }

           

            /**

             * 生成一个唯一的id

             */

            publicstatic String createUUID()

            {

                        returnUUID.randomUUID().toString();

            }

           

            /**

             * 使用DataSource接口创建一个连接。

             * 此种方式移植性更好,只需要在本机配置数据库的数据源即可。

             * @return

             */

            publicstatic Connection createConnectionFromDS()

            {

                        try

                        {

                                    OracleDataSourceoracelDataSource = new OracleDataSource();

                                    oracelDataSource.setServerName("SERVER-CENTER");

                                    //oracelDataSource.setURL("202.117.118.45");

                                    oracelDataSource.setDatabaseName("myoracle");

                                   

                                    Contextcontext = new InitialContext();

                                    context.bind("jdbc/repace",oracelDataSource);

                                   

                                    DataSourcedataSource = (DataSource) context.lookup("jdbc/myoracle");

                                   

                                    Connectionconnection = dataSource.getConnection("myoracle","myoracle");

                                   

                                   

                                    returnconnection;

                        }

                        catch(Exceptionex)

                        {

                                   

                        }

                       

                        returnnull;

                       

            }

           

            publicstatic void main(String[] args)

            {                      

                        Connectionconnection = DB.createConection();

                        //Connectionconnection = DB.createConnectionFromDS();

                       

                        if(connection!= null)

                        {

                                    System.out.println("Connectto oralce successfully!");

                        }

                        else

                        {

                                    System.out.println("Faliledto connect to oralce!");

                        }

            }

           

}

 

为简单起见,这里所有的数据使用的是staticstring私有数据及方法,这样使用时可以不必保存DB对象。

也可以将数据库的配置数据写在一个属性文件中(如何使用java读取/设置属性文件参考,如何读取环境变量参考http://ling091.javaeye.com/admin/blogs/354052)。

文件中的值如下:

IP= 192.168.0.110

port=1521

serviceName=myoracle

userName=myoracle

password=myoracle

代码如下(需要包含头文件java.util.Properties,如用Eclipse 可以使用Ctrl-Shift-O自动包含未包含的头文件,Mac上使用Cmd-Shift-O):

private staticString[] readProperties()

            {

                        StringpropFile = DB.PROP_FILE;

                       

              //根目录保存在环境变量中

                        StringmuleHome = System.getenv("ORACLE_EXAMPLE_HOME");

                        if(dirHome != null)

                        {

                                   

                                    propFile= dirHome + "//userconf//" +propFile;

                        }

                       

                        //如果不存在配置文件

                        /*File file = new File(propFile);

                        if(!file.exists() )

                        {

                                    System.out.println("找不到配置文件oracel.conf,使用程序默认配置!");

                                    return null;

                        }*/

                       

                        String[]properties = new String[5];

                        String[]propNames = {"IP", "port", "serviceName","userName", "password"};

                       

                        Propertiesprops = new Properties();

                        InputStreamistream = null;

                         

                        try

                        {

                                    istream= new BufferedInputStream (new FileInputStream(propFile) );

                                    props.load(istream);

                                    for(inti = 0; i < propNames.length; i++)

                                    {

                                                properties[i]= props.getProperty (propNames[i]);                         

                                    }

                        }

                        catch (Exception e)

                        {

                                    e.printStackTrace();

                        }              

                        finally

                        {

                                    try

                                    {

                                                istream.close();

                                    }

                                    catch(Exception e)

                                    {

                                                e.printStackTrace();

                                    }

                        }

                       

                        return  properties;

            }

3       代码2 Student

4       代码3 StudentDAO

对于有一对多,多对多的对象,DAO的实现可根据需求而定。可以每张数据表(student表, course)单独实现DAO,然后为关联表(student_course表)实现表征studentcourse关系的DAO,这意味着为每张表实现一个DAO。但如果两者关系更为密切,如表1与表2是一对多的关系,在类的层面上,表2更合适作为表1内部属性,可以将直接定义成一个对象。如联系人也可以放在学生的属性中。

这需要根据需要权衡,如同在数据库中将属性用另外的表存储还是作为已有表的属性存储,xml中作为attribute还是element是类似的。

package ling.example.oracle.dao;

 

import java.sql.*;

 

import javax.sql.*;

import java.util.*;

 

 

import example.oracle.db.*;

import example.oracle.data.*;

 

 

public class StudentDAO

{

            publicstatic boolean save(Student student)

            {

                        Stringsql = "insert into student(id, name) values(" +

                                                +"'" + student.getID() + "',"

                                                +"'" + student.getName() + "')";

                       

                        DB.executeUpdate(sql);

            }

           

           

           

            publicstatic boolean update(Student student)

            {                      

                        Stringsql = "update student set name = '"

                                    +student.getName()                         

                                    +"' where id = '"

                                    +student.getID()

                                    +"'";

                       

                        returnDB.executeUpdate(sql);

            }

           

            publicstatic boolean deleteById(String id) 

            {

                        Stringsql = "delete from student where id = '" + id + "'";

                       

                        returnDB.executeUpdate(sql);

            }

           

            publicstatic boolean deleteAll()      

            {

                        Stringsql = "delete from student”;

                       

                        returnDB.executeUpdate(sql);

            }

           

            //删除满足query查询的学生

            publicstatic boolean deleteByQuery(String querySQL)      

            {

                        Stringsql = "delete from student where id in (" + querySQL + “)”;

                       

                        returnDB.executeUpdate(sql);

            }

 

           

            publicstatic List<Student> findBySQL(String sql)

            {                      

                        Connectionconnection = DB.createConection();

                        Statementstatement = null;

                        ResultSetresultSet = null;

                       

                        if(connection== null)

                        {

                                    returnnull;

                        }

                       

                        try

                        {

                                    //ResultSetresultSet = DB.executeQuery(connection, sql);

                                   

                                    statement= connection.createStatement();

                                    resultSet= statement.executeQuery(sql);

                                   

                                    List<Student>studentList = new ArrayList<Student>();

                                    while(resultSet.next())

                                    {

                                                Studentstudent = new Student(

                                                                        resultSet.getString(1),

                                                                        resultSet.getString(2));

                                               

                                                studentList.add(student);

                                    }

                                   

                                   

                                    returnstudentList;

                        }

                        catch(Exceptionex)

                        {

                                   

                        }

                        finally

                        {

                                    DB.closeResultSet(resultSet);

                                    DB.closeStatement(statement);

                                    DB.closeConnecion(connection);

                        }

                       

                        returnnull;

            }

           

            //如果有多个属性时,可以使用该查询

            publicstatic List<Student> findByFiled(String fieldName, String fieldValue)

            {                      

                        Stringsql = "select id, name from student where "

                                    +fieldName

                                    +" = '"

                                    +fieldValue

                                    +"'";

                                   

                        returnfindBySQL(sql);

            }

           

            publicstatic Student findById(String studentid)

            {

                        List<Student>studentList = findStudentByFiled("studentid", studentid);

                       

                        if(students!= null && students.length > 0)

                        {

                                    returnstudentList[0];

                        }

                       

                        returnnull;

            }

           

            publicstatic List<Student> findAll ()

            {

                        Stringsql = "select id, name, password from student";

                       

                        returnfindBySQL(sql);

            }

           

            publicstatic void main(String[] args)

            {                      

                        booleanresult = false;

                       

                        //--------save----------

                       

                        Studentstudent = new Student( "001", "zhang san");

           

                       

                        result= StudentDAO.saveStudent(student);

                        System.out.println("save:" + result);                      

                       

            }

                       

}

 

 

如果有多条语句同时执行,可以使用基本的数据库操作进行:

//这里是一个复杂插入的例子,比如一个学生有多个联系人方式

//这里使用基本的数据库操作。

public static booleansaveStudent(Student student)

{

            Connection connection =DB.createConection();

            PreparedStatement pstatement = null;

            PreparedStatement pstatement2 = null;

            PreparedStatement pstatement3 = null;

           

            if(connection == null)

            {

                        return false;

            }

           

            try

            {

                        connection.setAutoCommit(false);

                       

                        String sql = "insert into student(id, name) values (?, ?)";

                        pstatement =connection.prepareStatement(sql);

                       

                        String studentid =student.getID();

                       

                        pstatement.setString(1,  studentid);

                        pstatement.setString(2,student.getName() );

                       

                        int result =pstatement.executeUpdate();

                                               

                        //插入联系人

                       

                        ContractPerson[]contractPersons = student.getContractPersons();

                        if(contractPersons!= null && contractPersons.length > 0)

                        {

                                    sql = "insert into contractPerson(id, name, phone_number)values(?, ?, ?)";

                                    String sql3= "insert intostudent_contractPerson(id, contract_id) values(?, ?)";

 

                                   

                                    pstatement2= connection.prepareStatement(sql);

                                    pstatement3= connection.prepareStatement(sql3);

                                   

                                    int i = 0;

                                    int count =roles.length;

                                    for(; i < count;++i)

                                    {                                                          

                                                Stringcontractid = DB.createUUID();

                                               

                                                pstatement2.setString(1,  );

                                                pstatement2.setString(2,contractPersons[i].getName() );

                                                pstatement2.setString(3,contractPersons[i].getPhoneNumber() );

                                               

                                                pstatement2.executeUpdate();                                            

                                                pstatement2.clearParameters();

                                                                                   

                                                pstatement3.setString(1,studentid);

                                                pstatement3.setString(2,contractid);

                                               

                                                //先执行语句2 ,再执行语句3

                                                pstatement3.executeUpdate();        

                                                pstatement3.clearParameters();

                                    }

                                   

                        }

                       

                        connection.commit();

                       

                        return true;

            }

            catch(SQLException ex)

            {

                        try

                        {

                                    connection.rollback();

                        }

                        catch(Exception ex)

                        {

                                    System.out.println(ex.getMessage());

                        }

            }

            finally

            {

                        DB.closeStatement(pstatement);

                        DB.closeStatement(pstatement2);

                        DB.closeStatement(pstatement3);

                        DB.closeConnecion(connection);

                       

            }

                                                           

            return false;

           

}

 

5       参考

[hbpg] Hibernate实现分页查询的原理分析.http://www.javaeye.com/topic/261.2003.09.

如果相应的数据库定义了限定查询记录的sql语句,那么直接使用特定数据库的sql语句。如果数据库不支持分页的SQL语句,那么根据在配置文件里面
#hibernate.jdbc.use_scrollable_resultset true
默认是true,如果你不指定为false,那么Hibernate会使用JDBC2.0scrollableresult来实现分页。如果支持scrollableresult,使用ResultSetabsolute方法直接移到查询起点,如果不支持的话,使用循环语句,rs.next一点点的移过去。

可见使用Hibernate,在进行查询分页的操作上,是具有非常大的灵活性,Hibernate会首先尝试用特定数据库的分页sql,如果没用,再尝试Scrollable,如果不行,最后采用rset.next()移动的办法。

在查询分页代码中使用Hibernate的一大好处是,既兼顾了查询分页的性能,同时又保证了代码在不同的数据库之间的可移植性。

 

[hbch] Hibernate 缓存机制. http://www.360doc.com/content/10/0407/10/1158044_21911705.shtml.2010.04

[dahb] 一个通用的DAO接口及Hibernate 实现.http://jayjunyu.javaeye.com/blog/215838.  2008.07.

[hbqp] Hibernate Dao层的处理实例. 有模糊查询和 分页. http://hi.baidu.com/xiaoxiaolq/blog/item/50c5961839488ab14bedbc70.html.2008.05.

 

原创粉丝点击