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实例,从而将包含所需值的新行插入到 employee表中,如下所示:

session.persist(newEmployee);

如果自动提交打开,并且 数据库中已经存在 id与此实例 相同的行,则该方法失败。如果自动提交关闭并且数据库中已存在与此 实例相同的行,则该方法成功但后续失败。 Employeepersist()idEmployeepersist()commit()

如果您希望在行已存在的情况下保存数据,请使用savePersistent()方法而不是persist()方法。该 savePersistent()方法根据需要更新现有实例或创建新实例,而不会引发异常。

您未指定的值与其 Java 默认值一起存储(0对于整数类型、 0.0数字类型和 null引用类型)。

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

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

这相当于主键查找查询 SELECT * FROM employee WHERE id = 988

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

笔记

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

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

更新并保存一行。  要更新我们刚刚获得的行中给定列的值theEmployee,请使用 set*()名称对应于该列名称的方法。例如,要更新 startedthis 的日期 Employee,请使用 EmployeesetStarted()方法,如下所示:

theEmployee.setStarted(new Date(getMillisFor(2010, 01, 04)));
笔记

为了方便起见,我们在这个例子中使用了一个方法 getMillisFor(),它在文件 AbstractClusterJModelTest.java中(在 storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj NDB Cluster 源树的目录中找到)定义如下所示:

/** 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;
}

有关详细信息,请参阅指示的文件。

您可以通过调用其他 Employeesetter 方法来更新其他列,如下所示:

theEmployee.setDepartment(3);

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

session.updatePersistent(theEmployee);

删除行。 deletePersistent() 您可以使用 的方法 轻松删除单行 Session。在这个例子中,我们找到 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()相当于 DELETE FROM employeemysql客户端中发出 SQL 语句。

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

然后使用它来设置查询比较的列。在这里,我们展示了如何准备一个将employeedepartment列的值与常量值 进行比较的查询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();

The return value is a List that you can iterate over to retrieve and process the rows in the usual manner.

Transactions.  The Transaction interface can optionally be used to bound transactions, via the following methods:

It is also possible using Transaction to check whether the transaction is active (via the isActive() method, and to get and set a rollback-only flag (using getRollbackOnly() and setRollbackOnly(), respectively).

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