一个应用程序例子 现在通过一个简单的例子,我们检测一下移动数据库应用程序的典型用法和要害组件。 移动联系治理器
这是一个由PointBase提供的移动联系治理器的例子。联系治理器 contact manager包括在PointBase 4.x中。为了读者方便,我已经把源代码打包成zip文件放在Resource中。假如你想编译和运行例子,你必须先从PointBase处下载适当的jar文件。 这个应用程序本身比较简单。它主要沿用了高级地址本应用程序的通用特性。例如,它答应用户存储联系人名字,地址和电话号码;提供自觉浏览和搜索接口;和后台数据库服务器同步。图1和图2分别显示了该应用程序在标准模式和同步模式下的操作。这些屏幕快照来自一个由Insignia’s Jeode PersonalJava VM驱动的Pocket PC 和一个由J2SE驱动的Mac OS X 膝上型电脑。相同字节代码的应用程序没有经过修改运行在许多平台上,证实了Java的威力。  图1 在袖珍PC Jeode PersonalJava上的标准联系治理器  图2 在Mac OS X上的两个同步的联系治理器spoke 客户端应用程序UI(用户界面)是用AWT写的。这是被PersonalJava或J2ME/FP/PP设备所支持的唯一标准UI库。除了这些UI驱动,我们还有另一个代码层,它提供访问一般的设备上JDBC数据库。这个数据库访问层也提供了与后台服务器同步移动数据的逻辑,它是通过PointBase专有UniSync同步服务器来实现的。现在我们来看看数据访问层的代码,它包括在一个单独的类:DBManager. 设备上的数据访问 类DBManager是一个单独的类,它提供从应用程序单点访问数据。这个单独模式避免了嵌入式数据库的线程复杂性。下面的代码片断显示了DBManager的构造器和初始化的代码。它连接数据库,定义表,将测试数据导入表中,创建为以后时候的SQL状态模版(PreparedStatement)。正如我们所看到的,这里用到的都是标准JDBC。对于企业Java 开发者下面的代码应该很轻易明白: 例1 连接移动数据库和初始化访问对象 class DBManager { // DBManager is a singleton class. private static DBManager instance; private String driver; private String url; private String user; private String passWord; private boolean delay; private Connection connection; private Statement statement; private PreparedStatement insert; private PreparedStatement find; private PreparedStatement delete; private PreparedStatement update; private PreparedStatement all; static DBManager getInstance() { if (instance == null) { instance = new DBManager(); } return instance; } private DBManager() { // Get parameters from runtime properties. // This allows us to switch to different JDBC databases // without changing the application code. Properties properties = ContactManager.getProperties(); driver = properties.getProperty("driver", "com.pointbase.me.jdbc.jdbcDriver"); url = properties.getProperty("url", "jdbc:pointbase:micro:pbdemo"); user = properties.getProperty("user", "PBPUBLIC"); password = properties.getProperty("password", "PBPUBLIC"); delay = properties.getProperty("delayread","true").equals("true"); connect(); } private void connect() { try { // Load the driver class. Class.forName(driver); // If the database doesn't exist, create a new database. connection = DriverManager.getConnection(url, user, password); // Create template statement objects. statement = connection.createStatement(); createStatement(); // If the database is newly created, load the schema. boolean newdb=initDatabase(); // Load sample data for the new tables. if(newdb) { SampleDataCreator.insert(connection); } } catch (Exception e) { e.printStackTrace(); System.exit(1); } } void disconnect() { try { connection.commit(); statement.close(); insert.close(); find.close(); delete.close(); update.close(); all.close(); connection.close(); System.exit(0); } catch (Exception e) { e.printStackTrace(); System.exit(1); } } // Create the table and load the schema. private boolean initDatabase() { try { String sql = "CREATE TABLE NameCard (ID INT PRIMARY KEY, "+ "Name VARCHAR(254), Company VARCHAR(254), Title VARCHAR(254), "+ "Address1 VARCHAR(254), Address2 VARCHAR(254), "+ "Phone VARCHAR(254), Email VARCHAR(254), "+ "Picture Binary(1000000))"; // If the table already exists, this will throw an exception. statement.executeUpdate(sql); // This means the database already exists. return true; } catch (SQLException e) { // Ignore the error - the table already exists, which is good // so we don't need to add demo data later on. return false; } } // Create statement templates. private void createStatement() { try { insert = connection.prepareStatement( "INSERT INTO NameCard (ID, Name, Company, Title, Address1, "+ "Address2, Phone, Email, Picture) "+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"); find = connection.prepareStatement( "SELECT * FROM NameCard WHERE (Name LIKE ?) "+ "AND (Company LIKE ?) AND (Title LIKE ?) "+ "AND ((Address1 LIKE ?) OR (Address2 LIKE ?)) "+ "AND (Phone LIKE ?) AND (Email LIKE ?)"); delete = connection.prepareStatement( "DELETE FROM NameCard WHERE ID = ?"); update = connection.prepareStatement( "UPDATE NameCard SET ID=?, Name=?, Company=?, Title=?, "+ "Address1=?, Address2=?, Phone=?, Email=?, Picture=? "+ "WHERE ID = ?"); all = connection.prepareStatement( "SELECT ID, Name, Company, Title, Address1, Address2, "+ "Phone, Email FROM NameCard"); } catch (SQLException e) { e.printStackTrace(); } } // Other methods. } 在DBManager中的其他方法通过简单JDBC API调用进行访问数据库。
如下的代码片断展示了搜索和操纵名称卡片记录的方法。这些方法使用了我们之前定义的SQL模版。 例2 数据访问方法 Vector findNameCardsByKeyword(String name, String company, String title, String address1, String address2, String phone, String email) { Vector NameCards = new Vector(); String[] keywords = {name, company, title, address1, address2, phone, email}; try { for (int i = 0; i < keywords.length; i++) { String criteria = (keywords[i].equals("")) ? "%" : "%" + keywords[i] + "%"; find.setString(i + 1, criteria); } ResultSet resultSet = find.executeQuery(); while (resultSet.next()) { NameCard nameCard = new NameCard(resultSet.getInt(1), resultSet.getString(2), resultSet.getString(3), resultSet.getString(4), resultSet.getString(5), resultSet.getString(6), resultSet.getString(7), resultSet.getString(8)); if (!delay) loadPic
|