Spring-Hibernate:无法使用HibernateTemplate将对象数据保存到表中

时间:2018-07-28 18:45:03

标签: java spring hibernate

我遍历了整个stackoverflow,似乎找不到关于使用HibernateTemplate将创建的对象保存到数据库表(MySQL)的查询的答案。我正在使用Hibernate 5和Spring 5.0.7的最新版本。我对Spring-Hibernate还是很陌生,这里是我到目前为止编写的代码:

applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id = "dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/edureka?useLegacyDatetimeCode=false&amp;serverTimezone=Europe/Amsterdam&amp;useSSL=false" />
        <property name="username" value="admin" />
        <property name="password" value="password" />
    </bean>

    <bean id= "mySessionFactory" class = "org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="mappingResources">
            <list>
                <value>mobilephone.hbm.xml</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.show_sql">true</prop>

            </props>
        </property>

    </bean>

    <bean id = "dao" class = "co.module12.MobilePhoneDAO">
        <property name="sessionFactory" ref = "mySessionFactory"/>
    </bean>

</beans>

休眠映射文件(mobilephone.hbm.xml):

<!DOCTYPE hibernate-mapping PUBLIC
" - //Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping">

<hibernate-mapping>
    <class name = "co.module12.MobilePhone" table="mobiles">
        <id name="id">
            <generator class="increment"></generator>
        </id>
        <property name="manfacturer" />
        <property name="name" />
        <property name="price" />
        <property name="colour" />
    </class>
</hibernate-mapping>

POJO类(Java Bean)MobilePhone.java:

package co.module12;

/**
 *
 * @author NetBeans
 */
public class MobilePhone {
    private String manfacturer;
    private String colour;
    private Double price;
    private String name;
    private Integer id;


    public MobilePhone() {

    }

    public String getManfacturer() {
        return manfacturer;
    }

    public void setManfacturer(String manfacturer) {
        this.manfacturer = manfacturer;
    }

    public String getColour() {
        return colour;
    }

    public void setColour(String colour) {
        this.colour = colour;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }




}

MobilePhoneDAO.java:

package co.Module12;

import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate5.HibernateTemplate;
import org.springframework.transaction.annotation.Transactional;


/**
 *
 * @author NetBeans
 */
public class MobilePhoneDAO {
    HibernateTemplate template;
    SessionFactory factory;

    public void setSessionFactory(SessionFactory factory) {
       template = new HibernateTemplate(factory);
    }


    public void saveMobile(MobilePhone phone) {
        template.setCheckWriteOperations(false);
        template.save(phone);
        System.out.println(phone.getId());
        System.out.println(phone.getManfacturer());
        System.out.println(phone.getName());

    }

    public void updateMobile(MobilePhone phone) {
        template.update(phone);
    }

    public void deleteMobile(MobilePhone phone) {
        template.delete(phone);
    }

}

主文件:

package co.Module12;

import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 *
 * @author NetBeans
 */
public class Module12MainClass {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        MobilePhoneDAO dao = (MobilePhoneDAO)context.getBean("dao");

        /*Create Mobile Phone One to Map to mySQL database*/
        MobilePhone samsungOne = new MobilePhone();
        samsungOne.setColour("black");
        samsungOne.setManfacturer("Samsung");
        samsungOne.setName("Galaxy S9+");
        samsungOne.setPrice(55158.25);
        samsungOne.setId(1001);
        dao.saveMobile(samsungOne);

        /*Create Mobile Phone Two to Map to mySQL database*/
        MobilePhone lgPhone = new MobilePhone();
        lgPhone.setColour("gray");
        lgPhone.setManfacturer("LG");
        lgPhone.setName("G7");
        lgPhone.setPrice(58782.25);
        lgPhone.setId(1002);
        dao.saveMobile(lgPhone);

    }

}

1 个答案:

答案 0 :(得分:0)

尝试在您的DAO方法中添加Spring“ @Transactional”(https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/Transactional.html)批注。

可能发生的事情(尽管由于我的数据库当前没有合适的jar,目前无法测试),尽管您的代码确实执行了“保存”方法(您可能会确定是否没有错误,可以在您的DAO中放入调试器),默认情况下,Hibernate可能会设置为执行“自动刷新”功能。这意味着Hibernate决定何时将记录刷新到数据库,但是由于没有事务,因此Hibernate不会费心调用此方法。放置“ @Transactional”批注会将save调用绑定到同时绑定了Hibernate Session的Spring事务,这意味着当事务关闭时,会通知Session关闭,并且应该刷新。

更新:这是我使用H2数据源运行示例股票的错误:

BUG org.springframework.orm.hibernate5.HibernateTemplate - Could not retrieve pre-bound Hibernate session
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
    at org.springframework.orm.hibernate5.SpringSessionContext.currentSession(SpringSessionContext.java:133)
    at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:699)
    at org.springframework.orm.hibernate5.HibernateTemplate.doExecute(HibernateTemplate.java:344)
    at org.springframework.orm.hibernate5.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:326)
    at org.springframework.orm.hibernate5.HibernateTemplate.save(HibernateTemplate.java:640)
    at co.module12.MobilePhoneDAO.saveMobile(MobilePhoneDAO.java:23)
    at co.module12.Module12MainClass.main(Module12MainClass.java:23)

但是,您需要对您的Spring上下文文件进行更新,以使事务完全起作用。

<tx:annotation-driven transaction-manager="txManager"/><!-- a PlatformTransactionManager is still required -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- (this dependency is defined somewhere else) -->
        <property name="dataSource" ref="dataSource"/>
    </bean>

这取自以下示例: https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html#transaction-declarative-annotations

我得到了可以在H2数据源上运行的代码,MySQL不应有太大区别。但是,请注意三点:

  1. 检查您的导入-它必须是 Spring 事务性的,而不是javax!
  2. 价格是货币-由于精度很重要,因此您应该映射到BigDecimal而不是Double。
  3. 您应该依靠save()调用来生成ID-请勿提前生成ID。