Thứ Bảy, 7 tháng 1, 2017

Criteria API

I.Định Nghĩa

Trước khi các ngôn ngữ như JP QL đã trở thành tiêu chuẩn, phương pháp phổ biến nhất để xây dựng các truy vấn trongnhiều nhà cung cấp bền bỉ đã được thông qua một API lập trình. Khung truy vấn trong EclipseLink, cho ví dụ là cách hiệu quả nhất để thực sự mở khóa toàn bộ sức mạnh của công cụ truy vấn của nó. Và, ngay cả với các đời của JP QL, API lập trình đã vẫn còn được sử dụng để cung cấp cho truy cập vào các tính năng chưa được hỗ trợ bởi ngôn ngữ truy vấn chuẩn.

JPA 2.0 giới thiệu một tiêu chuẩn API mới để xây dựng các truy vấn chuẩn hóa nhiều tính năng mà tồn tại trong các sản phẩm kiên trì độc quyền chương trình. Không chỉ là một bản dịch nghĩa đen JP QL để giao diện lập trình, nó cũng thông qua thực hành lập trình tốt nhất của các mô hình độc quyền, chẳng hạn như phương pháp xâu chuỗi, và tận dụng đầy đủ các tính năng ngôn ngữ lập trình Java.

II.Chi Tiết
SELECT e FROM Employee e WHERE e.name = ‘John Smith’
Và đây là các truy vấn tương đương xây dựng bằng cách sử dụng tiêu chí API :
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery c = cb.createQuery(Employee.class);
Root emp = c.from(Employee.class);
c.select(emp).where(cb.equal(emp.get(“name”), “John Smith”));
  • Search employee sử dung jpql
@Stateless
public class SearchService {
@PersistenceContext(unitName = "EmployeeHR")
EntityManager em;
public List findEmployees(String name, String deptName,
String projectName, String city) {
StringBuffer query = new StringBuffer();
query.append("SELECT DISTINCT e ");
query.append("FROM Employee e LEFT JOIN e.projects p ");
query.append("WHERE ");
List criteria = new ArrayList();
if (name != null) {
criteria.add("e.name = :name");
}
if (deptName != null) {
criteria.add("e.dept.name = :dept");
}
if (projectName != null) {
criteria.add("p.name = :project");
}
if (city != null) {
criteria.add("e.address.city = :city");
}
if (criteria.size() == 0) {
throw new RuntimeException("no criteria");
}
for (int i = 0; i < criteria.size(); i++) {
if (i > 0) {
query.append(" AND ");
}
query.append(criteria.get(i));
}
Query q = em.createQuery(query.toString());
if (name != null) {
q.setParameter("name", name);
}
if (deptName != null) {
q.setParameter("dept", deptName);
}
if (projectName != null) {
q.setParameter("project", projectName);
}
if (city != null) {
q.setParameter("city", city);
}
return (List) q.getResultList();
}
}
  • Search Employee sử dụng  Criteria API
@Stateless
public class SearchService {
@PersistenceContext(unitName = "EmployeeHR")
EntityManager em;
public List findEmployees(String name, String deptName,
String projectName, String city) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery c = cb.createQuery(Employee.class);
Root emp = c.from(Employee.class);
c.select(emp);
c.distinct(true);
Join<Employee, Project> project
= emp.join("projects", JoinType.LEFT);
List criteria = new ArrayList();
if (name != null) {
ParameterExpression p
= cb.parameter(String.class, "name");
criteria.add(cb.equal(emp.get("name"), p));
}
if (deptName != null) {
ParameterExpression p
= cb.parameter(String.class, "dept");
criteria.add(cb.equal(emp.get("dept").get("name"), p));
}
if (projectName != null) {
ParameterExpression p
= cb.parameter(String.class, "project");
criteria.add(cb.equal(project.get("name"), p));
}
if (city != null) {
ParameterExpression p
= cb.parameter(String.class, "city");
criteria.add(cb.equal(emp.get("address").get("city"), p));
}
if (criteria.size() == 0) {
throw new RuntimeException("no criteria");
} else if (criteria.size() == 1) {
c.where(criteria.get(0));
} else {
c.where(cb.and(criteria.toArray(new Predicate[0])));
}
TypedQuery q = em.createQuery(c);
if (name != null) {
q.setParameter("name", name);
}
if (deptName != null) {
q.setParameter("dept", deptName);
}
if (project != null) {
q.setParameter("project", projectName);
}
if (city != null) {
q.setParameter("city", city);
}
return q.getResultList();
}
}
JP QL ClauseCriteria API InterfaceMethod
SELECTCriteriaQueryselect()
Subqueryselect()
FROMAbstractQueryfrom()
WHEREAbstractQuerywhere()
ORDER BYCriteriaQueryorderBy()
GROUP BYAbstractQuerygroupBy()
HAVINGAbstractQueryhaving()
III.Đánh Giá

