【问题标题】:scalike-jdbc - How to specify column alias in query?scalike-jdbc - 如何在查询中指定列别名?
【发布时间】:2017-10-15 03:00:04
【问题描述】:

我定义了一个对象来帮助将结果集转换为 POJO。

  // an object, that help to map from query result to POJO,
  object Dummy extends SQLSyntaxSupport[Dummy] {
    override val tableName = "dummy"
    def apply(rs: WrappedResultSet) = new Dummy(
      rs.long("id"), rs.stringOpt("name"), rs.intOpt("size"), rs.jodaDateTime("create_date"))
  }

然后下面的代码尝试从表中查询,

  /*** query - with condition - start ***/
  // use paste mode (:paste) on the Scala REPL
  val d = Dummy.syntax("d")
  val name = "hello"
  val helloDummyOpt: Option[Dummy] = withSQL {
    select.from(Dummy as d).where.eq(d.name, name).limit(1)
  }.map(rs => Dummy(rs)).single.apply()

  printf("hello dummy:\t%s\n", if(helloDummyOpt.isDefined) helloDummyOpt.get else "")
  /*** query - with condition - end ***/

从控制台,我可以看到生成的sql是:

select d.id as i_on_d, d.name as n_on_d, d.size as s_on_d, d.create_date as cd_on_d
from dummy d where d.name = 'hello' limit 1;

为了使转换工作,需要将生成的sql中的列别名更改为表中的原始名称,例如name而不是n_on_d

那么,怎么做呢,谢谢。


@更新

完整代码在这里:

package eric.scalikejdbc

import scalikejdbc._
import org.postgresql.Driver._
import org.joda.time._

/**
 * scalikejdbc hello.
 * @author eric
 * @date Jul 6, 2016 23:14:07 PM
 */
object ScalikeJdbcHello extends App {
  Class.forName("org.postgresql.Driver")
  ConnectionPool.singleton("jdbc:postgresql://localhost:5432/sportslight", "postgres", "123456")

  implicit val session = AutoSession

  /*** query - parse as List of Map - start ***/
  // find rows, with limit 10000,
  val entities: List[Map[String, Any]] = sql"select * from dummy limit 10000".map(_.toMap).list.apply()
  printf("dummy count: %d\n", entities.size)
  /*** query - parse as List of Map - end ***/

  /*** query - parse as POJO - start ***/
  // define a POJO class,
  case class Dummy(id: Long, name: Option[String], size: Option[Int], createDate: DateTime)

  // an object, that help to map from query result to POJO,
  object Dummy extends SQLSyntaxSupport[Dummy] {
    override val tableName = "dummy"
    def apply(rs: WrappedResultSet) = new Dummy(
      rs.long("id"), rs.stringOpt("name"), rs.intOpt("size"), rs.jodaDateTime("create_date"))
  }

  // find top 10 rows,
  val dummyList: List[Dummy] = sql"select * from dummy limit 10".map(rs => Dummy(rs)).list.apply()

  var i = 0;
  printf("dummy top rows:\n")
  for (d <- dummyList) {
    printf("\t[%d] %s\n", i, d)
    i = i + 1
  }
  /*** query - parse as POJO - end ***/

  /*** query - with condition - start ***/
  // TODO ... specify column name in result,
  val d = Dummy.syntax("d")
  val name = "hello"
  val helloDummyOpt: Option[Dummy] = withSQL {
    select.from(Dummy as d).where.eq(d.name, name).limit(1)
  }.map(rs => Dummy(rs)).single.apply()

  printf("hello dummy:\t%s\n", if(helloDummyOpt.isDefined) helloDummyOpt.get else "")
  /*** query - with condition - end ***/
}

这是为postgresql创建表和初始化数据的sql:

/* table - dummy */
-- drop table
drop table if exists dummy;

-- create table
create table dummy (
    id serial8,
    name varchar(50) not null,
    size int not null,
    create_date timestamptz,
    primary key (id)
);

-- init data - dummy
insert into dummy(name, size, create_date) values
('test', 1, now()),
('hello', 1, now());

【问题讨论】:

  • 为什么要担心别名?当您使用 Dummy 对象时,您永远不会看到在代码中使用它们。
  • @Rumoku 我更新了问题,提供了更多信息。

标签: postgresql scala jdbc scalikejdbc


【解决方案1】:

select.from 调用 alias.result.*。调用 alias.* 只是按原样返回列名。

scala> select(a.*).from(Article as a).toSQL.statement
res7: String = select a.id, a.title, a.body, a.created_at, a.updated_at from articles a

scala> select(a.result.*).from(Article as a).toSQL.statement
res8: String = select a.id as i_on_a, a.title as t_on_a, a.body as b_on_a, a.created_at as ca_on_a, a.updated_at as ua_on_a from articles a

scala> select.from(Article as a).toSQL.statement
res9: String = select a.id as i_on_a, a.title as t_on_a, a.body as b_on_a, a.created_at as ca_on_a, a.updated_at as ua_on_a from articles a

【讨论】:

  • 第一个示例修复了代码,如下:val helloDummyOpt: Option[Dummy] = withSQL { select(d.*).from(Dummy as d).where.eq(d.name, name).limit(1) }.map(rs =&gt; Dummy(rs)).single.apply(),但可能从http://scalikejdbc.org/First example的代码示例最终查询以val alice:开头,也应该类似地调整方式。
【解决方案2】:

您使用的是一半类型安全的 DSL,一半是默认 API。你应该选择一个并继续它。

对于 TypeSafe DSL,您不应使用自定义的 SqlSyntaxSupport 实现。

您应该能够使用在 sql 查询中定义的 d Dummy 对象,而不是 .map(rs =&gt; Dummy(rs))

  val d = Dummy.syntax("d")

  val helloDummyOpt: Option[Dummy] = withSQL {
    select.from(Dummy as d).where.eq(d.name, name).limit(1)
  }.single.apply()

查看 TypeSafe DSL 部分以获取更多示例:http://scalikejdbc.org

如果你想接收那些自动生成的名字,你应该通过对象 d 引用它们:

 val d = Dummy.syntax("d")
d.id // = i_on_d
d.name // = n_on_d
d.create_date // = cd_on_d

【讨论】:

  • 谢谢,但实际上代码是从scalikejdbc.orgFirst example 部分模仿的。我试过你的代码,上面写着Error:(51, 17) No extractor is specified. You have forgotten call #map(...) before #apply(). }.single.apply()。我已经添加了完整的代码来质疑你能不能在此基础上进行修改,使其可以运行?
猜你喜欢
  • 2012-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-12
  • 1970-01-01
相关资源
最近更新 更多