有时候为了做些测试需要创建数据库及相关表,安装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已经对使用内存数据库提供很完美的支持:
配置类:
1 @Configuration 2 public class HibernateConfiguration { 3 @Autowired 4 private DataSource dataSource; 5 @Bean 6 public AnnotationSessionFactoryBean sessionFactoryBean() { 7 Properties props = new Properties(); 8 //配置H2方言 9 props.put("hibernate.dialect", H2Dialect.class.getName()); 10 props.put("hibernate.format_sql", "true"); 11 AnnotationSessionFactoryBean bean = new AnnotationSessionFactoryBean(); 12 bean.setAnnotatedClasses(new Class[]{Item.class, Order.class}); 13 bean.setHibernateProperties(props); 14 bean.setDataSource(this.dataSource); 15 bean.setSchemaUpdate(true); 16 return bean; 17 } 18 @Bean 19 public HibernateTransactionManager transactionManager() { 20 return new HibernateTransactionManager( sessionFactoryBean().getObject() ); 21 } 22 23 /** 24 * 设置内存数据库类型,可以更改为Derby,HSQL 25 * @return 26 */ 27 @Bean 28 public DataSource dataSource(){ 29 EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); 30 builder.setType(EmbeddedDatabaseType.H2); 31 return builder.build(); 32 }
然后我们可以写entity类及相关测试用例:
Order Entity类:
1 @Entity 2 @Table(name="T_ORDER") 3 public class Order { 4 5 @Id 6 @GeneratedValue(strategy=GenerationType.AUTO) 7 private Long id; 8 9 private String customer; 10 11 @OneToMany(cascade=CascadeType.ALL) 12 @JoinColumn(name="ORDER_ID") 13 private Collection<Item> items = new LinkedHashSet<Item>(); 14 /** 15 * @return the customer 16 */ 17 public String getCustomer() { 18 return customer; 19 } 20 /** 21 * @param customer the customer to set 22 */ 23 public void setCustomer(String customer) { 24 this.customer = customer; 25 } 26 /** 27 * @return the items 28 */ 29 public Collection<Item> getItems() { 30 return items; 31 } 32 /** 33 * @param items the items to set 34 */ 35 public void setItems(Collection<Item> items) { 36 this.items = items; 37 } 38 /** 39 * @return the id 40 */ 41 public Long getId() { 42 return id; 43 } 44 45 }
Item Entity类
1 @Entity 2 public class Item { 3 @Id 4 @GeneratedValue(strategy = GenerationType.AUTO) 5 private Long id; 6 @ManyToOne 7 private Order order; 8 private String product; 9 private double price; 10 private int quantity; 11 /** 12 * @return the order 13 */ 14 public Order getOrder() { 15 return order; 16 } 17 /** 18 * @return the product 19 */ 20 public String getProduct() { 21 return product; 22 } 23 /** 24 * @param product 25 * the product to set 26 */ 27 public void setProduct(String product) { 28 this.product = product; 29 } 30 /** 31 * @return the price 32 */ 33 public double getPrice() { 34 return price; 35 } 36 /** 37 * @param price 38 * the price to set 39 */ 40 public void setPrice(double price) { 41 this.price = price; 42 } 43 /** 44 * @return the quantity 45 */ 46 public int getQuantity() { 47 return quantity; 48 } 49 /** 50 * @param quantity 51 * the quantity to set 52 */ 53 public void setQuantity(int quantity) { 54 this.quantity = quantity; 55 } 56 /** 57 * @return the id 58 */ 59 public Long getId() { 60 return id; 61 } 62 }
Junit测试类
1 @ContextConfiguration 2 @RunWith(SpringJUnit4ClassRunner.class) 3 public class OrderPersistenceTests { 4 @Autowired 5 private SessionFactory sessionFactory; 6 @Test 7 @Transactional 8 public void testSaveOrderWithItems() throws Exception { 9 Session session = sessionFactory.getCurrentSession(); 10 Order order = new Order(); 11 order.getItems().add(new Item()); 12 session.save(order); 13 session.flush(); 14 assertNotNull(order.getId()); 15 } 16 @Test 17 @Transactional 18 public void testSaveAndGet() throws Exception { 19 Session session = sessionFactory.getCurrentSession(); 20 Order order = new Order(); 21 order.getItems().add(new Item()); 22 session.save(order); 23 session.flush(); 24 // Otherwise the query returns the existing order (and we didn't set the 25 // parent in the item)... 26 session.clear(); 27 Order other = (Order) session.get(Order.class, order.getId()); 28 assertEquals(1, other.getItems().size()); 29 assertEquals(other, other.getItems().iterator().next().getOrder()); 30 } 31 @Test 32 @Transactional 33 public void testSaveAndFind() throws Exception { 34 Session session = sessionFactory.getCurrentSession(); 35 Order order = new Order(); 36 Item item = new Item(); 37 item.setProduct("foo"); 38 order.getItems().add(item); 39 session.save(order); 40 session.flush(); 41 // Otherwise the query returns the existing order (and we didn't set the 42 // parent in the item)... 43 session.clear(); 44 Order other = (Order) session 45 .createQuery( "select o from Order o join o.items i where i.product=:product") 46 .setString("product", "foo").uniqueResult(); 47 assertEquals(1, other.getItems().size()); 48 assertEquals(other, other.getItems().iterator().next().getOrder()); 49 } 50 }