文档 / 持久化
保存
保存将根据 bean 的状态插入或更新 bean。
Order order = new Order();
order.setOrderDate(new Date());
...
// insert the order
order.save();
如果已获取 bean,则将更新 bean...
Order order = DB.find(Order.class, 42);
order.setStatus(SHIPPED);
...
// update the order
order.save();
保存和删除将基于关联的 @OneToMany、@OneToOne 等注解中指定的 CascadeType 进行级联。
默认情况下,保存和删除不会级联,因此您需要为 save() 或 delete() 指定级联类型(例如以下详细信息中的级联类型)以进行级联。
...
@Entity
@Table(name="orders")
public class Order {
...
@ManyToOne // no cascading
Customer customer;
@OneToMany(cascade=CascadeType.ALL) // save and delete cascaded
List<OrderDetail> details;
...
请注意 details 属性上的 @OneToMany(cascade=CascadeType.ALL)。这意味着 save() 和 delete() 都将从订单级联到其订单详细信息。
...
// save the order ... will cascade also saving the order details
DB.save(order);
删除
删除与保存非常相似。只需调用 DB.delete();
...
Order order = DB.find(Order.class, 12);
// delete the order
// ... this will cascade also deleting the order details
// ... with either CascadeType.ALL or CascadeType.REMOVE
DB.delete(order);
级联
映射注解 @ManyToOne、@OneToMany、@OneToOne 和 @ManyToMany 提供了一个级联属性,用于控制是否级联保存和删除。
默认情况下,不级联保存或删除(根据 JPA 规范)。
以下示例显示了具有其映射注解的 Order 实体 bean。如果您保存一个 Order,则详细信息也将被保存,但关联的客户不会被保存,因为没有级联属性,并且默认情况下不级联。
...
@Entity
@Table(name="orders")
public class Order {
...
@ManyToOne // no cascading
Customer customer;
@OneToMany(cascade=CascadeType.ALL) // save and delete cascaded
List<OrderDetail> details;
批量更新
Update 提供了一种发出插入、更新或删除语句的方法。
这对于使用单个语句(通常称为“批量”更新)更新或删除多行(或单行)非常有用。
如果您想在不先执行查询的情况下执行更新或删除,这也很有用。这是在无状态 Web 应用程序中执行更新的典型方法。
该语句可以作为原始 DML 提供,其中包含表名和列名,也可以采用“逻辑”形式,其中实体名用于代替表名,属性名用于代替列名。
// orm bulk delete use bean name and bean properties
DB.createUpdate(OrderDetail.class, "delete from orderDetail").execute();
// sql bulk update uses table and column names
DB.sqlUpdate("delete from country").execute();
批量 SQL 更新
与 SqlQuery 类似,您可以使用命名或定位参数指定 SQL INSERT、UPDATE 或 DELETE 语句。
String dml = "update b_bug set title=:title where id = :id";
int rows = DB.sqlUpdate(dml)
.setParameter("title", "Updated Again")
.setParameter("id", 1)
.execute();
CallableSql
CallableSql 提供了一种调用数据库存储过程的方法。
String sql = "{call sp_order_mod(?,?)}";
CallableSql cs = DB.createCallableSql(sql);
cs.setParameter(1, "turbo");
cs.registerOut(2, Types.INTEGER);
DB.execute(cs);
// read the out parameter
Integer returnValue = (Integer) cs.getObject(2);
您可以扩展 CallableSql,还可以从事务中获取 java.sql.Connection,并使用原始 JDBC API 调用存储过程。
原始 JDBC
您无法始终预测应用程序需求何时无法通过 Ebean 中的功能得到满足。如果您需要,了解您可以轻松使用原始 JDBC 会很好。
java.sql.Connection 对象可以从事务中返回,有了它,您可以执行任何您喜欢的原始 JDBC 调用。
这对于保存点、高级 Clob/Blob 使用或高级存储过程调用(如果 CallableSql 无法为您完成业务)可能很有用。
try (Transaction transaction = DB.beginTransaction()) {
Connection connection = transaction.getConnection();
// use raw JDBC
...
transaction.commit();
}
JDBC 批处理
Ebean 提供对 JDBC 批处理的支持。批处理将相关的 SQL 语句分组到一个批处理中,并通过一次调用提交到数据库。
批处理设置可以通过 application.properties 或通过 DatabaseConfig 进行配置,并且可以针对每个事务进行覆盖。
您可以通过 setBatch() 为要保存的实体设置批处理模式,并通过 setCascadeBatch() 为其子集合设置批处理模式。
...(正在建设中)...需要提供更好的指导,说明如何确定批处理模式、子批处理模式和批处理大小
Transaction transaction = database.beginTransaction();
try {
// turn of cascade persist
transaction.setCascadePersist(false);
// control the jdbc batch mode and size
// transaction.setBatchMode(true); // equivalent to transaction.setBatch(PersistBatch.ALL);
// transaction.setBatchMode(false); // equivalent to transaction.setBatch(PersistBatch.NONE);
transaction.setBatch(PersistBatch.ALL); // PersistBatch: NONE, INSERT, ALL
transaction.setCascadeBatch(PersistBatch.INSERT); // PersistBatch: NONE, INSERT, ALL
transaction.setBatchSize(30);
// for a large batch insert if you want to skip
// getting the generated keys
transaction.setGetGeneratedKeys(false);
// for batch processing via raw SQL you can inform
// Ebean what tables were modified so that it can
// clear the appropriate L2 caches
String tableName = "customer";
boolean inserts = true;
boolean upates = true;
boolean deletes = false;
transaction.addModification(tableName, inserts, updates, deletes);
...
} finally {
transaction.end();
}
@Transactional(batchSize = 50)
public void goodStuff() {
order.save()
customer.save()
}