Các API Tiêu chuẩn được sử dụng để xác định các truy vấn cho các entity và persistent state của nó bằng cách tạo ra query-defining objects. Tiêu chuẩn truy vấn được viết bằng ngôn ngữ lập trình API Java, là typesafe, và linh hoạt. truy vấn như vậy làm việc được với bất kể là data store.

IV.Tổng Kết

Trong điều tra các API tiêu chuẩn, chúng ta bắt đầu với khái niệm JP QL và tìm cách vẽ song song giữa các ngôn ngữ truy vấn và các API tiêu chí. Chúng tôi nhìn vào cách xây dựng từng điều khoản của một truy vấn với các API tiêu chuẩn và giải quyết một số vấn đề phức tạp hơn mà các nhà phát triển gặp phải.

Chúng ta có thể tìm hiểu các API metamodel và biết làm thế nào nó có thể được sử dụng để tạo các truy vấn mạnh mẽ đánh máy với các API tiêu chí. Chúng tôi nhìn vào lập trình với các API metamodel sử dụng cả hai giao diện thời gian chạy và thông qua các lớp học tạo ra một thực metamodel kinh điển.

Cuối cùng chúng tôi đã thảo luận về những ưu điểm của phương pháp tiếp cận khác nhau để truy vấn xây dựng sử dụng JP QL,

API là rất khác nhau từ các ngôn ngữ truy vấn JP QL, ngữ nghĩa cơ bản gần như giống nhau và chuyển đổi giữa hai là tương đối dễ dàng một khi bạn nhận được hang của API mã hóa mẫu.

Query Language

I.Định Nghĩa

JPQL không phải là SQL. Mặc dù những điểm tương đồng giữa hai ngôn ngữ về từ khóa và cấu trúc tổng thể, có rất khác biệt quan trọng. Cố gắng viết JPQL như thể nó là SQL là cách dễ nhất để nhận được thất vọng với ngôn ngữ. Các điểm tương đồng giữa hai ngôn ngữ là có chủ ý (cho các nhà phát triển một cảm giác về những gì JP QL có thể thực hiện được), nhưng bản chất hướng đối tượng của JPQL đòi hỏi một loại khác nhau về cách nghĩ.


JPQL là ngôn ngữ Java Persistence Truy vấn định nghĩa trong đặc tả JPA. Nó được sử dụng để tạo ra các truy vấn đối với các đơn vị để lưu trữ trong một cơ sở dữ liệu quan hệ. JPQL được phát triển dựa trên cú pháp SQL. Nhưng nó sẽ không ảnh hưởng đến các cơ sở dữ liệu trực tiếp. JPQL có thể lấy thông tin hoặc dữ liệu sử dụng mệnh đề SELECT, có thể làm cập nhật số lượng lớn bằng khoản UPDATE và DELETE khoản. EntityManager.createQuery () API sẽ hỗ trợ cho các truy vấn ngôn ngữ.

II.Chi Tiết


  • Constructor Expressions
SELECT NEW example.EmployeeDetails(e.name, e.salary, e.department.name) FROM Employee e
  • Literal syntax is also similar to SQL (see the “Literals” section).
Operator precedence is as follows:
1. Navigation operator (.)
2. Unary +/–
3. Multiplication (*) and division (/)
4. Addition (+) and subtraction (–)
5. Comparison operators: =, >, >=, <, <=, <>, [NOT] BETWEEN, [NOT] LIKE, [NOT] IN, IS [NOT] NULL, IS [NOT] EMPTY, [NOT] MEMBER [OF] 6. Logical operators (AND, OR, NOT)
  • BETWEEN Expressions
