数据库API的封装

本文介绍了一种不依赖Hibernate的情况下,手动实现一个简易的ORM框架的方法。从理解Hibernate的工作原理出发,逐步介绍了如何通过Java代码实现数据库表与对象的映射,并提供了基本的增删查改操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

1        Hibernate

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

Hibernate会根据表的字段,生成一个数据库表到 Java对象的映射文件,据此映射文件再生成对应的 Java类及 DAO Data Access 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" />

            <generator class="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 {

  //添加一个学生

            public static boolean save(Student  aStudent) {…}

           

            //添加一个学生

            public static boolean update(Student  aStudent) {…}

           

            //删除一个学生

            public static boolean deleteById(String id) {…}

           

            //获取所有学生

            public static List<Student> findAll() {..}

           

//获取某个学生

            public static Student findById(String id) {…}

                       

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

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

                                   

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

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

                       

            //一个简单的测试

            public static void main(String[] args) {

                        //增加一名学生

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

                        boolean resident = 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";

           

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

            private static String userName = "myoracle";

            private static String password = "myoracle";

           

            public static final String ORACLE_DRIVER = "oracle.jdbc.driver.OracleDriver";

 

            public static Connection createConection()

            {          

                        try

                        {

                                    //加载 Driver

                                    Class.forName(DB.ORACLE_DRIVER);

                                   

                                    Connection connection = DriverManager.getConnection(url, userName, password);

                                   

                                    return connection;

                        }

                        catch(Exception ex)

                        {

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

                        }

                       

                        return null;

 

            }

           

            public static void closeConnecion(Connection connection)

            {

                        if(connection != null)

                        {

                                    try

                                    {

                                                connection.close();

                                    }

                                    catch(Exception ex)

                                    {

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

                                    }

                        }

                       

            }

           

            public static void closeStatement(Statement statement)

            {

                        if(statement != null)

                        {

                                    try

                                    {

                                                statement.close();

                                    }

                                    catch(Exception ex)

                                    {

                                               

                                    }

                        }

            }

           

            public static void closeResultSet(ResultSet resultSet)

            {

                        if(resultSet != null)

                        {

                                    try

                                    {

                                                resultSet.close();

                                    }

                                    catch(Exception ex)

                                    {

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

                                    }

                        }

            }

           

           

            public static ResultSet executeQuery(Connection connection, String sql)

                        throws SQLException

            {                      

                        Statement statement = connection.createStatement();

                        ResultSet resultSet = statement.executeQuery(sql);

                       

                        return resultSet;

            }

           

            public static ResultSet executeQuery(String sql)

            {

                        Connection connection = DB.createConection();

                        ResultSet resultSet = null;

                        try

                        {

                                    resultSet = DB.executeQuery(connection, sql);

                        }

                        catch(SQLException ex)

                        {

                                   

                        }

                        finally

                        {

                                    DB.closeConnecion(connection);

                        }

                       

                        return resultSet;

            }

           

            public static boolean executeUpdate(Connection connection, String sql)                       

            {

                        int result = 0;

                        Statement statement = null;

                       

                        try

                        {

                                    statement = connection.createStatement();

                                    result = statement.executeUpdate(sql);

                        }

                        catch(Exception ex)

                        {

                                   

                        }

                        finally

                        {

                                    DB.closeStatement(statement);

                        }

                       

                        return result > 0;

                       

            }

           

            public static boolean executeUpdate(String sql)                

            {                      

                        Connection connection = DB.createConection();                

                       

                        if(connection == null)

                        {

                                    return false;

                        }

                       

                        try

                        {

                                    return DB.executeUpdate(connection, sql);                        

                        }

                        catch(Exception ex)

                        {

                                   

                        }

                        finally

                        {                                  

                                    DB.closeConnecion(connection);

                        }

                       

                        return false;

                       

            }

           

            /**

              * 生成一个唯一的 id

              */

            public static String createUUID()

            {

                        return UUID.randomUUID().toString();

            }

           

            /**

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

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

              * @return

              */

            public static Connection createConnectionFromDS()

            {

                        try

                        {

                                    OracleDataSource oracelDataSource = new OracleDataSource();

                                    oracelDataSource.setServerName("SERVER-CENTER");

                                    //oracelDataSource.setURL("202.117.118.45");

                                    oracelDataSource.setDatabaseName("myoracle");

                                   

                                    Context context = new InitialContext();

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

                                   

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

                                   

                                    Connection connection = dataSource.getConnection("myoracle", "myoracle");

                                   

                                   

                                    return connection;

                        }

                        catch(Exception ex)

                        {

                                   

                        }

                       

                        return null;

                       

            }

           

            public static void main(String[] args)

            {                      

                        Connection connection = DB.createConection();

                        //Connection connection = DB.createConnectionFromDS();

                       

                        if(connection != null)

                        {

                                    System.out.println("Connect to oralce successfully!");

                        }

                        else

                        {

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

                        }

            }

           

}

 

