【问题标题】:Saving an object via getSessionFactory().getCurrentSession().save(item)通过 getSessionFactory().getCurrentSession().save(item) 保存对象
【发布时间】:2026-01-09 03:35:01
【问题描述】:

即使该操作似乎非常频繁地使用,我也没有发现我的代码中的问题出在哪里。 在 DAO 课程中,我有:

    public class ItemDaoImpl extends HibernateDaoSupport implements ItemDao {
    @Transactional
    public void addItem(Item item){
        getSessionFactory().getCurrentSession().save(item);
    }

    @Transactional(readOnly = true)
    public List<Item> findAllItem(){
        return getSessionFactory().getCurrentSession().createQuery("from Item").list();
    }}

findAllItem() 效果很好,而 addItem() 则不行。当我单击调用 addItem() 的按钮时,会引发以下错误:

java.lang.ClassCastException: com.z.item.model.Item 不能转换为 java.util.Map javax.faces.el.E​​valuationException: java.lang.ClassCastException: com.z.item.model.Item 不能转换为 java.util.Map 在 javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:98) 在 com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:98) 在 javax.faces.component.UICommand.broadcast(UICommand.java:311) . . .

但我没有指定任何地图,因为我到处都使用对象“项目”。传递给 addItem() 的项目对象也是正确的。为什么会抛出这个异常?

这是我的配置方式:

<hibernate-mapping>
    <class entity-name="com.z.item.model.Item"
        table="item">

        <id name="id" type="long">
            <column name="ID" />
            <generator class="identity" />
        </id>
        <property name="name" type="string">
            <column name="ITEMNAME" length="45" not-null="true" />
        </property>
        <property name="amount" type="int">
            <column name="AMOUNT" not-null="true" />
        </property>
        <property name="price" type="java.math.BigDecimal">
            <column name="PRICE" length="10" not-null="true" />
        </property>
    </class>
</hibernate-mapping>


    <tx:annotation-driven  transaction-manager="transactionManager"/>
    <bean id="transactionManager"
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
    </bean>
    <bean id="itemDao"
         class="com.z.item.dao.impl.ItemDaoImpl" >
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>



   <bean id="sessionFactory" 
     class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource">
      <ref bean="dataSource"/>
    </property>


    <property name="hibernateProperties">
       <props>
         <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
         <prop key="hibernate.show_sql">true</prop>
       </props>
    </property>
    <property name="mappingResources">
    <list>
          <value>com/z/item/hibernate/Item.hbm.xml</value>
    </list>
    </property>
   </bean>

【问题讨论】:

  • 这里有问题吗?还是我应该解决所有显示的问题..

标签: spring hibernate hibernate-mapping hsqldb spring-transactions


【解决方案1】:

我认为这不是 Hibernate 引起的问题。当您单击按钮并在到达addItem() 之前,该问题可能已经发生。很可能是数据映射问题(我假设您在单击按钮时首先将一些数据映射到 Item)。尝试在调用addItem() 之前打印出项目,即使不调用addItem(),您也会看到上述异常。

【讨论】:

  • 没错,我不确定这是否是 Hibernate 问题。但是如果映射做错了,那么我的 findAllItem() 不应该工作吗?当我点击添加按钮时,我已经可以看到 findAllItem() 从数据库中正确选择的项目列表。我在调试器上检查了传递给 addItem() 的项目是正确的。我什至做了一个实验,并在 addItem() 中创建了一个全新的 Item 对象并尝试保存它,但 ClassCastException 仍然存在。
  • 您从 findAllItem() 得到结果,这意味着您的项目实体映射是正确的。从您的日志javax.faces.el.EvaluationException 中,您可以看到当您尝试将数据从 UI 映射到 Item 时发生了问题,甚至没有到达 addItem()
【解决方案2】:

对于@Transactional 注解,您需要使用false 指定写入(保存和删除)DAO 方法,使用true 指定读取(获取和加载)方法。

@Transactional 只是为方法或类添加某些元数据,关于事务是只读还是写入或是否需要新事务等。有关@Transactional 注释的更多信息,请阅读here .

@Transactional(readOnly=false)
public void addItem(Item item){
    getSessionFactory().getCurrentSession().save(item);
}

@Transactional(readOnly=true)
public List<Item> findAllItem(){
    return getSessionFactory().getCurrentSession().createQuery("from Item").list();
}

此外,您应该更改映射以使用&lt;class name="Item" table="item"&gt; 而不是&lt;class entity-name="com.z.item.model.Item" table="item"&gt;。此映射允许您以 dom4j 树的形式访问数据,或者以属性名称/值对的图形或 java 映射的形式访问数据。仅指定没有任何关联类的 XML 映射。属性名称是可以在 HQL 查询中引用的纯逻辑结构。请参阅the hibernate doco 了解更多信息。

entity-name(可选 - 默认为类名):Hibernate3 允许 一个类被多次映射,可能映射到不同的表。 它还允许由 Maps 或 XML 表示的实体映射 Java级别。在这些情况下,您应该提供一个明确的 实体的任意名称。请参阅第 4.4 节“动态模型”和 第 18 章,XML 映射了解更多信息。

【讨论】:

  • 我遵循了你的想法:首先我为 addItem() 添加了@Transactional(readOnly = false)。但是 ClassCastException 仍然被抛出。然后我尝试了您的另一个想法并删除了 addItem() 上的此注释,但这次我又遇到了另一个错误:org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
  • 我已经编辑了我的答案,以反映您应该尝试的映射变化。这应该处理案例问题。对不起,我错过了。我还假设这是一个简单的对象关系?你不想要任何特殊的映射?对于“绑定到线程”问题。这是独立的,与您创建休眠会话的方式有关。见:docs.jboss.org/hibernate/orm/4.2/devguide/en-US/html/…
  • 我认为我们正朝着正确的方向前进。在我查看的教程中,它是名称,但我将其更改为实体名称。我更改了它,因为它正在修复另一个错误:严重:上下文初始化失败 org.springframework.beans.factory.BeanCreationException:在 ServletContext 资源 [/WEB-INF/classes/config/spring/beans 中定义名称为“sessionFactory”的 bean 创建错误/HibernateSessionFactory.xml]: init 方法调用失败;嵌套异常是 org.hibernate.HibernateException: Unable to instantiate default tuplizer [org.hibernate.tuple.entity.PojoEntityTuplizer]...
  • 完美。现在您只需要解决这些其他事情并查看您的会话事务管理。对于上述异常,请查看您如何注入会话以及如何定义它。
  • 您所拥有的是一系列错误或不同的问题。也许尝试将一个问题或相关问题保留在一个线程中。如有必要,请打开另一个问题。
【解决方案3】:

实际上,我做了几件事来使这段代码正常工作。

  1. 我已将我的 dao 方法更改为:

    @Transactional(readOnly=false) public void addItem(Item item){}

  2. 我已经从 2.2 修改了 pom.xml 中的 cglib 版本。到 2.1。

  3. 我已将配置更改为:

    <class name="pl.outbox.item.model.Item" table="item">
    <id name="id" type="int">
        <column name="ID" />
        <generator class="increment"/>
    </id>
    

【讨论】:

    最近更新 更多