SELECT e FROM Employee e WHERE e.salary BETWEEN 40000 AND 45000
  • LIKE Expressions
SELECT d FROM Department d WHERE d.name LIKE '__Eng%'
  • Subqueries 
SELECT e FROM Employee e WHERE e.salary = (SELECT MAX(emp.salary) FROM Employee emp)
  • IN Expressions
SELECT e FROM Employee e WHERE e.address.state IN ('NY', 'CA')
  • Collection Expressions
SELECT e FROM Employee e WHERE e.directs IS NOT EMPTY
  • EXISTS Expressions
SELECT e FROM Employee e WHERE NOT EXISTS (SELECT p FROM e.phones p WHERE p.type = 'Cell')
  • ANY, ALL, and SOME Expressions
SELECT e FROM Employee e WHERE e.directs IS NOT EMPTY AND e.salary < ALL (SELECT d.salary FROM e.directs d)
  • Scalar Expressions
Một biểu thức vô hướng là một giá trị ký tự, chuỗi số học, biểu hiện chức năng, loại biểu hiện, hoặc trường hợp biểu hiện mà giải quyết đến một giá trị vô hướng duy nhất. Nó có thể được sử dụng trong mệnh đề SELECT để định dạng dự
trường trong truy vấn báo cáo hoặc là một phần của biểu thức điều kiện trong WHERE hoặc HAVING khoản của một truy vấn.

Truy vấn con mà giải quyết cho các giá trị vô hướng cũng được coi là biểu hiện vô hướng, nhưng có thể được sử dụng chỉ
khi soạn các tiêu chí trong mệnh đề WHERE của truy vấn. Truy vấn con không bao giờ có thể được sử dụng trong SELECT
  • Literals
{d ‘yyyy-mm-dd’}                               e.g. {d ‘2009-11-05’}
{t ‘hh-mm-ss’}                                    e.g. {t ’12-45-52′}
{ts ‘yyyy-mm-dd hh-mm-ss.f’}    e.g. {ts ‘2009-11-05 12-45-52.325’}
  • ORDER BY Clause
SELECT e FROM Employee e ORDER BY e.name DESC
Multiple expressions can also be used to refine the sort order:
SELECT e, d FROM Employee e JOIN e.department d ORDER BY d.name, e.name DESC
  • Aggregate Queries
Aggregate Functions Five aggregate functions can be placed in the select clause of a query: AVG, COUNT, MAX, MIN, and SUM.
  • GROUP BY Clause
SELECT d.name, COUNT(e) FROM Department d JOIN d.employees e GROUP BY d.name
  • HAVING Clause
SELECT e, COUNT(p) FROM Employee e JOIN e.projects p GROUP BY e HAVING COUNT(p) >= 2
  • Update Queries
UPDATE Employee e SET e.salary = 60000 WHERE e.salary = 55000
  • Delete Queries
DELETE FROM Employee e WHERE e.department IS NULL
III.Đánh Giá
JPQL là một truy vấn di động ngôn ngữ được thiết kế để kết hợp các cú pháp và ngữ nghĩa truy vấn đơn giản của SQL với các biểu cảm của một hướng đối tượng ngôn ngữ biểu thức. Truy vấn được viết bằng ngôn ngữ này có thể được biên dịch để portably SQL trên tất cả các máy chủ cơ sở dữ liệu lớn.

IV.Kết
Ta đã nhìn vào rất nhiều các loại truy vấn và cú pháp của họ. Lịch sử của các ngôn ngữ, từ gốc rễ của nó trong EJB 2.0 đặc điểm kỹ thuật cho các cải tiến quan trọng được giới thiệu bởi JPA.
Trong phần trên các truy vấn lựa chọn, chúng ta khám phá từng khoản truy vấn và từng bước xây dựng được nhiều hơn truy vấn phức tạp như cú pháp đầy đủ đã được mô tả. Chúng ta thảo luận các biến dạng và đường dẫn biểu thức, được sử dụng để điều hướng thông qua các mô hình miền trong các biểu thức truy vấn. Chúng ta cũng nhìn tại nhiều biểu thức điều kiện và vô hướng được hỗ trợ bởi ngôn ngữ.
Trong cuộc thảo luận của chúng ta về các truy vấn tổng hợp chúng ta giới thiệu các nhóm và lọc bổ sung khoản mở rộng chọn câu truy vấn. Chúng ta cũng đã chứng minh các chức năng tổng hợp khác nhau.
Trong các phần trên cập nhật và xóa các truy vấn, chúng ta mô tả cú pháp đầy đủ để cập nhật hàng loạt và xóabáo cáo, người có hành vi gian chạy được mô tả trong các chương trước.

