Integrating JDBC with Hibernate

本文介绍如何在Hibernate数据访问对象类中无缝集成手动SQL,通过实现org.hibernate.jdbc.Work接口并利用Session的doWork方法,可以在不破坏现有对象模型的情况下执行SQL语句。

One of the powerful things about Hibernate is that you do not typically need to manually write SQL: you build a domain model that represents your data model in an object-oriented manner and then interact with your domain model. This is the ideal, but sometimes you need to model a legacy data model or a data model that is not object-oriented in nature, which leads to either complicated Hibernate mappings or the inclusion of manual SQL. When this occurs, you do not want to have to build separate data access object classes but rather you would like to find a way to seamlessly integrate SQL into your existing data access object classes in a way that your consumers do not even realize that you're not using Hibernate Query Language (HQL) under-the-hood.

Fortunately you do not need to jump through too many hoops to integrate manual JDBC into your Hibernate classes, you just need to perform the following steps:

  1. Obtain access to your Hibernate's Session object
  2. Create a class that implements org.hibernate.jdbc.Work, or create an anonymous inner class that implements the Work interface, and implement the execute() method using the supplied Connection object to execute your SQL
  3. Pass the Work class to Hibernate's doWork() method, which in turn invokes your Work's execute() method

Listings 1 and 2 illustrate how to use the Work interface to execute a simple SQL statement.

Listing 1. MyDao.java
...
public class MyDao 
{
    ...
    public String getValue( long id )
    {
        // Create a SQL order of work, which we will use to execute a manual SQL statement
        MyWork myWork = new MyWork( id );

        // Gain access to the underlying Hibernate session
        Session session = getSessionFactory().openSession();

        // Ask the Hibernate session to execute the unit of work
        session.doWork( myWork );
        
        // Obtain the results of the unit of work
        return myWork.getValue();
    }
    ..
}

Listing 1 defines a getValue() method that accepts an id and returns a String. It creates a newMyWork instance, passing it the id as an initialization parameter, locates a Hibernate Session, and passes the MyWork instance to the Sessions doWork() method. After the query is complete, it retrieves the value from the MyWork class.

The mechanism that you use to obtain a Hibernate Session will be dependent on the technology with which you are building your data access object. If you're using Spring by extendingHibernateDaoSupport, you can invoke getSessionFactory().openSession() to create a new Session object.

Listing 2 shows the source code for the MyWork class.

Listing 2. MyWork.java
public class MyWork implements Work
{
    private long id;
    private String value;

    public MyWork( long id )
    {
        this.id = id;
    }

    public String getValue()
    {
        return value;
    }

    @Override
    public void execute( Connection connection ) throws SQLException
    {
        PreparedStatement ps = null;
        ResultSet rs = null;
        try
        {
            ps = connection.prepareStatement( "SELECT * FROM table WHERE id = ?" );
            ps.setLong( 1, id );
            rs = ps.executeQuery();
            while( rs.next() )  
            {
                value = rs.getString( 1 );
            }
        }
        catch( SQLException e ) { }
        finally  {
            if( rs != null )  
            {
                try {
                    rs.close();
                }
                catch( Exception e ) {}
            }
            if( ps != null ) 
            {
                try {
                    ps.close();
                }
                catch( Exception e ) {}
            }
        }
    }
}

The MyWork class implements its data access logic in its execute() method. The execute() method is passed a java.sql.Connection object that you can use as you normally would to create aStatementPreparedStatement, or CallableStatement. The doWork() method returns void, so it is up to you to develop a mechanism to return a value from your unit of work.

If you are executing SQL from which you do not necessarily need to retrieve results, you can accomplish the same results by creating an anonymous inner class:

       // Gain access to the underlying Hibernate session
        Session session = getSessionFactory().openSession();

        // Ask the Hibernate session to execute the unit of work
        session.doWork( new Work() {
            @Override
            public void execute( Connection connection ) {
                // Implement your SQL here
            }
	} );

