私のアプリケーションでは、サービス層があります。これは、DAO層を扱う多くのREST Webサービスであり、データベース表を表すエンティティでCRUD操作を実行します。 DAOレイヤーでHibernateを使用しています。私のサービス層のJavaクラスの例は:複雑でメンテナンスの難しいサービス層
@Path("/customers")
public class CustomerService extends SessionUtil implements Service {
public static CustomerDao customerDao = (CustomerDao) context.getBean("customerDAO");
public static CustomerDebtDao customerDebtDao = (CustomerDebtDao) context.getBean("customerDebtDAO");
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<Customer> getAllCustomersService() {
return (ArrayList<Customer>) customerDao.getAllCustomers();
}
@GET
@Path("/{start}/{end}")
@Produces(MediaType.APPLICATION_JSON)
public List<Customer> getCustomerBatchService(@PathParam("start") int start, @PathParam("end") int end) {
ArrayList<Customer> customers = (ArrayList<Customer>) customerDao.getCustomerBatch(start, end);
return customers;
}
@GET
@Path("/count")
@Produces(MediaType.APPLICATION_JSON)
public int getTotalRowCountService() {
return (int) customerDao.getTotalRowCount();
}
@GET
@Path("/{customerId}")
@Produces(MediaType.APPLICATION_JSON)
public Customer getCustomerService(@PathParam("customerId") int customerId) {
Customer customer = (Customer) customerDao.getCustomer(customerId);
return customer;
}
@POST
@Path("/create")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response createCustomerService(Customer customer) {
customerDao.createCustomer(customer);
return response;
}
@DELETE
@Path("/{customerId}")
@Produces(MediaType.APPLICATION_JSON)
public Response deleteCustomerService(@PathParam("customerId") int customerId) {
customerDao.deleteCustomer(customerId);
return response;
}
@PUT
@Path("/{customerId}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response editCustomerService(Customer customer) {
customerDao.editCustomer(customer);
return response;
}
...
}
DAO層の例は次のとおりです。問題は、サービス層では、ある
public class CustomerDaoImpl extends JdbcDaoSupport implements CustomerDao {
@Autowired
private SessionFactory sessionFactory;
@Override
public void createCustomer(Customer customer) {
customer.setCustomerId(getNextCustomerId());
customer.setCreated(new Date());
customer.setCustomerId(getNextCustomerId());
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(customer);
try {
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
}
@Override
public void editCustomer(Customer customer) {
Session session = sessionFactory.openSession();
session.beginTransaction();
session.update(customer);
try {
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
}
}
、私は時々に複数の呼び出しを行いますDAOレイヤーを呼び出すことができます。また、各呼び出しは1つのHibernateトランザクションで処理されるため、1つの操作が失敗すると他の操作は実行されません。たとえば、請求書を作成して顧客の債務を更新するようにコードに指示しています。私はそれが請求書を作成し、債務を更新していないことが分かりました。私はいくつかの本を調べて、すべての操作を単一のトランザクションで処理し、何かが失敗した場合にそれらをロールバックする必要があると言いました。私はこれをやろうとしていますが、それは私がDAO層全体をほとんど取り除く原因となり、サービス層は巨大で、読めなくなり、維持不能になっています。次のように例を示します。
既存のコメントに加えて@POST
@Path("/create")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response createSalesInvoiceLineService(SalesInvoiceLine salesInvoiceLine) {
Session session = sessionFactory.openSession();
session.beginTransaction();
// prepare sales invoice line object
salesInvoiceLine = salesInvoiceLineDao.createSalesInvoiceLine(salesInvoiceLine);
session.save(salesInvoiceLine);
updateSalesInvoiceAmountForCreate(salesInvoiceLine, session);
// update stock
Stock stock = stockDao.getStockByProduct(salesInvoiceLine.getProductId());
stock.setQuantity(stock.getQuantity().subtract(salesInvoiceLine.getQuantity()));
stockDao.editStock(stock);
session.save(stock);
// update debt
SalesInvoice salesInvoice = salesInvoiceDao.getSalesInvoice(salesInvoiceLine.getSalesInvoiceId(), session);
List<CustomerDebt> customerDebtList = customerDebtDao.getCustomerDebtByCustomerId(salesInvoice.getCustomerId());
CustomerDebt customerDebt = customerDebtList.get(0);
customerDebt.setAmount(customerDebt.getAmount().add(salesInvoiceLine.getLineAmount()));
Date date = new Date();
java.sql.Date currentDate = new java.sql.Date(date.getTime());
customerDebt.setUpdateDate(currentDate);
customerDebtDao.editCustomerDebt(customerDebt);
session.update(customerDebt);
try {
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
session.close();
}
return response;
}
...他のトランスポート層(SOAP、...)に暴露され、テストすることができ、それは、コードを作業し、ちょうどあなたがそのすべてを逃した – SteelToe
最適化が必要とされるコードレビューでこれを投稿してくださいSpringは、依存性注入、および自動の宣言的なトランザクション管理に役立ちます。 Springのドキュメントを実際に読んでください。トランザクションサービスのために必要なのは、 '@ Transactional'アノテーションだけです。 DAOインスタンスを取得する必要があるのは、サービスコンストラクタまたは非静的フィールドの '@ Autowired'です。また、Hibernateエンティティが管理されているという事実も見逃しました。セッションから取得したエンティティでsave()を呼び出すことは無意味です。そして、BTW、save()は新しい永続インスタンスを作成するためのものです。 –
DAOからArrayListに渡したリストをキャストすることはまったく役に立たず、実際にコードを失敗させる可能性があります。 –