2010-10-22 7 views
6

Ich benutzte ScalaQuery und Scala.Wie verwende ich ScalaQuery, um ein BLOB-Feld einzufügen?

Wenn ich ein Array [Byte] -Objekt habe, wie füge ich es in die Tabelle ein?

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) 

Kann ich definieren die Methode def extInfo = column[Array[Byte]]("mbody", O.Nullable), wie zu bedienen (UPDATE, INSERT, SELECT) mit dem Typ-Feld BLOB?

BTW: keine ScalaQuery Tag

+0

danke @Craig Hilfe beheben Sie die Grammatikfehler, mein Englisch ist nicht gut, danke nochmal. –

Antwort

11

Da das BLOB-Feld NULL-Werte zulässt, schlage ich vor, seine Scala Typ Option [Blob], für die folgende Definition zu ändern:

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]) 

Sie ein rohes verwenden können, Nullable-Blob-Wert, wenn Sie es vorziehen, aber dann müssen Sie orElse (null) auf der Säule verwenden, um tatsächlich einen Nullwert aus ihm heraus (statt eine Ausnahme zu werfen):

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

Jetzt für die ein periodisches BLOB-Handling. Lesen ist geradlinig: Sie haben soeben ein Blob-Objekt im Ergebnis erhalten, die durch den JDBC-Treiber implementiert ist, z.B .:

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

Wenn Sie zum Einfügen oder Aktualisieren von Daten, müssen Sie Ihre eigene BLOBs erstellen. Eine geeignete Implementierung für Stand-alone-Blob-Objekt wird von JDBC des RowSet Funktion zur Verfügung gestellt:

import javax.sql.rowset.serial.SerialBlob 

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

Edit: Und hier ist ein TypeMapper [Array [Byte]] für Postgres (deren BLOBs sind noch nicht von ScalaQuery unterstützt):

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

I obigen Code verwendet, aber postgresql Treiber Auslösen einer Ausnahme: bei org.postgresql.jdbc2.AbstractJdbc2ResultSet.toLong (AbstractJdbc2ResultSet.java:2736) \t bei org.postgresql.jdbc2.AbstractJdbc2ResultSet.getLong (AbstractJdbc2ResultSet.java:2032) \t bei org.postgresql.jdbc3.Jdbc3ResultSet.getBlob (Jdbc3ResultSet.java:52) \t bei org.scalaquery.session.PositionedResult.nextBlob (PositionedResult.scala: 22), sehe ich die postgresql JDBC-Dokumentation (http: // jdbc .postgresql.org/documentation/83/binary-data.html), vielleicht brauchen Sie getBytes im ResultSet. –

+0

Tatsächlich funktioniert ScalaQuerys Standard-BLOB-Behandlung bei Postgres noch nicht. (Das Beispiel funktioniert für mich auf H2, MySQL, Derby und HsqlDb). Ich habe http://github.com/szeiger/scala-query/issues/issue/7 für dieses Problem geöffnet. Für den Fall, dass Sie dem DB nicht standardmäßige Namen geben oder nicht standardmäßige Zugriffsmethoden verwenden müssen, können Sie einen eigenen TypeMapper implementieren (möglicherweise für einen benutzerdefinierten Typ, der für Sie besser geeignet ist als java.sql.Blob). – szeiger

+1

Sorry, ich versuche, mich selbst TypMapper zu implementieren, definierte ich das neue implizite Objekt BArrayTypeMapper erweitert BaseTypeMapper [Array [Byte]] 'und' Klasse BArrayTypeMapperDelegate erweitert TypeMapperDelegate [Array [Byte]] ', aber ein Kompilierfehler blockieren mich,' könnte Impliziter Wert für den Beweisparameter des Typs org.scalaquery.ql.TypeMapper [Option [Array [Byte]]] 'nicht gefunden.Können Sie mir einen Beispielcode senden, um ein Array [Byte] auf Postgresql-Treiber, meine E-Mail [email protected], vielen Dank zu implementieren. –

1

poste ich nur einen aktualisierten Code für Scala und SQ, vielleicht wird es einige Zeit für jemanden sparen:

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") 

} 

und dann Verwendung, zum Beispiel:

... 
// defining a column 
def content = column[Array[Byte]]("page_Content")(PostgresByteArrayTypeMapper) 
Verwandte Themen