2010-10-22 19 views
6

ScalaQuery ve Scala kullanmıştım.Bir BLOB alanı eklemek için ScalaQuery nasıl kullanılır?

Bir Array [Byte] nesnesine sahipseniz, bunu tabloya nasıl yerleştirebilirim?

object TestTable extends BasicTable[Test]("test") { 
    def id = column[Long]("mid", O.NotNull) 
    def extInfo = column[Blob]("mbody", O.Nullable) 

    def * = id ~ extInfo <> (Test, Test.unapply _) 
} 

case class Test(id: Long, extInfo: Blob) 

Ben, işletmek nasıl BLOB tipi alanıyla (GÜNCELLEME, INSERT, SEÇ) def extInfo = column[Array[Byte]]("mbody", O.Nullable) kullanılan yöntemi tanımlar mısınız?

BTW: BLOB alan null olduğu için hiçbir ScalaQuery etiketi

+0

teşekkürler @Craig gramer hatasını düzeltmeye yardımcı olur, ingilizcem iyi değil, tekrar teşekkürler. –

cevap

11

, ben şu tanımı için, Seçenek [Blob] ile olan Scala türünü değiştirmeniz önerilir:

object TestTable extends Table[Test]("test") { 
    def id = column[Long]("mid") 
    def extInfo = column[Option[Blob]]("mbody") 
    def * = id ~ extInfo <> (Test, Test.unapply _) 
} 

case class Test(id: Long, extInfo: Option[Blob]) 

Bir çiğ kullanabilirsiniz, null Blob değeri tercih, ama o zaman aslında (bir özel durum atma yerine) bunun dışında boş değer elde etmek sütun üzerinde OrElse (null) kullanmanız gerekiyorsa: a Şimdi

 def * = id ~ extInfo.orElse(null) <> (Test, Test.unapply _) 

ctual BLOB kullanımı. Okuma düz ileri: Sadece

Query(TestTable) foreach { t => 
    println("mid=" + t.id + ", mbody = " + 
     Option(t.extInfo).map { b => b.getBytes(1, b.length.toInt).mkString }) 
    } 

takmadan veya güncelleme veri istiyorsanız

, kendi BLOB'ları oluşturmak için gereken JDBC sürücüsü tarafından uygulanan sonucu, ör .: bir Blob nesnesi olsun.

import javax.sql.rowset.serial.SerialBlob 

TestTable insert Test(1, null) 
TestTable insert Test(2, new SerialBlob(Array[Byte](1,2,3))) 

Edit: Tek başına Blob nesnesi için uygun bir uygulama JDBC en RowSet özelliği tarafından sağlanmaktadır Ve burada (kimin BLOB'lar henüz ScalaQuery tarafından desteklenmez) Postgres için TypeMapper [Dizi [Bayt]] var:

örneğin, daha sonra

object PostgresByteArrayTypeMapper extends 
    BaseTypeMapper[Array[Byte]] with TypeMapperDelegate[Array[Byte]] { 
    def apply(p: org.scalaquery.ql.basic.BasicProfile) = this 
    val zero = new Array[Byte](0) 
    val sqlType = java.sql.Types.BLOB 
    override val sqlTypeName = "BYTEA" 
    def setValue(v: Array[Byte], p: PositionedParameters) { 
    p.pos += 1 
    p.ps.setBytes(p.pos, v) 
    } 
    def setOption(v: Option[Array[Byte]], p: PositionedParameters) { 
    p.pos += 1 
    if(v eq None) p.ps.setBytes(p.pos, null) else p.ps.setBytes(p.pos, v.get) 
    } 
    def nextValue(r: PositionedResult) = { 
    r.nextBytes() 
    } 
    def updateValue(v: Array[Byte], r: PositionedResult) { 
    r.updateBytes(v) 
    } 
    override def valueToSQLLiteral(value: Array[Byte]) = 
    throw new org.scalaquery.SQueryException("Cannot convert BYTEA to literal") 

} 

ve kullanım:

implicit object PostgresByteArrayTypeMapper extends 
     BaseTypeMapper[Array[Byte]] with TypeMapperDelegate[Array[Byte]] { 
    def apply(p: BasicProfile) = this 
    val zero = new Array[Byte](0) 
    val sqlType = java.sql.Types.BLOB 
    override val sqlTypeName = "BYTEA" 
    def setValue(v: Array[Byte], p: PositionedParameters) { 
     p.pos += 1 
     p.ps.setBytes(p.pos, v) 
    } 
    def setOption(v: Option[Array[Byte]], p: PositionedParameters) { 
     p.pos += 1 
     if(v eq None) p.ps.setBytes(p.pos, null) else p.ps.setBytes(p.pos, v.get) 
    } 
    def nextValue(r: PositionedResult) = { 
     r.pos += 1 
     r.rs.getBytes(r.pos) 
    } 
    def updateValue(v: Array[Byte], r: PositionedResult) { 
     r.pos += 1 
     r.rs.updateBytes(r.pos, v) 
    } 
    override def valueToSQLLiteral(value: Array[Byte]) = 
     throw new SQueryException("Cannot convert BYTEA to literal") 
    } 
+0

kod üzerinde kullanılabilir, ancak postgresql Sürücü bir özel durum atma: org.postgresql.jdbc2.AbstractJdbc2ResultSet.toLong (AbstractJdbc2ResultSet.java:2736) de org.postgresql.jdbc2.AbstractJdbc2ResultSet.getLong (AbstractJdbc2ResultSet.java:2032) en \t org.postgresql.jdbc3.Jdbc3ResultSet.getBlob (Jdbc3ResultSet.java:52) de \t org.scalaquery.session.PositionedResult.nextBlob (PositionedResult.scala: 22) de \t: // jdbc, ben postgresql JDBC docs (bkz http .postgresql.org/documentation/83/binary-data.html), ResultSet'te getBytes kullanmanız gerekebilir. –

+0

Gerçekten de, ScalaQuery'nin standart BLOB işlemi Postgres üzerinde çalışmıyor. (Örnek benim için H2, MySQL, Derby ve HsqlDb'de çalışıyor). Bu sorun için http://github.com/szeiger/scala-query/issues/issue/7 adresini açtım. Şimdilik, DB standart olmayan türde adlar vermeniz veya standart olmayan erişimcileri kullanmanız gerekiyorsa, kendi TypeMapper'ınızı (muhtemelen java.sql.Blob'den daha kullanışlı olan özel bir tür için) uygulayabilirsiniz. – szeiger

+1

Üzgünüm, kendimi uygulamaya çalışıyorum TypeMapper, BArrayTypeMapper'ın yeni 'örtük nesnesi tanımlandı BaseTypeMapper [Array [Byte]] ve class sınıfı BArrayTypeMapperDelegate, TypeMapperDelegate [Array [Byte]] dizinini genişletiyor, ancak bir derleme hatası beni engelliyor,' org.scalaquery.ql.TypeMapper [Seçenek [Array [Byte]]] türüne ait kanıt parametresi için örtük değer bulamaz.Postgresql Sürücüsünde bir Array [Byte], e-posta [email protected], uygulamak için bir örnek kod gönderebilir misiniz, çok teşekkür ederim. –

1

sadece belki de birisi için biraz zaman kazandıracak, Scala ve SQ için güncellenmiş kod sonrası

... 
// defining a column 
def content = column[Array[Byte]]("page_Content")(PostgresByteArrayTypeMapper) 
İlgili konular