Using Queries

Đối với hầu hết các ứng dụng doanh nghiệp, nhận được dữ liệu trong cơ sở dữ liệu là ít nhất cũng quan trọng như khả năng để đưa dữ liệu mới. Từ tìm kiếm để phân loại, phân tích, và kinh doanh thông minh, hiệu quả chuyển động dữ liệu từ cơ sở dữ liệu cho các ứng dụng và trình bày nó cho người dùng là một phần thường xuyên của doanh nghiệp phát triển. Làm như vậy đòi hỏi phải có khả năng phát hành các truy vấn số lượng lớn so với cơ sở dữ liệu và giải thích kết quả cho các ứng dụng. Mặc dù ngôn ngữ cấp cao và các khuôn khổ hiện có trong nhiều trường hợp đã cố gắng để ngăn cách các nhà phát triển từ các tác vụ xử lý các truy vấn cơ sở dữ liệu ở cấp độ SQL, nó có thể là công bằng để nói rằng hầu hết các nhà phát triển doanh nghiệp đã làm việc với ít nhất một phương ngữ SQL tại một số điểm trong sự nghiệp của họ.

 Object-relational mapping bổ sung một mức độ phức tạp nhiệm vụ này. Hầu hết thời gian, các phát triển sẽ muốn các kết quả chuyển đổi cho các đối tượng để các kết quả truy vấn có thể được sử dụng trực tiếp ứng dụng logic. Tương tự như vậy, nếu mô hình miền đã được trừu tượng hóa từ mô hình vật lý thông qua đối tượng-quan hệ lập bản đồ, nó làm cho cảm giác cũng truy vấn trừu tượng đi từ SQL, mà không phải là chỉ gắn với các mô hình vật lý nhưng cũng khó để cổng giữa các nhà cung cấp. May mắn thay, như chúng ta sẽ thấy, JPA có thể xử lý một tập hợp đa dạng các yêu cầu truy vấn.

JPA hỗ trợ hai phương pháp để thể hiện các truy vấn để lấy các thực thể và liên tục dữ liệu khác từ cơ sở dữ liệu: ngôn ngữ truy vấn và các API tiêu chí. Ngôn ngữ truy vấn chính là Java.Ngôn ngữ truy vấn Persistence (JP QL), một ngôn ngữ truy vấn cơ sở dữ liệu độc lập mà hoạt động trên mô hình thực thể hợp lý như trái ngược với các mô hình dữ liệu vật lý. Truy vấn cũng có thể được thể hiện trong SQL để tận dụng các cơ sở dữ liệu nằm bên dưới. Các API tiêu chí cung cấp một phương pháp khác để xây dựng các truy vấn dựa trên Java objects thay vì các chuỗi truy vấn.


I.Named Query Definition

truy vấn có tên là một công cụ mạnh mẽ cho việc tổ chức định nghĩa truy vấn và cải thiện ứng dụng hiệu suất. Một truy vấn có tên được xác định bằng cách sử dụng chú thích @NamedQuery, có thể được đặt trên Định nghĩa lớp cho bất kỳ thực thể. Các chú thích định nghĩa tên của các truy vấn, cũng như các văn bản truy vấn.
@NamedQuery(name="findSalaryForNameAndDepartment", query="SELECT e.salary " + "FROM Employee e " + "WHERE e.department.name = :deptName AND " + " e.name = :empName")
Nhiều queries trong 1 class entity
@NamedQueries({ @NamedQuery(name="Employee.findAll", query="SELECT e FROM Employee e"), @NamedQuery(name="Employee.findByPrimaryKey", query="SELECT e FROM Employee e WHERE e.id = :id"), @NamedQuery(name="Employee.findByName", query="SELECT e FROM Employee e WHERE e.name = :name") })
  • Chạy 1 named Query
