首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

ActiveJPA:基於 JPA 的 Active Record 模式實現,消除 DAO 層樣板代碼

     編輯:Java 相關知識

ActiveJPA 將 Martin Fowler 的 Active Record 模式帶入 Java JPA 生態,讓實體類直接繼承 Model 即擁有 CRUD 能力,無需額外 DAO/Repository 類。支援 Hibernate、EclipseLink、OpenJPA 等所有 JPA 實現。

快速開始

1. 實體類轉換


@Entity
public class Order extends Model {  // 僅需繼承 Model
    @Id @GeneratedValue Long id;
    String customerEmail;
    String status;
    BigDecimal billingAmount;
    // ... 其他欄位、關聯
}

2. Maven 依賴


<dependency>
    <groupId>org.activejpa</groupId>
    <artifactId>activejpa-core</artifactId>
    <version>0.1.5</version>
</dependency>
<repository>
    <id>activejpa-repo</id>
    <url>https://raw.github.com/ActiveJpa/activejpa/mvn-repo/releases</url>
</repository>

3. 初始化(ServletContextListener)


public class AppInitializer implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent e) {
        ActiveJpaAgentLoader.instance().loadAgent();  // 載入 Java Agent
        JPA.addPersistenceUnit("order");  // 對應 persistence.xml
    }
}

核心 CRUD API

操作API 範例
主鍵查詢Order.findById(12345L)
條件查詢Order.where("customerEmail", "a@b.com", "status", "shipped")
首筆/唯一Order.first(...) / Order.one(...)
全表查詢Order.all()
存在性檢查Order.exists(1234L)
持久化order.persist()
刪除order.delete()
刷新/合併order.refresh() / order.merge()

進階查詢:Filter 與分頁


Filter filter = new Filter();
filter.setPageNo(1);
filter.setPerPage(25);
filter.addCondition(new Condition("customerEmail", Operator.eq, "a@b.com"));
filter.addCondition(new Condition("billingAmount", Operator.gt, 1000.00));

List<Order> orders = Order.where(filter);
Long count = Order.count(filter);
Order.deleteAll(filter);  // 批量刪除

巢狀關聯查詢


// 訂單項包含產品分類為 books 的訂單
Filter filter = new Filter();
filter.addCondition(new Condition("orderItems.product.category", Operator.eq, "books"));
List<Order> orders = Order.where(filter);

集合操作


// 訂單項集合操作
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(newOrderItem);
order.collections("orderItems").remove(orderItem);

// 集合分頁
Filter f = new Filter(); f.setPageNo(1); f.setPerPage(10);
f.addCondition(new Condition("status", Operator.eq, "shipped"));
order.collections("orderItems").where(f);
order.collections("orderItems").count(f);

動態屬性更新


// 簡單屬性
Map<String, Object> attrs = new HashMap<>();
attrs.put("billingAmount", 1000.0);
order.updateAttributes(attrs);

// 巢狀物件
Map<String, Object> attrs = new HashMap<>();
Map<String, Object> addr = new HashMap<>();
addr.put("city", "Bangalore"); addr.put("state", "Karnataka");
attrs.put("shippingAddress", addr);
attrs.put("billingAmount", 1000.0);
order.updateAttributes(attrs);

事務控制


JPAContext ctx = JPA.instance.getDefaultConfig().getContext();
ctx.beginTxn();
try {
    // 業務邏輯
    ctx.closeTxn(false);  // 提交
} catch (Exception e) {
    ctx.closeTxn(true);   // 回滾
    throw e;
}

Spring 整合


public class CustomContextListener extends ContextLoaderListener {
    @Override
    public void contextInitialized(ServletContextEvent e) {
        ActiveJpaAgentLoader.instance().loadAgent();
        super.contextInitialized(e);
        JPA.instance.addPersistenceUnit("default", 
            getCurrentWebApplicationContext().getBean(EntityManagerFactory.class), true);
    }
}

測試支援


public class OrderTest extends BaseModelTest {  // TestNG 基類
    @Test
    public void testCreateOrder() {
        Order order = new Order();
        order.setCustomerEmail("a@b.com");
        order.persist();
        Assert.assertEquals(Order.where("customerEmail", "a@b.com").get(0), order);
    }
}

優缺點評估

優點缺點/注意
消除 DAO 層樣板代碼耦合持久化邏輯於實體,違反純粹 DDD
語法簡潔、開發效率高複雜查詢仍需 JPQL/Criteria
支援所有 JPA 實現Java Agent 需啟動參數 -javaagent
動態屬性更新適合表單綁定集合/陣列屬性更新尚不支援
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved