有时候为了做些测试需要创建数据库及相关表,安装MySQL等轻量数据库虽然简单但还是有点麻烦?而且用于自己临时测试的数据库对象一般不会被多次使用,还是浪费?内存数据库结合ORM可以很好解决这个问题。


H2,Derby,HSQLDB 都是很好的内存数据库,大家可以根据自己的需要选择:


H2DerbyHSQLDBMySQLPostgreSQL
Pure JavaYesYesYesNoNo
Memory ModeYesYesYesNoNo
Encrypted DatabaseYesYesYesNoNo
ODBC DriverYesNoNoYesYes
Fulltext SearchYesNoNoYesYes
Multi Version ConcurrencyYesNoYesYesYes
Footprint (jar/dll size)~1 MB~2 MB~1 MB~4 MB~6 MB

Spring已经对使用内存数据库提供很完美的支持:

配置类:

@Configuration
public class HibernateConfiguration {
    @Autowired
    private DataSource dataSource;
    @Bean
    public AnnotationSessionFactoryBean sessionFactoryBean() {
        Properties props = new Properties();
        //配置H2方言
        props.put("hibernate.dialect", H2Dialect.class.getName());
        props.put("hibernate.format_sql", "true");
        AnnotationSessionFactoryBean bean = new AnnotationSessionFactoryBean();
        bean.setAnnotatedClasses(new Class[]{Item.class, Order.class});
        bean.setHibernateProperties(props);
        bean.setDataSource(this.dataSource);
        bean.setSchemaUpdate(true);
        return bean;
    }
    @Bean
    public HibernateTransactionManager transactionManager() {
        return new HibernateTransactionManager( sessionFactoryBean().getObject() );
    }
                                                   
    /**
     * 设置内存数据库类型,可以更改为Derby,HSQL
     * @return
     */
    @Bean
    public DataSource dataSource(){
        EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
        builder.setType(EmbeddedDatabaseType.H2);
        return builder.build();
    }
}

然后我们可以写entity类及相关测试用例:

Order Entity类:

@Entity
@Table(name="T_ORDER")
public class Order {
                                                 
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
                                                 
    private String customer;
                                                 
    @OneToMany(cascade=CascadeType.ALL)
    @JoinColumn(name="ORDER_ID")
    private Collection<Item> items = new LinkedHashSet<Item>();
    /**
     * @return the customer
     */
    public String getCustomer() {
        return customer;
    }
    /**
     * @param customer the customer to set
     */
    public void setCustomer(String customer) {
        this.customer = customer;
    }
    /**
     * @return the items
     */
    public Collection<Item> getItems() {
        return items;
    }
    /**
     * @param items the items to set
     */
    public void setItems(Collection<Item> items) {
        this.items = items;
    }
    /**
     * @return the id
     */
    public Long getId() {
        return id;
    }
                                                 
}

Item Entity类

@Entity
public class Item {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @ManyToOne
    private Order order;
    private String product;
    private double price;
    private int quantity;
    /**
     * @return the order
     */
    public Order getOrder() {
        return order;
    }
    /**
     * @return the product
     */
    public String getProduct() {
        return product;
    }
    /**
     * @param product
     *            the product to set
     */
    public void setProduct(String product) {
        this.product = product;
    }
    /**
     * @return the price
     */
    public double getPrice() {
        return price;
    }
    /**
     * @param price
     *            the price to set
     */
    public void setPrice(double price) {
        this.price = price;
    }
    /**
     * @return the quantity
     */
    public int getQuantity() {
        return quantity;
    }
    /**
     * @param quantity
     *            the quantity to set
     */
    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }
    /**
     * @return the id
     */
    public Long getId() {
        return id;
    }
}

Junit测试类

@ContextConfiguration
@RunWith(SpringJUnit4Cla***unner.class)
public class OrderPersistenceTests {
    @Autowired
    private SessionFactory sessionFactory;
    @Test
    @Transactional
    public void testSaveOrderWithItems() throws Exception {
        Session session = sessionFactory.getCurrentSession();
        Order order = new Order();
        order.getItems().add(new Item());
        session.save(order);
        session.flush();
        assertNotNull(order.getId());
    }
    @Test
    @Transactional
    public void testSaveAndGet() throws Exception {
        Session session = sessionFactory.getCurrentSession();
        Order order = new Order();
        order.getItems().add(new Item());
        session.save(order);
        session.flush();
        // Otherwise the query returns the existing order (and we didn't set the
        // parent in the item)...
        session.clear();
        Order other = (Order) session.get(Order.class, order.getId());
        assertEquals(1, other.getItems().size());
        assertEquals(other, other.getItems().iterator().next().getOrder());
    }
    @Test
    @Transactional
    public void testSaveAndFind() throws Exception {
        Session session = sessionFactory.getCurrentSession();
        Order order = new Order();
        Item item = new Item();
        item.setProduct("foo");
        order.getItems().add(item);
        session.save(order);
        session.flush();
        // Otherwise the query returns the existing order (and we didn't set the
        // parent in the item)...
        session.clear();
        Order other = (Order) session
                .createQuery( "select o from Order o join o.items i where i.product=:product")
                .setString("product", "foo").uniqueResult();
        assertEquals(1, other.getItems().size());
        assertEquals(other, other.getItems().iterator().next().getOrder());
    }
}

整个项目已经打包,大家可以详阅,也可以直接参考Spring的示例项目,基本一样。