Spirytus

Spirytus 是一个用来粘合 ScalaSpring Boot 的小工具.


虽然 Java 一直在改进那个糟糕的语法, 但是对集合进行操作还是 Scala 的语法更舒服. 但是 Scala 来说, 如果拿来构建一个 Web 服务, 无论是 Play Framework, 还是 Akka Http, 用起来都没有那么方便. 这个时候 Spring Boot 就很吸引人了.

Spirytus 可以在纯粹的 Scala 项目中, 顺利的使用 Spring Boot 提供的各项方便的服务.

Example domain:

@Entity
class ExampleDomain {

  @Id
  var id: String = ""

  //Let's assume name is unique.
  @Column
  var name: String = ""

  @Column
  var city: String = ""

  @Column
  var age: Int = -1

  @Column
  var alive: Boolean = false
}

Example repository:

@Repository
trait ExampleRepo extends JpaRepository[ExampleDomain, String]{

  //You might still mark the return type as Java list as jpa does not recognise Scala list.
  def findByAlive(alive: Boolean): java.util.List[ExampleDomain]

  def findByCity(city: String): java.util.List[ExampleDomain]

  def findByAgeBetween(ageStart: Int, ageStop: Int): java.util.List[ExampleDomain]

  def findByName(name: String): java.util.Optional[ExampleDomain]

}

Example repository singleton:

@Service
@ObjectAnnotation(ExampleRepoSingleton)
object ExampleRepoSingleton extends RepoHelper[ExampleDomain, String, ExampleRepo] with ObjectAutoConfig{

  //All you need to do is to override the setRepo method with Autowired Repo.
  @Autowired
  override def setRepo(r: ExampleRepo): Unit = super.setRepo(r)

  //Still needs to write some boilerplate codes though, it doesn't come in that handy for now.
  //All default methods come with JPARepository had been implemented in RepoHelper.
  //So, say we don't need customised methods, the above two lines are all you need.
  def listByCity(city: String): List[ExampleDomain] = repo.findByCity(city).toScala

  def listAlive(alive: Boolean): List[ExampleDomain] = repo.findByAlive(alive).toScala

  def listInAgeRange(min: Int, max: Int): List[ExampleDomain] = repo.findByAgeBetween(min, max).toScala

  def fetchByName(name: String): Option[ExampleDomain] = repo.findByName(name).toScala

  def listAllNames(): List[String] = findAll.map(_.name)

  def listAllCities(): List[String] = findAll.map(_.city).distinct
}

class ExampleRepoSingleton

Example service:

@Service
@ObjectAnnotation(ExampleService)
object ExampleService extends ObjectAutoConfig{

  def chartByCity(): Map[String, Int] = {
    ExampleRepoSingleton.findAll.groupBy(_.city).map(z => (z._1, z._2.length))
  }

  def existsByName(name: String): Boolean = {
    ExampleRepoSingleton.fetchByName(name).fold(false)(_ => true)
  }

  def fetchCitiesByIds(ids: List[String]): List[String] = {
    ExampleRepoSingleton.findAllById(ids).map(_.city).distinct
  }

}

class ExampleService

Example service with autowired repository:

@Service
@ObjectAnnotation(ExampleService2)
object ExampleService2 extends ObjectAutoConfig with JavaCollectionMapper{

  var exampleRepo: ExampleRepo = _

  @Autowired
  def setRepo(r: ExampleRepo): Unit ={
    exampleRepo = r
  }

  def chartByCity(): Map[String, Int] = {
    exampleRepo.findAll().toScala.groupBy(_.city).map(z => (z._1, z._2.length))
  }

  def existsByName(name: String): Boolean = {
    exampleRepo.findByName(name).toScala.fold(false)(_ => true)
  }

  def fetchCitiesByIds(ids: List[String]): List[String] = {
    exampleRepo.findAllById(ids.toJava).toScala.map(_.city).distinct
  }
}

class ExampleService2

详细的还是去 Github 直接看代码吧. Spirytus.

Sirius

Sirius

沪ICP备2021021264号