【ActiveJdbc】05

一、事务

通常在 Java ORM 中有一个显式连接或管理器对象(JPA 中的 EntityManager,Hibernate 中的 SessionManager 等)。

ActiveJDBC 中没有这样的对象。

 

下面是一个没有事务管理的最基本的 ActiveJDBC 应用程序示例:

public static void main(String[] args) {
   Base.open("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/test", "the_user", "the_password");
   Employee e = new Employee();
   e.set("first_name", "John");
   e.set("last_name", "Doe");
   e.saveIt();
   Base.close();
}

该调用Base.open()打开一个连接并将其附加到当前线程。

所有模型的所有后续方法都重用此连接。、

该调用Base.close()关闭连接并将其从当前线程中删除。

 

?到目前为止一切顺利,但要进行交易。

 

ActiveJDBC 确实提供了一些与事务相关的便利调用:

开始交易:

Base.openTransaction();

提交交易:

Base.commitTransaction();

并回滚:

Base.rollbackTransaction();

所有这些方法都简单地调用java.sql.Connection.setAutocommit(false),java.sql.Connection.commit()java.sql.Connection.rollback()分别在 INFO 级别包装异常和记录事件。

正如您所看到的,ActiveJDBC 在这里并没有尝试做太多事情,只是想不碍事。

如果您需要更精细的控制,您可以获取当前连接并对其执行纯 JDBC 操作:

java.sql.Connection con = Base.connection();
con.setAutocommit(false);
...//or:
Base.connection().setAutocommit(false);

 

事务完整事例:

一个使用事务的简单程序如下所示:

public static void main(String[] args) {
   try{
      Base.open("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/test", "the_user", "the_password");
      Base.openTransaction();
      Employee e = new Employee();
      e.set("first_name", "John");
      e.set("last_name", "Doe");
      e.saveIt();
      Base.commitTransaction();
   catch(Exception e){
      Base.rollbackTransaction();
   }finally{
      Base.close();
   }
}

 

和JNDI组合:

但是通常情况下,连接是从容器池中请求的,而事务配置已经由容器配置提供。

在这些情况下,用法是相同的(几乎),但您必须意识到某些调用可能不会成功,或者驱动程序可能会产生意想不到的副作用。

 

例如,如果您从池中请求连接,则事务可能会在那时开始,并且在您调用时:

Base.connection().setAutocommit(true/false);

,您可能会不小心提交正在进行的事务(?或者驱动程序将忽略您的调用并且什么也不做)。

ActiveJDBC 并没有在 J2EE 和 JDBC 已经提供的东西上添加任何特殊的东西。

以下是 MessageDriven Bean (JMS) 中使用的 ActiveJDBC 示例:

public void onMessage(Message m){
   Base.open("myConnectionJNDIName");
   TextMessage tm = (TextMessage)m;
   String content = tm.getText();
   String name = tm.getStringProperty("name");
   try{
      Article.create("name", name, "content", content).saveIt();
   }
   catch(Exception e){
     ctx.setRollbackOnly(); // == this will send the message back into queue
   }
   finally{
      Base.close();//always close connection
   }
}

在上面的示例中,容器将管理事务。它将同时回滚:JDBC 和 JMS 事务。

 

二、IN条件的特殊处理

在某些情况下,您需要编写如下内容:

SELECT my_column FROM my_table where search_column IN (?)

不幸的是,JDBC 不支持此功能,因此我们有如下解决方法:Preparedstatement IN 子句替代方案/StackOverflow

 

IN子句解决方法

解决方法很简单,如果你想执行这个:

String sql = "name IN ('John', 'Hellen', 'Henry')";

然后你用单引号和逗号加入这个列表:

List names = Collections.list("John", "Hellen", "Henry");
List<Person> people = Person.where("name IN ('" + Util.join(names, "', '") + "')");

您可以将此方法用于相对较小的列表,因为列表越大,生成的查询越长。每个数据库对查询的大小都有限制,因此您的里程可能会有所不同。

请参阅对Util#joinCollections#list方法的引用这些类已经在每个 ActiveJDBC 应用程序的类路径上。

 

posted @ 2021-07-21 19:29  emdzz  阅读(94)  评论(0编辑  收藏  举报