@Stateless
public class EmployeeServiceBean implements EmployeeService {
@PersistenceContext(unitName = “EmployeeService”)
EntityManager em;
public Employee findEmployeeByName(String name) {
return em.createNamedQuery("Employee.findByName", Employee.class).setParameter("name", name).getSingleResult();
} // ... 
}

Parameter Types

@NamedQuery(name="findEmployeesAboveSal", query="SELECT e " + "FROM Employee e " + "WHERE e.department = :dept AND " + " e.salary > :sal")
  • Cách gán dữ liệu
@Stateless
public class EmployeeServiceBean implements EmployeeService {
@PersistenceContext(unitName = "EmployeeService")
EntityManager em;
public List findEmployeesAboveSal(Department dept,
long minSal) {
return em.createNamedQuery("findEmployeesAboveSal",
Employee.class)
.setParameter("dept", dept)
.setParameter("sal", minSal)
.getResultList();
}
// ...
}
  • Gán dữ liệu kiểu Date
@Stateless
public class EmployeeServiceBean implements EmployeeService {
@PersistenceContext(unitName = "EmployeeService")
EntityManager em;
public List findEmployeesHiredDuringPeriod(Date start,
Date end) {
return em.createQuery("SELECT e "
+ "FROM Employee e "
+ "WHERE e.startDate BETWEEN ?1 AND ?2",
Employee.class)
.setParameter(1, start, TemporalType.DATE)
.setParameter(2, end, TemporalType.DATE)
.getResultList();
}
// ...
}

II.Đánh giá

JavaBeans Query Language (EJBQL) cho phép phát triển viết các công cụ tìm xách tay và chọn phương pháp cho entity bean container quản lý. Dựa trên một tập hợp con nhỏ của SQL, nó giới thiệu một cách để điều hướng qua các mối quan hệ thực thể cả để chọn dữ liệu và để lọc các kết quả. Thật không may, nó đặt những hạn chế nghiêm ngặt về cấu trúc của các truy vấn, hạn chế kết quả hoặc là một thực thể duy nhất hoặc một lĩnh vực kéo dài từ một thực thể. Bên tham gia giữa các thực thể là có thể, nhưng sử dụng một ký hiệu kỳ lạ. Việc phát hành ban đầu thậm chí còn không hỗ trợ phân loại.

III.Kết

Ta có cái nhìn tổng quan về các tính năng chính JPQL cho các nhà phát triển đã có kinh nghiệm với SQL hoặc EJB QL. Trong các cuộc thảo luận về việc thực hiện các truy vấn, ta giới thiệu các phương pháp để xác định các truy vấn cả
động trong thời gian chạy và tĩnh như một phần của đơn vị bền vững siêu dữ liệu. Chúng ta nhìn vào các truy vấn và TypedQuery giao diện và các loại kết quả truy vấn có thể sử dụng JP QL. Chúng ta cũng xem xét tham số ràng buộc, các chiến lược để xử lý bộ kết quả lớn và làm thế nào để đảm bảo rằng các truy vấn trong các giao dịch với dữ liệu biến đổi hoàn toàn thành công.

Trong phần về cập nhật hàng loạt và xóa chúng nhìn như thế nào để thực hiện các loại truy vấn và làm thế nào để đảm bảo rằng chúng được sử dụng một cách an toàn bởi các ứng dụng. Chúng ta cung cấp chi tiết về cách kiên trì
nhà cung cấp hợp đồng với số lượng lớn các hoạt động và tác động mà họ có trong bối cảnh kiên trì hoạt động.

Chúng ta kết thúc cuộc thảo luận của chúng ta về tính năng truy vấn với một cái nhìn gợi ý truy vấn. Chúng tađã cho thấy làm thế nào để xác định
gợi ý và cung cấp một ví dụ sử dụng gợi ý hỗ trợ bởi việc thực hiện JPA tham khảo.

Cuối cùng, chúng ta tóm tắt quan điểm của chúng ta về thực hành tốt nhất liên quan đến truy vấn, nhìn vào các truy vấn được đặt tên,
chiến lược khác nhau cho các loại truy vấn khác nhau, cũng như các chi tiết thực hiện cần được hiểu cho các nhà cung cấp khác nhau kiên trì.

