`
ootabc
  • 浏览: 110570 次
  • 性别: Icon_minigender_1
  • 来自: 湖南
社区版块
存档分类
最新评论

hibernate 存储过程

阅读更多
User.hbm.xml文件的内容如下:

<?xml version="1.0"?>

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

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


<hibernate-mapping package="com.amigo.proc.model">

    <class name="User" table="tbl_user">

        <id name="userid" column="userid">

            <generator class="assigned"/>

        </id>

        <property name="name" column="name" type="string" />

        <property name="blog" column="blog" type="string" />

    </class>

   

    <sql-query name="getUserList" callable="true">

        <return alias="user" class="User">

            <return-property name="userid" column="userid"/>

            <return-property name="name" column="name"/>

            <return-property name="blog" column="blog" />

        </return>

        {call getUserList()}

    </sql-query>

</hibernate-mapping>


在该文件中需注意<sql-query…></sql-query>中的这段代码,调用的存储过程在其中定义,并定义了调用存储过程后将记录组装成User对象,同时对记录的字段与对象的属性进行相关映射。


public class ProcTest {


    /** *//**

     * @param args

     */

    public static void main(String[] args) throws Exception {

        ProcTest proc = new ProcTest();

        Session session = HibernateSessionFactory.getSession();

        proc.testProcQuery(session);

        proc.testProcUpdate(session);

        System.out.println("update successfully");

       

        proc.testProcInsert(session);

        System.out.println("insert successfully");

       

        proc.testProcDelete(session);

        System.out.println("delete successfully");

        session.close();

    }

   

    /** *//**

     * 测试实现查询的存储过程

     * @throws Exception

     */

    private void testProcQuery(Session session) throws Exception {

        //查询用户列表

        List list = session.getNamedQuery("getUserList").list();

        for (int i = 0; i < list.size(); i++) {

            User user = (User) list.get(i);   

            System.out.print("序号: " + (i+1));

            System.out.print(", userid: " + user.getUserid());

            System.out.print(", name: " + user.getName());

            System.out.println(", blog: " + user.getBlog());

        }

    }

   

    /** *//**

     * 测试实现更新的存储过程

     * @throws Exception

     */

    private void testProcUpdate(Session session) throws Exception {

        //更新用户信息

        Transaction tx = session.beginTransaction();

        Connection con = session.connection();

        String procedure = "{call updateUser(?, ?, ?)}";

        CallableStatement cstmt = con.prepareCall(procedure);

        cstmt.setString(1, "陈xx");

        cstmt.setString(2, "http://www.blogjava.net/sterningChen");

        cstmt.setString(3, "sterning");

        cstmt.executeUpdate();

        tx.commit();

    }


    /** *//**

     * 测试实现插入的存储过程

     * @throws Exception

     */

    private void testProcInsert(Session session) throws Exception {

        //创建用户信息

        session.beginTransaction();

        PreparedStatement st = session.connection().prepareStatement("{call createUser(?, ?, ?)}");

        st.setString(1, "amigo");

        st.setString(2, "阿蜜果");

        st.setString(3, "http://www.wblogjava.net/amigoxie");

        st.execute();

        session.getTransaction().commit();

    }

   

    /** *//**

     * 测试实现删除的存储过程

     * @throws Exception

     */

    private void testProcDelete(Session session) throws Exception {

        //删除用户信息

        session.beginTransaction();

        PreparedStatement st = session.connection().prepareStatement("{call deleteUser(?)}");

        st.setString(1, "amigo");

        st.execute();

        session.getTransaction().commit();

    }

}


   在本类中,调用查询类存储过程时,调用session.getNamedQuery("…")方法来获得User.hbm.xml中配置的查询存储过程。在其余的存储过程调用的测试中,首先通过hibernate的session获得connection,然后调用connection对象的相应方法来实现存储过程的调用。

该类的执行结果如下:

Hibernate: {call getUserList()}

序号: 1, userid: ant, name: 蚂蚁, blog: [url]http://www.blogjava.net/qixiangnj[/url]

序号: 2, userid: beansoft, name: bean, blog: [url]http://www.blogjava.net/beansoft[/url]

序号: 3, userid: sterning, name: 似水流年, blog: [url]http://www.blogjava.net/sterning[/url]

序号: 4, userid: tom, name: tom, blog: [url]http://www.blogjava.net/tom[/url]

update successfully

insert successfully

delete successfully


五.总结
   本例提出了在hibernate3中调用mysql的存储过程的实现方案,从本例可以看出,hibernate提供了在*.hbm.xml中配置调用存储过程,并通过向用户提供session.getNamedQuery(“…”)方法来调用配置的调用查询相关的存储过程的方法,另外,hibernate还提供了取得sql的connection的方法,从而能够通过connection中存储过程调用相关的方法来实现存储过程的调用。

DamYankee 2007-12-13 18:44

http://java.ccidnet.com/art/3737/20030124/472461_1.html
DamYankee 2007-12-15 15:48

Hibernate 要点

1. 三W What, Why, When 什么是, 为什么, 什么时候
        what:是一个 OR Mappming(O Object 对象 R relative 关系数据库 映射) 框架(framework)
        why:
        把一个对象的人 分解成一张横的表的几列
        Person => id, name, age
        根据对象自动生成对应的关系数据库的 SQL, 可以简化 Java 数据库开发, 代替 JDBC 来实现持久化(Persistence).
        when:
        1) 必须有明确的对象设计的时候才能用 Hibernate.
        2) 数据库是用大量的存储过程实现的 不能用 Hibernate !!!
        3) 如果多表查询, 也要慎重 Hibernate, 查询顺序不可预料(createSQLQuery(手写查询语句))
       
2. 怎么用
        1) 全局配置信息被 Configuration 类解析(配置解析器)
         a) 怎么连接数据库
        hibernate.cfg.xml
        获取数据库连接的参数(URL, username, password)
        方言 (Dialect) 为了对不同的数据库生成相应的 SQL
         b) 有那些映射文件需要处理

Configuration 类
Configuration类负责管理 Hibernate 的配置信息。Hibernate 运行时需要
获取一些底层实现的基本信息,其中几个关键属性包括:
数据库URL
数据库用户
数据库用户密码
数据库JDBC驱动类
数据库dialect,用于对特定数据库提供支持,其中包含了针对特定数据库特性
的实现,如Hibernate数据类型到特定数据库数据类型的映射等。
使用 Hibernate 必须首先提供这些基础信息以完成初始化工作,为后继操作做好准
备。这些属性在hibernate配置文件(hibernate.cfg.xml )中加以设 定.
调用:
Configuration config = new Configuration().configure();
时,Hibernate会自动在当前的 CLASSPATH 中搜寻 hibernate.cfg.xml文件并将其读
取到内存中作为后继操作的基础配置。Configuration 类一般只有在获取 SessionFactory
时需要涉及,当获取 SessionFactory 之后,由于配置信息已经由 Hibernate 维护并绑定
在返回的SessionFactory之上,因此一般情况下无需再对其进行操作。

示例的配置文件:
     
   <?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

<session-factory>
<!-- 显示后台的 SQL, 便于调试 -->
<property name="show_sql">true</property>
        <property name="connection.username">classiccars</property>
        <property name="connection.url">
                jdbc:derby://localhost:1527/myeclipse;create=true
        </property>
        <property name="dialect">org.hibernate.dialect.DerbyDialect</property>
        <property name="connection.driver_class">org.apache.derby.jdbc.ClientDriver</property>
        <property name="connection.password">myeclipse</property>
        
        <!-- 实体映射文件 -->
        <mapping resource="dao/User.hbm.xml" />

</session-factory>



        2) 实体类(POJO Plain and Old Java Ojbect) JavaBean 的要求
        值对象, 只有 getter, setter, 没有业务方法
        什么样的对象需要映射
     
  public class User implements java.io.Serializable {
                private int id;
                private String username;
                getxxx
                setxxx
        }

                a) 要有主键字段.
                b) 可序列化(缓存, 有时候在内存, 有时候放硬盘)

        3) 实体映射文件 实体名.hbm.xml
        告诉 Hibernate 怎么来做对象映射. 向哪个表插入数据, 每个属性的数据类型, 以及对应数据表里的列名.
        一个文件配置多个实体类也是可以的, 一般来说是一个实体一个配置文件.
<?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">
<hibernate-mapping>
    <class name="dao.User" table="users(数据库表格)" catalog="数据库名字">
    
    <!-- 主键字段配置, hibernate为我们生成主键id, 必须定义-->
        <id name="id" type="java.lang.Integer">
            <column name="id" />
            <generator class="increment" />
            <!-- increment 是先从数据库取最大ID然后加1, 再存入数据库 
            assigned 必须手工赋值给一个 ID
            auto, identify, sequence, native, uuid.hex, hilo 等等
            -->
        </id>
        
        <!-- property 默认把类的变量映射为相同名字的表列,当然我们可以修改其映射方式-->
        
        <!-- 类型写法两种 Hibernate type: string, int; Java 类的全名: java.lang.Integer -->
        <property name="username" type="java.lang.String">
                        <!-- 指定对应数据库中的字段信息 -->
            <column name="username" length="200" not-null="true" />
        </property>
        <property name="password" type="java.lang.String">
            <column name="password" length="20" not-null="true" />
        </property>
        <property name="age" type="java.lang.Integer">
            <column name="age" />
        </property>
    </class>
</hibernate-mapping>


多对多几乎没人用, 一对一常用, 一对多比较常用.

3. SessionFactory 和 Session
        SessionFactory ==> 等价于 DriverManager, 只需要一个.
SessionFactory 负责创建 Session 实例。可以通过 Configuation 实例构建
SessionFactory:

SessionFactory sessionFactory = config.buildSessionFactory();

Configuration实例config会根据当前的配置信息,构造 SessionFactory实例并返回。
SessionFactory 一旦构造完毕,即被赋予特定的配置信息。也就是说,之后 config 的任
何变更将不会影响到已经创建的 SessionFactory 实例(sessionFactory)。如果需要
使用基于改动后的 config 实例的 SessionFactory,需要从 config 重新构建一个
SessionFactory实例。

Session ==> 等价于 JDBC中的 Connection
Session实例通过SessionFactory实例构建:
Session session = sessionFactory.openSession();

完整示例代码:

// 0. 加载配置和驱动等, 生成 Session 工厂(相当于连接池或者 DriverManager)
Configuration config = new Configuration().configure();
SessionFactory sessionFactory = config.buildSessionFactory();
        // 1. 打开 session
        Session session = sessionFactory.openSession();
        // 2. 打开事务(Transaction)
        org.hibernate.Transaction tran = session.beginTransaction();
        // 3. 生成实体类
        User bean = new User();
        // 4. 给 bean 赋值
        bean.setUsername("zhangsan");
        // 5. 保存或者更新(并没有立即保存到数据)
        session.save(bean);
        // 6. 提交事务(真正的保存或者更新数据)
        tran.commit();

        // 7. 做查询, 首先创建查询对象
        String queryString = "from User";// HSQL 操作的是实体, 不是数据库表格
        Query query = getSession().createQuery(queryString);
        // 8. 读取查询结果
        java.util.List<User> result = query.list();

4. Transaction 事务
Hibernate 是 JDBC 的轻量级封装,本身并不具备事务管理能力。在事务管理层,
Hibernate将其委托给底层的JDBC或者JTA,以实现事务管理和调度功能。
Hibernate的默认事务处理机制基于JDBC Transaction。我们也可以通过配置文定采用JTA作为事务管理实现:

   
     <property name="hibernate.transaction.factory_class"> 
net.sf.hibernate.transaction.JTATransactionFactory 
<!--net.sf.hibernate.transaction.JDBCTransactionFactory-->
</property> 


将事务管理委托给 JDBC 进行处理无疑是最简单的实现方式,Hibernate 对于 JDBC
事务的封装也极为简单。
我们来看下面这段代码:
  
   session = sessionFactory.openSession(); 
      Transaction tx = session.beginTransaction(); 
     …… 
      tx.commit(); 

从JDBC层面而言,上面的代码实际上对应着:
 
      Connection dbconn = getConnection(); 
      dbconn.setAutoCommit(false); 
     …… 
      dbconn.commit(); 

就是这么简单,Hibernate并没有做更多的事情(实际上也没法做更多的事情),只
是将这样的JDBC代码进行了封装而已。

5. 查询对象 Query(Hibernate 参考文档的第11章) 和 HSQL
     普通查询如上所示
    
      带参数的查询(相当于 PreparedStatement)
     
  
  q = session.createQuery("from User u where u.name= :name");
     q.setString("name", "张三");
     q = session.createQuery("from User u where u.name= ?");
     q.setString(0, "张三");
     
     Native SQL 方式(用于特定的数据库的查询)
     List cats=session.createSQLQuery(
"SELECT {cat.*} FROM CAT {cat} WHERE ROWNUM<10",
"cat",
Cat.class
).list();
Listcat s=session.createSQLQuery(
"SELECT {cat}.ID AS {cat.id}, {cat}.SEX AS {cat.sex},"+
"{cat}.MATE AS{cat.mate}, {cat}.SUBCLASSAS {cat.class},..."+
"FROM CAT {cat} WHERE ROWNUM<10",
"cat",
Cat.class
).list();
     

     过滤重复记录:
     select distinct cat.name from Cat cat
6. 一对多, 多对一, 多对多中的懒惰加载 Lazy, Fetch
新版本的Hibernate在处理Session的时候已经内置了延迟加载机制,只有在真正发生数据库操作的时候,才会从数据库连接池获取数据库连接. 这会带来问题.
    例如一对多:
   <set 
            name="addresses" 
            table="t_address" 
            lazy="false" 
            inverse="false" 
            cascade="all" 
        > 
...              <one-to-many 
                  class="org.hibernate.sample.TAddress" 
              /> 
        </set> 

        示例代码:
     
  Query q = getSession().createQuery("from User");
List userList = q.list();    
TUser user =(TUser)userList.get(0); 
System.out.println("User name => "+user.getName()); 
Set hset = user.getAddresses(); 
session.close();//关闭Session   
TAddress addr = (TAddress)hset.toArray()[0]; 
System.out.println(addr.getAddress()); 


运行时抛出异常:
LazyInitializationException - Failed to lazily initialize a collection - no session or session was closed
如果我们稍做调整,将session.close放在代码末尾,则不会发生这样的问题。但是一般 DAO 执行结束后即关闭了 session.
这意味着,只有我们实际加载user关联的address时,Hibernate才试图通过
session从数据库中加载实际的数据集,而由于我们读取address之前已经关闭了
session,所以报出session已关闭的错误。
解决办法:
1) Hibernate.initialize方法可以通过强制加载关联对象实现这一功能:

Hibernate.initialize(user.getAddresses());
session.close();
2) 用 HQL 里面的 fetch
from User fetch all properties

3) lazy="false"

7. Hibernate 分页
int currentPage = 0;// 当前页
int pageSize = 10;// 显示记录数
String queryString = "from User";
Query queryObject = getSession().createQuery(queryString);
// 设置从哪里读
queryObject.setFirstResult((currentPage - 1) * pageSize);
// 设置一共读几行
queryObject.setMaxResults(pageSize);
return queryObject.list();

分享到:
评论

相关推荐

    hibernate存储过程

    而"hibernate存储过程"是指使用Hibernate来调用数据库中的存储过程。存储过程是预编译的SQL语句集合,通常用于执行复杂的业务逻辑或提高数据库性能。以下将详细介绍Hibernate如何与存储过程进行交互,并提供相关知识...

    hibernate调用存储过程

    ### Hibernate调用存储过程详解 在企业级应用开发中,Hibernate作为一款优秀的对象关系映射(ORM)框架,被广泛应用于Java持久层解决方案。而存储过程作为一种预编译的SQL代码块,在数据库层面执行,提供了高性能的...

    Hibernate存储过程的调用

    ### Hibernate存储过程调用详解 #### 一、概述 在软件开发过程中,为了提高数据库操作的性能和安全性,经常会使用到存储过程。特别是在处理复杂的业务逻辑或者需要进行大量数据更新时,存储过程能够提供更好的解决...

    Hibernate 存储过程的调用.doc

    首先,我们需要了解Hibernate存储过程调用的基本概念。存储过程可以封装复杂的数据库操作,如多条SQL语句、条件判断等,然后通过一个名称来执行。在Hibernate中,我们可以使用XML映射文件或者注解的方式来调用存储...

    Hibernate使用存储过程

    本文将深入探讨如何在Hibernate中使用存储过程。 首先,存储过程是在数据库层面预先编译好的一组SQL语句,它可以接受输入参数,处理数据,并返回结果。使用存储过程的优点包括性能提升、代码复用和安全性增强。在...

    spring hibernate执行存储过程的例子

    Spring和Hibernate是Java开发中常用的两个框架,它们提供了对存储过程的支持。本文将深入探讨如何在Spring和Hibernate中执行存储过程,并基于描述中的例子进行解析。 首先,让我们了解Spring如何执行存储过程。...

    hibernate query调用oracle存储过程

    在Hibernate中,调用存储过程通常通过Session对象的createNativeQuery()方法实现,这个方法用于创建原生SQL查询,可以方便地调用数据库的自定义SQL或者存储过程。以下是一个简单的示例,展示了如何调用一个不带参数...

    hibernate调用存储过程的方法调用

    Hibernate作为Java领域内广泛使用的对象关系映射(ORM)框架,提供了调用数据库存储过程的能力。本文将深入探讨如何使用Hibernate调用存储过程,并结合提供的资源文件——`proc.sql`、`hibernateProc.sql`和`...

    hibernate框架调用存储过程

    3. **调用存储过程**: 要在Hibernate中调用存储过程,你需要创建一个名为`StoredProcedureQuery`的实例,然后设置存储过程的名称和参数。例如,假设有一个名为`usp_GetEmployeeById`的存储过程,接收一个整数ID作为...

    hibernate调用存储过程具体方法

    hibernate本对数据库的操作有些不完美,有必要的时候可以调用存储过程来补足。

    Hibernate 调用存储过程

    ### Hibernate调用存储过程详解 #### 一、建立存储过程 在进行Hibernate调用存储过程之前,首先需要在数据库中创建存储过程。本例中创建了一个名为`getUserInfo`的简单存储过程,其功能是从`user`表中选择所有记录...

    hibernate 3.1 存储过程

    在Hibernate 3.1版本中,存储过程的支持是其重要特性之一。存储过程是预编译的SQL代码块,封装在数据库中,可以提高执行性能,降低网络传输数据量,并且提供了一种安全的方式来执行复杂的数据库操作。 在Java应用中...

    hibernate环境搭建已经对应存储过程调用

    本文将深入探讨如何搭建Hibernate环境并进行存储过程的调用。 首先,让我们了解什么是Hibernate。Hibernate是一个开源的ORM框架,它允许Java开发者将Java类与数据库表进行映射,通过对象的方式来操作数据库。它提供...

    Oracle自动生成hibernate实体(.java 和.hbm.xml文件)存储过程

    在这个案例中,`AutoCreateEntity.prc`是一个自定义的存储过程,它的设计目标是根据输入的表名(在这里是表A0)来生成对应的Hibernate实体类和映射文件。这可能涉及到解析表结构,包括字段名、数据类型等,然后将...

    使用hibernate调用oracle的存储过程

    在hibernate中调用oracle中的存储过程的详细代码。可以借鉴使用,帮助学习。

Global site tag (gtag.js) - Google Analytics