SmartESQL示例
以下代码片段展示了基本的嵌入式 Java 应用程序实现:
import com.mcobject.smartedb.*;
import java.io.Console;
@Persistent // class will be stored in SmartEDB database
class MyTable
{
int pk;
String value;
};
public class Sql
{
static final int PAGE_SIZE = 128;
static final int DISK_PAGE_SIZE = 4096;
static final int DISK_CACHE_SIZE = 8*1024*1024;
static final int DATABASE_SIZE = 16*1024*1024;
public static void main(String[] args)
{
Database db;
int config = Database.MCO_CFG_SQL_SUPPORT;
boolean is_dptr = false;
Database.Device devs[];
Database.Parameters params = new Database.Parameters();
// get config parameters from the command line
for (String s : args)
{
if ("disk".equals(s)) config |= Database.MCO_CFG_DISK_SUPPORT;
if ("shm".equals(s)) config |= Database.MCO_CFG_SHARED_MEMORY;
if ("debug".equals(s)) config |= Database.MCO_CFG_DEBUG_LIBRARY;
if ("mvcc".equals(s)) config |= Database.MCO_CFG_MVCC_TRANSACTION_MANAGER;
if ("dptr".equals(s)) is_dptr = true;
if (s.startsWith("license:")) params.license_key = s.substring(8);
}
params.memPageSize = PAGE_SIZE; // memory page size
params.classes = new Class[] { MyTable.class }; // list of classes which should
// be stored in eXremeDB
// database. The classes must use
// the @Persistent annotation
params.maxConnections = 10;
if ((config & Database.MCO_CFG_DISK_SUPPORT) != 0)
{ // on-disk configuration
java.io.File file = new java.io.File("opendb.dbs");
file.delete();
file = new java.io.File("opendb.log");
file.delete();
params.diskPageSize = DISK_PAGE_SIZE; // disk page size
params.diskClassesByDefault = true; // mark @Persistent classes as on-disk
// classes by default
// declare memory devices
devs = new Database.Device[4];
if ((config & Database.MCO_CFG_SHARED_MEMORY) != 0)
{
devs[0] = new Database.SharedMemoryDevice(Database.Device.Kind.Data,
"opendb-db", 0, DATABASE_SIZE);
devs[1] = new Database.SharedMemoryDevice(Database.Device.Kind.DiskCache,
"opendb-cache", 0,
DISK_CACHE_SIZE);
}
else
{
devs[0] = new Database.PrivateMemoryDevice(Database.Device.Kind.Data,
DATABASE_SIZE);
devs[1] = new atabase.PrivateMemoryDevice(Database.Device.Kind.DiskCache,
DISK_CACHE_SIZE);
}
devs[2] = new Database.FileDevice(Database.Device.Kind.Data, "opendb.dbs");
devs[3] = new Database.FileDevice(Database.Device.Kind.TransactionLog,
"opendb.log");
}
else
{ // in-memory configuration
devs = new Database.Device[1];
if ((config & Database.MCO_CFG_SHARED_MEMORY) != 0)
{
long hint = 0;
if (is_dptr)
hint = 0x20000000;
devs[0] = new Database.SharedMemoryDevice(Database.Device.Kind.Data,
"opendb-db", hint,
DATABASE_SIZE);
} else
{
devs[0] = new Database.PrivateMemoryDevice(Database.Device.Kind.Data,
DATABASE_SIZE);
}
}
// create Database object
db = new Database(config);
db.open("sqldb", params, devs); // open database.
一旦打开数据库,就必须创建一个连接来访问它。应用程序可以通过 Database 类创建连接,例如:
Database db = new Database(Database.Mode.DebugSupport,“../../target/bin.so");
int maxAttempts = 10;
SqlLocalConnection conLocal = db.connectSql();
SqlRemoteConnection conRemote = db.connectRemoteSql(host, port, maxAttempts);
或者可以通过调用 SqlLocalConnection 或 SqlRemoteConnection 构造函数来实例化连接。请注意,对于远程连接的一个限制是,当前在单个连接中无法同时执行多个查询。因此,例如,如下这样的操作将无法实现:
SqlResultSet rs1 = conRemote.executeQuery("select * from Class1");
SqlResultSet rs2 = conRemote.executeQuery("select * from Class2");
Iterator<Class1> i1 = rs1.iterator();
Iterator<Class2> i2 = rs2.iterator();
while (i1.hasNext() && i2.hasNext())
{
...
}
然后使用 executeQuery() 方法执行 SQL 查询,该方法执行 SQL 选择语句并返回一个 SqlResultSet,或者使用 executeStatement() 方法执行 SQL 插入、更新或删除语句,并返回受影响的行数。例如:
SqlLocalConnection con = db.connectSql();
con.startTransaction(Database.TransactionType.ReadWrite);
con.executeStatement("insert into MyTable (pk,value) values (?,?)", 2012,
"Good bye");
con.executeStatement("insert into MyTable (pk,value) values (?,?)", 2013,
"Hello");
con.commitTransaction();
con.startTransaction(Database.TransactionType.ReadOnly);
SqlResultSet result = con.executeQuery("select pk,value from MyTable”
“ where pk>=?", 2013);
for (String column : result.getColumnNames())
{
System.out.print(column + ", ");
}
System.out.println();
for (SqlTuple tuple : result)
{
System.out.println(tuple.getInt(0) + ", " + tuple.get("value"));
}
con.commitTransaction();
con.disconnect();
db.close();
}
请注意,数据库事务必须通过 con.startTransaction() 显式启动,并通过 con.commitTransaction() 或 con.rollbackTransaction() 关闭。连接必须通过 con.disconnect() 关闭,数据库必须通过 db.close() 关闭。另外,请注意,executeQuery() 和 executeStatement() 这两个方法都允许将参数替换到语句中,以替换标记为 ? 或 %x 的占位符,其中 x 指定参数类型,可以是以下类型之一:
%b = bool
%i = signed<4>
%u = unsigned<4>
%l = signed<8>
%t = datetime
%s = string
%w = nstring
在大多数情况下,可以使用传统的 ODBC/JDBC 占位符“?”。如果您想将字符串作为 Unicode(宽字符)字符串(%w)而不是多字节字符字符串(%s)传递,则需要特定的参数类型说明符。例如:
con.executeQuery("select * from Employee where department=? and salary > ?", "HR", 50000);
executeQuery()
方法返回一个实现了 IEnumerable<SqlTuple> 接口的 SqlResultSet 对象。然后,如上面的代码片段所示,在一个 for
循环中提取元组值。
还可以获取结果列名的数量和列表。通过 SqlResultSet.getEnumerator() 方法返回一个 SqlCursor 实例,该实例实现了 IEnumerator<SqlTuple> 接口,并提供对所选元组的单向迭代。(请注意,无法重置迭代器以重新开始遍历。)SqlTuple 类表示列值的集合。它提供了获取列数的方法(不过最好从 SqlResultSet 集合而不是从元组获取此数字)以及提取特定列值的方法。
列可以通过索引(从 0 开始)或名称进行访问,如上例所示。
返回值的类型为:
- bool
- long
- double
- decimal
- String
- byte[]
- DateTime
通过索引访问元组的值是推荐的做法,因为使用列名需要进行哈希查找。可以使用一次 SqlResultSet.getColumnNo(string columnName) 方法通过列名获取列的索引;然后使用返回的索引来获取元组的值。