Entity Manager

I.Định Nghĩa

1.EntityManage
EntityManager là một giao diện (interface) cung cấp các API cho việc tương tác với các Entity. Một số chức năng cơ bản của EntityManager như:

  • Persist: phương thức này dùng để lưu một thực thể mới tạo vào cơ sở dữ liệu
  • Merge: dùng để cập nhật trạng thái của entity vào cơ sở dữ liệu.
  • Remove: xóa một thể hiện của entity.

2.Persistence Contexts

Persistence Contexts là tập hợp các entity và các entity này chính là các managed. EntityManager kiểm soát lifecycle và có thể truy cập tài nguyên kho dữ liệu. Khi Persistence Contexts kết thúc thì các entity managed trở thành các detached. Các detached này sẽ không còn chịu sự kiểm soát của EntityManager và đồng thời cũng mất quyền truy cập vào cơ sở dữ liệu. Thường thì các detached sẽ được gọi và query lại thành một EntityManager mới với các tính năng tương tự.

II. Áp Dụng

@Stateless
public class ProjectServiceBean implements ProjectService {
@PersistenceContext(unitName = "EmployeeService")
EntityManager em;
public void assignEmployeeToProject(int empId, int projectId) {
Project project = em.find(Project.class, projectId);
Employee employee = em.find(Employee.class, empId);
project.getEmployees().add(employee);
employee.getProjects().add(project);
}
// ...
}

1.Extended

@Stateful
public class DepartmentManagerBean implements DepartmentManager {
@PersistenceContext(unitName = "EmployeeService",
type = PersistenceContextType.EXTENDED)
EntityManager em;
Department dept;
public void init(int deptId) {
dept = em.find(Department.class, deptId);
}
public void setName(String name) {
dept.setName(name);
}
public void addEmployee(int empId) {
Employee emp = em.find(Employee.class, empId);
dept.getEmployees().add(emp);
emp.setDepartment(dept);
}
// ...
@Remove
public void finished() {
}
}
2.Application
public class EmployeeClient {
public static void main(String[] args) {
EntityManagerFactory emf
= Persistence.createEntityManagerFactory("EmployeeService");
EntityManager em = emf.createEntityManager();
List emps = em.createQuery("SELECT e FROM Employee e").getResultList();
for (Employee e : emps) {
System.out.println(e.getId() + ", " + e.getName());
}
em.close();
emf.close();
}
}
3.In Controller Servlet
public class LoginServlet extends HttpServlet {
@PersistenceUnit(unitName = "EmployeeService")
EntityManagerFactory emf;
protected void doPost(HttpServletRequest request,
HttpServletResponse response) {
String userId = request.getParameter("user");
// check valid user
EntityManager em = emf.createEntityManager();
try {
User user = em.find(User.class, userId);
if (user == null) {
// return error page
// ...
}
} finally {
em.close();
}
// ...
}
}
Các method() để tháo tác với database (CRUD):
  • persist – tạo mới một Employee
  • merge – thay đổi một Employee

III.Tổng Hợp

Ta có thể thấy EntityManager có thể được sử dụng bằng nhiều cách khác nhau để phù hợp với yêu cầu ứng dụng cần. Chúng ta có thể tìm hiểu về các thuật ngữ cốt lõi của JPA và tìm hiểu thêm về Persistence Contexts. Sau đó bao phủ ba loại khác nhau của EntityManager: giao dịch có phạm vi, mở rộng, và ứng dụng quản lý. Chúng ta có thấy các thiết kế được tạo ra để giải quyết các vấn đề mà ứng dụng yêu cầu như thế nào.

IV.Đánh Giá

EntityManager và  Persistence Contexts có quan hệ mật thiết tối quan trọng trong bài toán. Chúng được tạo ra để bổ sung và hỗ trợ lẫn nhau để có thể giải quyết các vấn đề, yêu cầu mà ứng dụng cần từ cơ bản đến phức tạp. Dựa vào các thiết kế này ta có thể giải quyết hầu hết các bài toán ứng dụng đưa ra trên nền tảng JavaEE.