ActiveJPA:针对JPA的勾当记录模式
当前位置:以往代写 > JAVA 教程 >ActiveJPA:针对JPA的勾当记录模式
2019-06-14

ActiveJPA:针对JPA的勾当记录模式

副标题#e#

ActiveRecord是Ruby on Rails的ORM层,概略上雷同于Java中的Hibernate。ActiveRecord基于约定优于设置的原则,所以它利用起来比Hibernate更容易。在简化根基的数据操纵方面,如建设、读取、更新和删除,它确实长短常棒的。

借助于ActiveRecord,你的模子类也会作为数据会见工具(Data Access Object,DAO)来执行CRUD操纵。在劈头探究之后,我对ActiveRecord发生了浓重的乐趣,因此开始寻找一种办理方案来简化基于Java耐久化API(Java Persistence API,JPA)的ORM框架的利用。

大大都JPA应用城市有某种范例的数据会见层(Data Access Layer,DAL)来与数据库举办交互。凡是DAL会包括数据会见工具或切合Repository设计模式的类。

DAO的实现与实体工具凡是是一对一的干系,而Repository则是针对每个聚合根(aggregate root)实现一个。不管是哪种场景,应用最后城市建设多个类与数据库举办交互。尽量适当的抽象可以或许有效限制所建设类的数量,可是它终究照旧会在应用中引入一个特另外层,这都是需要维护和测试的。

ActiveJPA基于JPA,提供了Martin Fowler所提出的勾当记录模式(Active Record pattern)的Java实现。借助于ActiveJPA,模子自己会作为DAO并与数据库交互,这样就不需要特另外代码作为数据会见层了。

ActiveJPA利用到了JPA类型,因此所有JPA的ORM实现(Hibernate、EclipseLink、OpenJPA等)都可以与ActiveJPA协同利用。

将已有的JPA模子转换为ActiveJPA

要将已有的模子转换为ActiveJPA,只需让你的模子实现扩展org.activejpa.entity. Model即可:

@java.persistence.Entity   
public class YourModel extends org.activejpa.entity.Model {   
}

执行CRUD操纵

你的模子将会从ActiveJPA的模子类中担任获得许多的CRUD成果。

//按照id得到订单    
Order order = Order.findById(12345L);

// 按照customer得到其已发货的订单   
List orders = Order.where("customerEmail", "[email protected]",
 "status", "shipped");

// 获得匹配过滤条件的第一条订单记录 
Long count = Order.first("customerEmail", "[email protected]", 
"status", "shipped");

// 获得匹配过滤条件的独一一条订单记录
Long count = Order.one("customerEmail", "[email protected]", 
"status", "shipped");

// 获得所有的记录   
List orders = Order.all();

// 查抄指定标识符的订单是否存在   
boolean exists = Order.exists(1234L);

// 生存订单   
order.persist();

// 删除订单   
order.delete();

// 刷新订单
order.refresh();

// 与耐久化上下文中已有的订单举办归并
order.merge();

过滤与分页

对记录举办过滤时,你并不需要建设JPQL或criteria查询。ActiveJPA提供了一个巨大的过滤器,用于在差异的操纵间举办毗连(conjunction):

