Scala 用函数式编程的方法调用db4o

db4o 是一个开源的纯面向对象数据库,同时支持Java和dotNet。使用db4o可以用更加面向对象的方式存储数据,比JPA等通过ORM来协调数据库和对象之间的方案来的更为自然。

那么用函数式编程的眼光来看,应该如何使用db4o这样的库呢?首先我们来看一个db4o的包装类

xml 代码
  1. package plan.util;   
  2.   
  3. import com.db4o.query.Query   
  4.   
  5. abstract class LazyQuery[QInterface, T]  (val criteria: List[Query=>Query]) extends Iterable[T] {   
  6.      
  7.   def elements = {   
  8.     val init: Query = null  
  9.     // 等价于 criteria leftFold init ( query=>query(query=>query) )
  10.     val query = (criteria :\ init)((f, q)=>f(q))   
  11.     Db4oUtil.iterate[T](query)   
  12.   }   
  13.      
  14.   def factory: List[Query=>Query]=>QInterface   
  15.      
  16.   def constrain(c: Query=>Query) = factory(c :: criteria)   
  17. }   
  18.   
  19. object Db4oUtil {   
  20.   def iterate[T](q: Query) = {   
  21.     val set = q.execute()   
  22.     new Iterator[T] {   
  23.       def hasNext = set.hasNext   
  24.       def next = set.next.asInstanceOf[T]   
  25.     }   
  26.   }   
  27. }   

看一个实际的例子,People和AutoInfo是POJO,People有一个指向AutoInfo的List。通过继承LazyQuery的Peoples可以很容易做一些查询、filter、以及复杂的操作。由于是functional的(所有的constrain都是query=>query的函数),所以各个查询条件可以互相组合,非常方便

xml 代码
  1. package plan;   
  2.   
  3. import plan.util.Db4oUtil   
  4. import plan.util.LazyQuery   
  5.   
  6. import com.db4o.Db4o   
  7. import com.db4o.ObjectContainer   
  8. import com.db4o.query.Query   
  9.   
  10. import scala.reflect.BeanProperty   
  11.   
  12. class People {   
  13.   @BeanProperty   
  14.   var id: int =_  
  15.   
  16.   @BeanProperty   
  17.   var name: String =_  
  18.   
  19.   @BeanProperty   
  20.   var address: String =_  
  21.   
  22.   @BeanProperty   
  23.   var autoInfoList: java.util.List = new java.util.ArrayList   
  24.      
  25.   def addAutoInfo(autoInfo: AutoInfo) = {   
  26.     autoInfoList.add(autoInfo)   
  27.   }   
  28.      
  29.   def autoCount = autoInfoList size   
  30. }   
  31.   
  32. class AutoInfo {   
  33.   @BeanProperty   
  34.   var id: int = _     
  35.   
  36.   @BeanProperty   
  37.   var name: String = _     
  38.   
  39.   @BeanProperty   
  40.   var owner: People  = _  
  41. }   
  42.   
  43. class Peoples(criteria: List[Query=>Query]) extends LazyQuery[Peoples, People](criteria) {   
  44.      
  45.   override def factory = new Peoples(_)   
  46.      
  47.   def withAuto() = {   
  48.     constrain { q=>  
  49.         q.descend("autoInfoList")   
  50.         q   
  51.     }   
  52.   }   
  53.        
  54.   def totalAuto = (this.map(_.autoCount) :\ 0)( (f,g) => f + g )   
  55. }   
  56.   
  57. object Db4oTest {   
  58.   var db: ObjectContainer = _  
  59.   def initData() = {   
  60.     val peo = new People   
  61.     peo.address = "北京"  
  62.     peo.name = "Chris"  
  63.     var auInfo = new AutoInfo   
  64.     auInfo.name = "雪铁龙"  
  65.     auInfo.owner = peo  
  66.     peo.addAutoInfo(auInfo)         
  67.     db.set(peo)   
  68.        
  69.     val peo1 = new People   
  70.     peo1.address = "上海"  
  71.     peo1.name = "Louis"  
  72.     db.set(peo1)   
  73.   }   
  74.   private def query(klass: Class) = {   
  75.     val q = db.query()   
  76.     q.constrain(klass)   
  77.     q   
  78.   }   
  79.   def main(args: Array[String]) = {   
  80.     db = Db4o.openFile("auto.yap")   
  81.     try {   
  82.       //initData       
  83.       val peoples = new Peoples(List(q=>query(classOf[People])))   
  84.   
  85.       // get total car all people have   
  86.       println( peoples.totalAuto )   
  87.   
  88.       // lazy query all people   
  89.       for (peo <- peoples.elements) {   
  90.         println( peo.name )    
  91.       }   
  92.       // lazy query all people with autoinfo   
  93.       for (peo <- peoples.withAuto.elements) {   
  94.         println( peo.name )    
  95.       }   
  96.     }finally{   
  97.       db.close();   
  98.     }   
  99.   }   
  100. }   

 

你可能感兴趣的:(编程,xml,scala,jpa,F#)