=====Schema Definition mit Avro in der Oracle NoSQL Datenbank=====
===Vorbereitung:===
Java Libraries :
* Avro Java Libraries laden von http://www.apache.org/dyn/closer.cgi/avro/
* avro-1.7.4.jar
* avro-tools-1.7.4.ja
* Jackson JSON library laden: http://wiki.fasterxml.com/JacksonDownload
* jackson-annotations-2.2.0.jar
* jackson-core-2.2.0.jar
* jackson-databind-2.2.0.jar
Libraries in eine Verzeichnis kopieren, in unsere Beispiel unter D:\entwicklung\avro-1.7.4
=== Ein Avro Schema definieren ===
Datei emp.avsc mit der Schema Definition anlegen:
{"namespace": "gpi.avro",
"type": "record",
"name": "emp",
"fields": [
{"name": "EMPNO" , "type": "int" , "default" : 0},
{"name": "ENAME" , "type": "string" , "default" : ""},
{"name": "JOB" , "type": "string" , "default" : ""},
{"name": "MGR" , "type": "int" , "default" : 0},
{"name": "HIREDATE", "type": "long" , "default" : 0},
{"name": "SAL" , "type": "float" , "default" : 0},
{"name": "COMM" , "type": "float" , "default" : 0},
{"name": "DEPTNO" , "type": "int" , "default" : 10}
]
}
}
Schema Definition siehe hier: [[http://avro.apache.org/docs/current/spec.html#schema_primitive|schema_primitive]] und [[http://docs.oracle.com/cd/NOSQL/html/GettingStartedGuide/avroschemas.html|Avro - Oracle NoSQL Getting Started]]
Das erste Problem, dass ins Auge fällt, ist die fehlende native Unterstützung für den Datentyp "date".
Wie in der Java Welt üblich, ist hier wie immer etwas Basteln angesagt, oder eben das Speichern des Datumswerts als Long Value.
Damit das Schema in der Datenbank später auch angepasst/geändert werden kann, muss ein Default Wert für die einzelnen Spalten definiert werden.
=== Schema prüfen und übersetzen ===
Mit den Avro Tool kann die Schema Definition überprüft und übersetzt werden.
java -jar D:\entwicklung\avro-1.7.4\avro-tools-1.7.4.jar compile schema .\emp.avsc .
Damit stehen die passende Java Klassen für die Schema Definition für die Serialisierung zur Verfügung.
=== Schema in der NoSQL Datenbank anlegen ===
Über die Admin Konsole wird das Schema in der Datenbank angelegt:
REM Admin Console starten:
java -jar D:\entwicklung\kv-2.1.8\lib\kvstore.jar runadmin -port 5000 -host localhost
REM Schema in der DB anlegen:
kv-> ddl add-schema -file emp.avsc
Added schema: gpi.avro.emp.1
REM Schemas in der DB anzeigen lassen:
kv-> show schemas
gpi.avro.emp
ID: 1 Modified: 2013-08-17 14:14:41 UTC, From: jupiter
=== Wie kann das Avro Schema in meiner Applikation genützt werden? ===
Ein Avro Schema kann auf verschiedene Weise in die eigene Applikation eingebunden werden.
* Generic
* Specific
* JSON
* Raw
Für die Details siehe [[http://docs.oracle.com/cd/NOSQL/html/GettingStartedGuide/avrobindings.html | NoSQL Guide Chapter 8]]
=== Ein erster Versuch mit einem Generic Binding ===
Ein einfaches Beispiel um mit Hilfe der Avro Schema Definition generisch in die DB zu schreiben:
(siehe auch [[http://docs.oracle.com/cd/NOSQL/html/GettingStartedGuide/genericbinding-overview.html|NoSQL Guide Generic Binding]])
package com.gpi.oranosql;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import oracle.kv.Consistency;
import oracle.kv.KVStore;
import oracle.kv.KVStoreConfig;
import oracle.kv.KVStoreFactory;
import oracle.kv.Key;
import org.apache.avro.generic.GenericData;
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.Schema;
import oracle.kv.avro.AvroCatalog;
import oracle.kv.avro.GenericAvroBinding;
public class AvroReadWrite {
// KV Store
public static KVStore kvstore = null;
public AvroReadWrite() {
}
public static void main(String[] args) {
AvroReadWrite avroReadWrite = new AvroReadWrite();
// get the host to connect as first parameter
String host = args[0];
// get the store Name
String store = args[1];
KVStoreConfig kvconfig = new KVStoreConfig(store, host);
// Connect to the store
kvstore = KVStoreFactory.getStore(kvconfig);
// Read the Avro Schema
Schema.Parser parser = null;
try {
parser = new Schema.Parser();
// read our avro schema definition
parser.parse(new File("emp.avsc"));
}
catch (IOException ex) {
System.out.println("Error -- File emp.avsc not found");
}
// parse the schema definition
// !!! Name of the Schema is :: namespace + name !!!
final Schema empSchema = parser.getTypes().get("gpi.avro.emp");
// connect to store and read Avro schema defintion in the database
AvroCatalog catalog = kvstore.getAvroCatalog();
//debug
//System.out.println("Info --" + catalog.getCurrentSchemas());
// Generic Binding
GenericAvroBinding binding = catalog.getGenericBinding(empSchema);
// Define the emp record
GenericRecord emp = new GenericData.Record(empSchema);
// put values in the record:
emp.put("EMPNO", 7898);
emp.put("ENAME", "SCOTT");
emp.put("JOB", "CLERK");
emp.put("MGR", 1000);
emp.put("HIREDATE", new Date().getTime());
emp.put("SAL", 12000f);
emp.put("COMM", 30f);
emp.put("DEPTNO", 10);
// Create the Key wiht minor und mayor component
Key key = Key.createKey("Mayer", "7899");
// put the emp record into the store
kvstore.put(key, binding.toValue(emp));
//close the store
kvstore.close();
System.exit(0);
}
}
Mit dem Client Tool kvcli testen:
java -jar D:\entwicklung\kv-2.1.8\lib\kvcli.jar -host localhost -port 5000 -store kvstore
kvshell-> get -all
/SCOTT/-/7898
{
"EMPNO" : 7898,
"ENAME" : "SCOTT",
"JOB" : "CLERK",
"MGR" : 1000,
"HIREDATE" : 1376751935296,
"SAL" : 12000.0,
"COMM" : 30.0,
"DEPTNO" : 10
}
Werte im Programm auslesen:
// see code above for the connection to the database
GenericRecord emp2;
Key key2 = Key.createKey("Mayer", "7899");
ValueVersion vv = kvstore.get(key2);
if (vv != null) {
emp2 = binding.toObject(vv.getValue());
String empno = emp2.get("EMPNO").toString();
String ename = emp2.get("ENAME").toString();
String job = emp2.get("JOB").toString();
int mgr = (Integer)emp2.get("MGR");
long time = (Long)emp2.get("HIREDATE");
Date hiredate = new Date();
hiredate.setTime(time);
System.out.println(" EMPNO ::"+empno);
System.out.println(" ENAME ::"+ename);
System.out.println(" JOB ::"+job);
System.out.println(" MGR ::"+mgr);
System.out.println(" HIREDATE ::"+hiredate);
}
==== Quellen ====
Dokumentation:
* http://avro.apache.org/docs/current/gettingstartedjava.html
Allgemein:
* http://martin.kleppmann.com/2012/12/05/schema-evolution-in-avro-protocol-buffers-thrift.html