有时候为了做些测试需要创建数据库及相关表,安装MySQL等轻量数据库虽然简单但还是有点麻烦?而且用于自己临时测试的数据库对象一般不会被多次使用,还是浪费?内存数据库结合ORM可以很好解决这个问题。
H2,Derby,HSQLDB 都是很好的内存数据库,大家可以根据自己的需要选择:
H2 | Derby | HSQLDB | MySQL | PostgreSQL | |
---|---|---|---|---|---|
Pure Java | Yes | Yes | Yes | No | No |
Memory Mode | Yes | Yes | Yes | No | No |
Encrypted Database | Yes | Yes | Yes | No | No |
ODBC Driver | Yes | No | No | Yes | Yes |
Fulltext Search | Yes | No | No | Yes | Yes |
Multi Version Concurrency | Yes | No | Yes | Yes | Yes |
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(SpringJUnit4ClassRunner.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());
}
}