为简单起见,这里所有的数据使用的是 static string私有数据及方法,这样使用时可以不必保存 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 static String[] readProperties()

            {

                        String propFile = DB.PROP_FILE;

                       

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

                        String muleHome = 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" };

                       

                        Properties props = new Properties();

                        InputStream istream = null ;

                         

                        try

                        {

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

                                    props.load(istream);

                                    for (int i = 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表)实现表征 student course关系的 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

{

            public static boolean save(Student student)

            {

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

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

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

                       

                        DB.executeUpdate(sql);

            }

           

           

           

            public static boolean update(Student student)

            {                      

                        String sql = "update student set name = '"

                                    + student.getName()                         

                                    + "' where id = '"

                                    + student.getID()

                                    + "'";

                       

                        return DB.executeUpdate(sql);

            }

           

            public static boolean deleteById(String id) 

            {

                        String sql = "delete from student where id = '" + id + "'";

                       

                        return DB.executeUpdate(sql);

            }

           

            public static boolean deleteAll()      

            {

                        String sql = "delete from student”;

                       

                        return DB.executeUpdate(sql);

            }

           

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

            public static boolean deleteByQuery(String querySQL)      

            {

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

                       

                        return DB.executeUpdate(sql);

            }

 

           

            public static List<Student> findBySQL(String sql)

            {                      

                        Connection connection = DB.createConection();

                        Statement statement = null;

                        ResultSet resultSet = null;

                       

                        if(connection == null)

                        {

                                    return null;

                        }

                       

                        try

                        {

                                    //ResultSet resultSet = DB.executeQuery(connection, sql);

                                   

                                    statement = connection.createStatement();

                                    resultSet = statement.executeQuery(sql);

                                   

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

                                    while(resultSet.next() )

                                    {

                                                Student student = new Student(

                                                                        resultSet.getString(1),

                                                                        resultSet.getString(2) );

                                               

                                                studentList.add(student);

                                    }

                                   

                                   

                                    return studentList;

                        }

                        catch(Exception ex)

                        {

                                   

                        }

                        finally

                        {

                                    DB.closeResultSet(resultSet);

                                    DB.closeStatement(statement);

                                    DB.closeConnecion(connection);

                        }

                       

                        return null;

            }

           

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

            public static List<Student> findByFiled(String fieldName, String fieldValue)

            {                      

                        String sql = "select id, name from student where "

                                    + fieldName

                                    + " = '"

                                    + fieldValue

                                    + "'";

                                   

                        return findBySQL(sql);

            }

           

            public static Student findById(String studentid)

            {

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

                       

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

                        {

                                    return studentList[0];

                        }

                       

                        return null;

            }

           

            public static List<Student> findAll ()

            {

                        String sql = "select id, name, password from student";

                       

                        return findBySQL(sql);

            }

           

            public static void main(String[] args)

            {                      

                        boolean result = false;

                       

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

                       

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

           

                       

                        result = StudentDAO.saveStudent(student);

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

                       

            }

                       

}

 

 

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

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

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

public static boolean saveStudent(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 into student_contractPerson(id, contract_id) values(?, ?)" ;

 

                                   

                                    pstatement2 = connection.prepareStatement(sql);

                                    pstatement3 = connection.prepareStatement(sql3);

                                   

                                    int i = 0;

                                    int count = roles.length;

                                    for (; i < count; ++i)

                                    {                                                          

                                                String contractid = 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.0 scrollable result来实现分 页。 如果支持 scrollable result,使用 ResultSet absolute方法直接移到查询起点,如果不支持的话,使用循环语句, 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.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值