【问题标题】:Spring + Hibernate: Initializing database with JUnit doesn't workSpring + Hibernate:使用 JUnit 初始化数据库不起作用
【发布时间】:2011-12-28 17:21:02
【问题描述】:

我有一个带有一个 Vehicle 表的简单数据库(使用 MySQL):

create table vehicle (
    vehicle_no varchar(10) not null,
    color varchar(10),
    wheel int,
    seat int,
    primary key (vehicle_no)
) engine = InnoDB;

在 Java 中,我有应该查询所有车辆的 DAO 对象(省略了其他 DAO 方法)。此 DAO 应加入现​​有事务或根据需要创建新事务:

@Transactional(propagation=Propagation.REQUIRED, readOnly=false)
public class HibernateVehicleDao implements VehicleDao {

    private SessionFactory sessionFactory;
    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    @Override
    public List<Vehicle> findAll() {
        return currentSession().createQuery("from Vehicle").list();
    }
}

现在,我已经为 DAO 编写了 JUnit 测试 (JUnit4)。在运行测试方法之前,它应该将 10 辆车插入数据库,运行后它应该删除所有车辆。我已经单独测试了这种行为与 Spring 的 JDBC 并且一切正常,所以应该没有问题。

@ContextConfiguration(locations = "/sk/xorty/dataaccess/dataaccess-beans.xml")
public class HibernateVehicleDaoTest extends AbstractTransactionalJUnit4SpringContextTests {

    private static final int COUNT = 10;

    @Autowired
    @Qualifier("hibernateVehicleDao")
    private VehicleDao dao;

    @Before
    public void setUp() {
        String insert = 
                "INSERT INTO VEHICLE (VEHICLE_NO, COLOR, WHEEL, SEAT) VALUES (?, ?, ?, ?)";
        List<Object[]> argsList = new ArrayList<>();
        for (int i = 0; i < COUNT; i++) {
            argsList.add(VehicleUtil.nextVehicleArgs());
        }
        simpleJdbcTemplate.batchUpdate(insert, argsList);
    }

    @After
    public void tearDown() {
        simpleJdbcTemplate.update("DELETE FROM VEHICLE", (Object[]) null);
    }

    @Test
    public void testFindAll() {
        assertEquals (COUNT, dao.findAll().size());
    }
}

一切都加载了,所以我怀疑配置是正确的,并且依赖项被正确注入。

问题是,该测试失败,因为数据库是空的(没有车辆)。另一方面,当我手动插入它们时,它们永远不会被删除。

请尝试注意使用事务注释,我对此很陌生,我认为我可能在某处犯了错误。

这是我的 bean 配置文件,如果有帮助的话:

<?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"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <context:annotation-config />
    <tx:annotation-driven />

    <!-- shared data source -->
    <bean id="dataSource" 
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" 
            value="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" />
        <property name="url" value="jdbc:mysql://localhost/vehicles" />
        <property name="username" value="root" />
        <property name="password" value="" />
    </bean>

    <!-- JDBC transaction manager -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!-- hibernate session factory -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="annotatedClasses" >
            <list>
                <value>sk.xorty.dataaccess.Vehicle</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property> 
    </bean>

    <bean id="hibernateVehicleDao" class="sk.xorty.dataaccess.HibernateVehicleDao" />

</beans>

编辑:请求的车辆实体代码:

@Entity
@Table(name="vehicle")
public class Vehicle implements Serializable {

    @Id
    @Column(name="VEHICLE_NO", nullable=false, length=10)
    private String vehicleNo;
    private String color;
    private int wheel;
    private int seat;

    public Vehicle() {}

    public Vehicle(String vehicleNo, String color, int wheel, int seat) {
        this.vehicleNo = vehicleNo;
        this.color = color;
        this.wheel = wheel;
        this.seat = seat;
    }

    public String getVehicleNo() {
        return vehicleNo;
    }

    public void setVehicleNo(String vehicleNo) {
        this.vehicleNo = vehicleNo;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getWheel() {
        return wheel;
    }

    public void setWheel(int wheel) {
        this.wheel = wheel;
    }

    public int getSeat() {
        return seat;
    }

    public void setSeat(int seat) {
        this.seat = seat;
    }

    @Override
    public String toString() {
        return "Vehicle [vehicleNo=" + vehicleNo + ", color=" + color
                + ", wheel=" + wheel + ", seat=" + seat + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((color == null) ? 0 : color.hashCode());
        result = prime * result + seat;
        result = prime * result
                + ((vehicleNo == null) ? 0 : vehicleNo.hashCode());
        result = prime * result + wheel;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Vehicle other = (Vehicle) obj;
        if (color == null) {
            if (other.color != null)
                return false;
        } else if (!color.equals(other.color))
            return false;
        if (seat != other.seat)
            return false;
        if (vehicleNo == null) {
            if (other.vehicleNo != null)
                return false;
        } else if (!vehicleNo.equals(other.vehicleNo))
            return false;
        if (wheel != other.wheel)
            return false;
        return true;
    }

}

【问题讨论】:

  • 你能发布 Vehicle 实体吗?
  • @kmb385 当然,请参阅编辑
  • 你在哪里实例化 simpleJdbcTemplate?
  • 它继承自 AbstractTransactionalJUnit4SpringContextTests,它是在 Spring 将 dataSource(我在 beans.xml 中有一个)自动装配到这个父类时创建的。
  • 如果您在 beans.xml 中定义 JDBC 模板,我认为您可能需要在当前配置文件中导入该配置文件。

标签: java hibernate spring transactions junit


【解决方案1】:

我不确定这是否重要,但以下方法中的大小写不正确:

@Override
public List<Vehicle> findAll() {
    return currentSession().createQuery("from Vehicle").list();
}

表名在“vehicle”中以小写v开头,而该方法使用大写“V”。

我从文档中读到的另一件有趣的事情:

simpleJdbcTemplate:用于查询确认状态。例如, 您可能会在测试创建的应用程序代码之前和之后进行查询 一个对象并使用 ORM 工具将其持久化,以验证数据 出现在数据库中。 (Spring 将确保查询在 同一事务的范围。)您需要告诉您的 ORM 例如,“刷新”其更改以使其正常工作的工具 在 Hibernate 的 Session 接口上使用 flush() 方法。

在执行查询之前尝试刷新会话。

【讨论】:

  • HQL 使用实体的名称而不是 SQL 表 afaik。只是为了清楚起见,我用小写字母试了一下,结果是 org.hibernate.hql.ast.QuerySyntaxException
  • 在hibernate dao中刷新也没有帮助:(
猜你喜欢
  • 2012-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-01
  • 2017-12-18
  • 2015-12-26
  • 2018-06-09
相关资源
最近更新 更多