In this example we create the Work() implementation in the doWork() method invocation and override the execute() method. Depending on your background this might look a bit strange, but once you get used to it, this is a fairly elegant way to implement your solution because it reduces the number of explicit classes you need to create and it couples the logic being executed with the invocation of that logic. For complicated cases you want to loosely couple things, but for a SQL statement it is overkill to create additional classes if you do not need to. The challenge here, however, is that if you need to obtain results from the query, you're limited because the doWork()method returns void.

Hibernate offers a simple mechanism to execute SQL inside your Hibernate data access object classes by defining a unit of work and passing it to your Hibernate Session's doWork() method. You can define your unit of work explicitly by creating a class that implements org.hibernate.jdbc.Workor by creating an anonymous inner class that implements the Work interface on-the-fly. The best solution, if you are building your domain model from scratch, is to model your objects as simply as you can (remember the KISS principle: keep it simple, stupid), but if you have to create a domain model that does not lend itself easily to an object-oriented representation then you can integrate manual SQL in this manner.

以下是将 Android HAL(Hardware Abstraction Layer)与 TinyALSA 集成的实用指南: ### 理解 Android HAL 和 TinyALSA Android HAL 是一个抽象层,用于将 Android 系统与底层硬件隔离开来,使得上层软件可以以统一的接口访问不同的硬件设备。TinyALSA 是一个轻量级的 ALSA(Advanced Linux Sound Architecture)库,用于在 Linux 系统上进行音频设备的控制和音频数据的处理。 ### 准备工作 - **环境搭建**:确保开发环境中已经安装了 Android NDK、SDK 以及相关的编译工具链。 - **获取 TinyALSA 源码**:可以从 TinyALSA 的官方仓库或者开源代码托管平台获取其源码。 ### 集成步骤 #### 1. 配置 Android.mk 或 CMakeLists.txt 在 Android HAL 模块的 Android.mk 或者 CMakeLists.txt 文件中添加对 TinyALSA 库的依赖。 **Android.mk 示例**: ```makefile LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := your_hal_module LOCAL_SRC_FILES := your_hal_source_files.c # 添加 TinyALSA 库的路径 LOCAL_C_INCLUDES += /path/to/tinyalsa/include # 链接 TinyALSA 库 LOCAL_SHARED_LIBRARIES := libtinyalsa include $(BUILD_SHARED_LIBRARY) ``` **CMakeLists.txt 示例**: ```cmake cmake_minimum_required(VERSION 3.4.1) add_library(your_hal_module SHARED your_hal_source_files.c) # 添加 TinyALSA 库的路径 include_directories(/path/to/tinyalsa/include) # 链接 TinyALSA 库 target_link_libraries(your_hal_module libtinyalsa) ``` #### 2. 包含 TinyALSA 头文件 在 Android HAL 模块的源代码文件中包含 TinyALSA 的头文件,以便使用其提供的 API。 ```c #include <tinyalsa/asoundlib.h> ``` #### 3. 使用 TinyALSA API 实现音频功能 在 Android HAL 模块中使用 TinyALSA 的 API 来实现音频设备的打开、关闭、音频数据的读写等功能。 **打开音频设备示例**: ```c #include <tinyalsa/asoundlib.h> struct pcm_config config; struct pcm *pcm; // 配置音频参数 config.channels = 2; config.rate = 44100; config.period_size = 1024; config.period_count = 4; config.format = PCM_FORMAT_S16_LE; config.start_threshold = 0; config.stop_threshold = 0; config.silence_threshold = 0; // 打开音频设备 pcm = pcm_open(0, 0, PCM_OUT, &config); if (!pcm || !pcm_is_ready(pcm)) { // 处理打开失败的情况 } ``` #### 4. 编译和测试 使用 Android NDK 或者 CMake 进行编译,将生成的库文件推送到 Android 设备上进行测试。 ### 注意事项 - **错误处理**:在使用 TinyALSA API 时,要注意对返回值进行检查,处理可能出现的错误情况。 - **资源管理**:在使用完音频设备后,要及时关闭设备,释放相关资源。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值