【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()
关闭连接并将其从当前线程中删除。
事务API
?到目前为止一切顺利,但要进行交易。
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#join和Collections#list方法的引用。这些类已经在每个 ActiveJDBC 应用程序的类路径上。