相关文档 下载本手册
PDF (US Ltr) - 3.6Mb
PDF (A4) - 3.6Mb


4.2.2.4 ClusterJ 基本操作

在本节中,我们将介绍如何执行 ClusterJ 应用程序的基本操作,包括以下内容

  • 创建新实例、设置其属性并将它们保存到数据库

  • 执行主键查找(读取)

  • 更新现有行并将更改保存到数据库

  • 从数据库中删除行

  • 构造和执行查询,从数据库中获取满足特定条件的一组行

创建新行。  要将新行插入表格中,首先创建 Employee 的新实例。这可以通过调用 Session 方法 newInstance() 来完成,如下所示

Employee newEmployee = session.newInstance(Employee.class);

设置与所需 employee 表列对应的 Employee 实例属性。例如,以下设置了 idfirstNamelastNamestarted 属性。

emp.setId(988);

newEmployee.setFirstName("John");
newEmployee.setLastName("Jones");

newEmployee.setStarted(new Date());

对更改满意后,可以持久化 Employee 实例,从而导致将包含所需值的newRow 插入 employee 表,如下所示

session.persist(newEmployee);

如果自动提交已开启,并且数据库中已存在与该 Employee 实例的 id 相同的行,则 persist() 方法将失败。如果自动提交已关闭,并且数据库中已存在与该 Employee 实例的 id 相同的行,则 persist() 方法将成功,但随后的 commit() 将失败。

如果希望保存数据,即使该行已存在,也请使用 savePersistent() 方法而不是 persist() 方法。 savePersistent() 方法根据需要更新现有实例或创建新实例,不会抛出异常。

未指定的将使用其 Java 默认值存储(对于整数类型为 0,对于数字类型为 0.0,对于引用类型为 null)。

主键查找。  可以使用 Sessionfind() 方法查找 NDB 表中的现有行,如下所示

Employee theEmployee = session.find(Employee.class, 988);

这等效于主键查找查询 SELECT * FROM employee WHERE id = 988

ClusterJ 还支持复合主键。 find() 方法可以接受一个对象数组作为键,其中对象数组的组件用于表示主键列,顺序与声明顺序相同。此外,查询经过优化,可以检测主键列是否被指定为查询条件的一部分,如果是,则将执行主键查找或扫描作为实现查询的策略。

注意

ClusterJ 还支持多列有序 B 树和唯一哈希索引。与主键一样,如果查询指定了有序或唯一索引字段的值,ClusterJ 会优化查询,使用索引扫描表格。

NDB Cluster 会自动将表格数据分布到多个数据节点。对于某些操作(查找、插入、删除和更新),向集群告知数据在哪个数据节点上物理存在,并在该数据节点上执行事务效率更高。ClusterJ 会自动检测分区键;如果操作可以针对特定数据节点进行优化,ClusterJ 会自动在该节点上启动事务。

更新并保存一行。  要更新我们刚刚获取的作为 theEmployee 的行中给定列的值,请使用名称与该列名称相对应的方法 set*()。例如,要更新该 Employeestarted 日期,请使用 EmployeesetStarted() 方法,如下所示

theEmployee.setStarted(new Date(getMillisFor(2010, 01, 04)));
注意

为了方便起见,我们在本示例中使用了方法 getMillisFor(),该方法定义如下,在文件 AbstractClusterJModelTest.java 中(位于 NDB Cluster 源代码树的 storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj 目录中)

/** Convert year, month, day into milliseconds after the Epoch, UTC.
* Set hours, minutes, seconds, and milliseconds to zero.
* @param year the year
* @param month the month (0 for January)
* @param day the day of the month
* @return
*/

protected static long getMillisFor(int year, int month, int day) {
  Calendar calendar = Calendar.getInstance();
  calendar.clear();
  calendar.set(Calendar.YEAR, year);
  calendar.set(Calendar.MONTH, month);
  calendar.set(Calendar.DATE, day);
  calendar.set(Calendar.HOUR, 0);
  calendar.set(Calendar.MINUTE, 0);
  calendar.set(Calendar.SECOND, 0);
  calendar.set(Calendar.MILLISECOND, 0);
  long result = calendar.getTimeInMillis();
  return result;
}

有关更多信息,请参阅指定的文件。

可以通过调用其他 Employee setter 方法来更新其他列,如下所示

theEmployee.setDepartment(3);

要将更改后的行保存回 NDB Cluster 数据库,请使用 SessionupdatePersistent() 方法,如下所示

session.updatePersistent(theEmployee);

删除行。  可以使用 SessiondeletePersistent() 方法轻松删除单个行。在本示例中,我们将找到 ID 为 13 的员工,然后从 employee 表中删除该行

Employee exEmployee = session.find(Employee.class, 13);

session.deletePersistent(exEmployee);'

System.out.println("Deleted employee named " + exEmployee.getFirst()
                 + " " + exEmployee.getLast() + ".");

还存在一个用于删除多行的方法,它提供两个选项

  1. 删除表格中的所有行。

  2. 删除任意行集合。

这两种类型的多行删除都可以使用 deletePersistentAll() 方法执行。 该方法的第一个变体 会作用于一个 Class。例如,以下语句会删除 employee 表中的所有行并返回删除的行数,如下所示

int numberDeleted = session.deletePersistentAll(Employee);

System.out.println("There used to be "  + numberDeleted + " employees, but now there are none.");

上面显示的 deletePersistentAll() 调用等效于在 mysql 客户端中发出 SQL 语句 DELETE FROM employee

deletePersistentAll() 也可用于删除行集合,如本示例所示

//  Assemble the collection of rows to be deleted...

List<Employee> redundancies = new ArrayList<Employee>();

for (int i = 1000; i < 2000; i += 100) {
  Employee redundant = session.newInstance(Employee.class);
  redundant.setId(i);
  redundancies.add(redundant);
}

numberDeleted = session.deletePersistentAll(redundancies);

System.out.println("Deleted " + numberDeleted + " rows.");

在删除行之前,不必在数据库中查找它们。

编写查询。  ClusterJ QueryBuilder 接口用于实例化查询。该过程从获取 QueryBuilder 实例开始,该实例由当前 Session 提供;然后,我们可以获得一个 QueryDefinition,如下所示

QueryBuilder builder = session.getQueryBuilder();

QueryDomainType<Employee> domain = builder.createQueryDefinition(Employee.class);

然后使用它来设置查询要比较的列。此处,我们将展示如何准备一个查询,该查询将 employee 表的 department 列的值与常量值 8 进行比较。

domain.where( domain.get("department").equal(domain.param("department") );

Query<Employee> query = session.createQuery(domain);

query.setParameter("department", 8);

要从查询中获取结果,请调用 QuerygetResultList() 方法,如下所示;

List<Employee> results = query.getResultList();

返回值是一个 List,可以迭代它以按常规方式检索和处理行。

事务。  可以选择使用 Transaction 接口通过以下方法绑定事务

也可以使用 Transaction 来检查事务是否处于活动状态(通过 isActive() 方法),并获取和设置仅回滚标志(分别使用 getRollbackOnly()setRollbackOnly())。

如果您不使用 Transaction 接口,则 Session 中影响数据库的方法(如 persist()deletePersistent()updatePersistent() 等)会自动包含在数据库事务中。