// 获取匹配指定Email地点且账单额大于1000的所有订单,而且要举办分页 
Filter filter = new Filter();    
filter.setPageNo(1);    
filter.setPerPage(25);    
filter.addCondition(new Condition("customerEmail", Operator.eq,
 "[email protected]");

filter.addCondition(new Condition("billingAmount", Operator.gt, 
1000.00);   
List orders = Order.where(filter);

// 对满意过滤条件的订单举办计数   
Long count = Order.count(filter);

// 删除匹配这个过滤器的订单   
Long count = Order.deleteAll(filter);


#p#副标题#e#

嵌套查询

ActiveJPA答允嵌套过滤参数。这样的话就能更容易地在运行时建设动态查询。譬喻,你获取的订单中,至少要有一个订单项是基于“book”类此外产物建设的。

// 获得至少包括一个book项的所有订单 
Filter filter = new Filter();    
filter.setPageNo(1);    
filter.setPerPage(25);    
filter.addCondition(new Condition("orderItems.product.category",
 Operator.eq, "books");    
List orders = Order.where(filter);

利用荟萃

上面接头的所有CRUD操纵同时可以在荟萃级别执行。将查询范畴配置到荟萃类的用法如下所示:

// 在订单中,按照id查找订单项    
order.collections("orderItems").findById(123L);

// 获得第一个已发货的订单项
order.collections(“orderItems”).first(“status”, “shipped”);

// 获得所有打消的订单项   
order.collections(“orderItems”).where(“status”, “cancelled”);

// 获得荟萃中的所有项   
order.collections(“orderItems”).all();

// 往荟萃中添加一项   
order.collections(“orderItems”).add(orderItem);

// 移除荟萃中的一项   
order.collections(“orderItems”).remove(orderItem);

#p#分页标题#e#

过滤和分页也可以利用到荟萃之中

// 对一个订单中的订单项基于过滤器举办查询并举办分页
Filter filter = new Filter();   
filter.setPageNo(1);    
filter.setPerPage(25);

filter.addCondition(new Condition(“status”, “shipped”);   
order.collections("orderItems").where(filter);

// 在订单中,获得匹配过滤器的订单项的数量

order.collections(“orderItems”).count(filter);

动态更新

ActiveJPA支持对模子的动态更新。在有些场景下这是很有用的,譬喻用户通过欣赏器更新一个表单。你可以通报一个包括属性的map来举办更新,而不是挪用每个属性的setter要领:

// 更新属性    

Map attributes = new HashMap();    
attributes.put("billingAmount", 1000.0);  
order.updateAttributes(attributes);

你也可以更新非原始/非包装范例的域,只需给这些工具通报map即可。以下的样例揭示了更新一个订单的收获地点和账单金额。

// 更新一个订单的收获地点和账单金额

Map attributes = new HashMap();

Map address = new HashMap();

address.put(“city”, “Bangalore”);

address.put(“state”, “Karnataka”);

attributes.put(“shippingAddress”, address);

attributes.put("billingAmount", 1000.0);

order.updateAttributes(attributes);

留意:今朝尚不支持更新list/set/array域,将来的版本将会提供支持。

事务处理惩罚

默认环境下,假如没有事务,ActiveJPA将会为所有的更新操纵启动一个事务,不外你也可以将整个事情单位包装到一个事务之中:

JPAContext context = JPA.instance.getDefaultConfig().getContext();    
context.beginTxn();    
boolean failed = true;    
try {    
 // 你的事情单位置于此处    
failed = false;    
} finally {    
 // 提交或回滚事务    
context.closeTxn(failed);    
}

假如已经存在了外部的事务,那么ActiveJPA将会利用这个事务,可是不会举办提交或回滚。应该由应用来认真封锁该事务。

#p#副标题#e#

测试你的模子

ActiveJPA为TestNG提供了一个根基的测试类,它会将ActiveJPA以挂钩(hook)的方法添加到测试运行时之中。只需让你的测试类扩展自org.activejpa.entity.testng.BaseModelTest类即可。以下为一个样例代码:

public class OrderTest extends BaseModelTest {
     @Test
     public void testCreateOrder() {
       Order order = new Order();
       order.setCustomerEmail("[email protected]");
       ...
       ...
       order.persist();
       Assert.assertEquals(Order.where("customerEmail",
 "[email protected]").get(0), order);
    }
  }
}

利用起步

搭建Maven

ActiveJPA可以以Maven artifact的方法来获取,可以或许很是容易地集成到你的应用之中。只需在你的pom.xml文件中添加如下的maven依赖:

<dependencies>    
<dependency>    
<groupId>org.activejpa</groupId>    
<artifactId>activejpa-core</artifactId>    
<version>0.1.5</version>    
</dependency>    
</dependencies>

<repositories>   
<repository>    
<id>activejpa-repo</id>    
<url>https://raw.github.com/ActiveJpa/activejpa/mvn-repo/releases</url>    
<snapshots>    
<enabled>true</enabled>    
<updatePolicy>always</updatePolicy>    
</snapshots>    
</repository>    
</repositories>

嵌入到你的应用之中

ActiveJPA需要在实体类加载前就嵌入到你的应用之中。假如你利用Tomcat的话,那么ServletContextListener就是做这件事的一个很好的处所。你可以将以下的代码编写到上下文监听器的contextInitialized()要领之中。

// 动态加载Java署理   
ActiveJpaAgentLoader.instance().loadAgent();

// 添加界说在persistence.xml中的耐久化单位,以“order”名举办标识。
persistence.xml应该位于类路径下   
JPA.addPersistenceUnit("order");

// 假如你已经建设了实体打点工场的话,可以将其关联到ActiveJpa上  
// JPA.addPersistenceUnit("order", entityManagerFactory);

与Spring框架集成

将ActiveJPA与Spring这样的框架举办集成是很容易的。大大都的应用城市利用Spring的注解来设置JPA和打点事务。ActiveJPA可以或许以两种方法来举办设置——你可以让它来建设实体打点工场也可以传入一个已存在的工具。在Spring设置JPA的环境下,我们可以利用Spring所建设的实体打点工场。这样就能担保ActiveJPA利用Spring所建设的沟通的毗连和事务,从而提供无缝的集成。

#p#分页标题#e#

以下的代码揭示了如何将ActiveJPA集成到Spring应用之中,这个应用是陈设在servlet容器内里的。它利用了一个自界说的上下文加载监听器,从而将ActiveJPA嵌入到应用之中。需要留意的是,这很雷同与上面的servlet样例,区别在于这里利用了Spring框架的ContextLoaderListener:

public class CustomContextListener extends ContextLoaderListener {
  @Override
  public void contextInitialized(ServletContextEvent event) {
          try {
                    // 在这里动态加载Java署理
                    ActiveJpaAgentLoader.instance().loadAgent();
          } catch (Exception e) {
                    throw new RuntimeException(e);
          }
          super.contextInitialized(event);
          JPA.instance.addPersistenceUnit("default", 
getCurrentWebApplicationContext().getBean(EntityManagerFactory.
class), true);
   }
}

样例应用

在GitHub的ActiveJPA工程页面上有一个示例应用,包括了许多更详细的样例,揭示了Spring-ActiveJPA的集成。

    关键字:

在线提交作业