2013-12-24 2 views
1

Я изо всех сил вставив запись в PostgreSQL:Я изо всех сил получить обратно идентификатор из PostgreSQL в Play

val res = DB.withConnection { 
     implicit con => 
      SQL(
      """INSERT INTO 
       my_table(id, user_id, file_name, added_at) 
       VALUES(DEFAULT, {userId}, {fileName}, {currentTime}) 
       RETURNING id 
      """) 
      .on("userId" -> 1, "fileName" -> "fileName1", "currentTime" -> new java.sql.Timestamp(DateTime.now.getMillis)) 
      .executeInsert() 
     } 

Ok(toJson(JsObject(Seq("res" -> JsString(res.toString))))) 

Это делает вставить значение (которое можно увидеть через pdAdmin), но она возвращает ошибку в конечном итоге ERROR: syntax error at or near "RETURNING".

Если удалить RETURNING id то ошибка становится TypeDoesNotMatch(Cannot convert requestBody4050249427671619471asTemporaryFile :class java.lang.String to Long for column ColumnName(my_table.file_name,Some(file_name)))]]

Когда я отрезал id и DEFAULT ошибка остается прежней.

my_table определено в

CREATE TABLE my_table 
(
    file_name character(255), 
    user_id integer, 
    added_at timestamp without time zone, 
    id serial NOT NULL, 
    CONSTRAINT my_table_pk PRIMARY KEY (id), 
    CONSTRAINT scan_fk FOREIGN ..... 
) 

Почему? Что это имеет отношение к file_name в любом случае?

+0

Обычно, если вы используете 'RETURNING', вам нужно выдать его больше как запрос' SELECT'; например в обычной Java вы должны использовать 'execute' not' executeUpdate', чтобы он получал ResultSet. Я подозреваю, что здесь происходит, что PgJDBC или Play добавляет к вам свое предложение 'RETURNING' для вас неявно. Проверьте журнал ошибок сервера * для получения подробностей - есть ли в вашем запросе два предложения «ВОЗВРАТ»? –

+0

где «журнал ошибок сервера»? –

+1

Сервер PostgreSQL создает журнал. Google расскажет вам об этом. По умолчанию, когда любой клиент запускает оператор, который вызывает ошибку, сервер регистрирует сообщение об ошибке. Просмотрите этот журнал ошибок, и вы увидите сообщение об ошибке и заявление, которое вызвало ошибку, что может быть очень информативным. –

ответ

1

Учитывая эту таблицу:

CREATE TABLE my_table 
(
    file_name character(255), 
    user_id integer, 
    added_at timestamp without time zone, 
    id serial NOT NULL, 
    CONSTRAINT my_table_pk PRIMARY KEY (id) 
); 

Вы можете вставить запись и получить его идентификатор, как это:

package dao 

import anorm._ 
import anorm.SqlParser._ 
import play.api.db.DB 
import play.api.Logger 
import play.api.Play.current 

object MyDAO { 

    def insert(fileName: String, userId: Int): Int = { 
    val sql = SQL(
     """ 
     insert into my_table(file_name, user_id, added_at) 
     values ({fileName}, {userId}, CURRENT_TIMESTAMP) 
     returning id 
     """) 
     .on(
     "fileName" -> fileName, 
     "userId" -> userId) 
    DB.withConnection { implicit c => 
     val id = sql.as(scalar[Int].single) 
     Logger.info(s"Inserted '$fileName' with id '$id'.") 
     id 
    } 
    } 

} 

И проверить это следующим образом:

import org.junit.runner._ 
import org.specs2.mutable._ 
import org.specs2.runner._ 
import play.api.test._ 
import play.api.test.Helpers._ 
import dao.MyDAO 

@RunWith(classOf[JUnitRunner]) 
class MyDAOSpec extends Specification { 
    "MyDAO" should { 
    "insert a record and return its id" in new WithApplication { 
     val id = MyDAO.insert("file1", 101) 
     id must be_>=(0) 
    } 
    } 
} 

См Anorm, simple SQL data access для больше примеров того, как извлекать данные из наборов результатов.

+0

и как это связано с моей ошибкой? –

+0

Отношение состоит в том, что этот ответ показывает вам способ вставить запись, возвращающую идентификатор, не вызывая описанные вами ошибки. Первая ошибка была вызвана использованием executeInsert для возврата данных. Во-вторых, для попытки получить результат из инструкции, которая не возвращает результирующий набор. –

+0

Я спрашиваю о решении моей проблемы, а не о том, как сделать то же самое. –

Смежные вопросы