Trong các phần trước, Ban biên tập nội dung SmartJob tập trung vào các câu hỏi Java core. Để tránh sự nhàm chán với những chủ đề mang tính căn bản, nền tảng của core Java, phần 4 sẽ nói về tương tác giữa ứng dụng Java với cơ sở dữ liệu quan hệ.
Nhà tuyển dụng: JDBC là gì?
Ứng viên: JDBC là viết tắt của Java Database Connectivity, cung cấp các API (Application Programming Interface: Giao diện lập trình ứng dụng) để truy cập, tương tác (Ghi, xóa, sửa, thêm, tìm kiếm) trên cơ sở dữ liệu quan hệ. JDBC hỗ trợ cơ sở dữ liệu quan hệ (Cơ sở dữ liệu tuân thủ SQL – Structed Query Language: Ngôn ngữ truy vấn có cấu trúc).
Nhà tuyển dụng: ORM là gì?
Ứng viên: ORM là viết tắt của Object-Relation Mapping. Tạm dịch là Ánh xạ Đối tượng-Quan hệ. Một cơ chế móc nối đối tượng (Object) trong mã nguồn Java với các bảng, bản ghi, trường dữ liệu trong Hệ quản trị cơ sở dữ liệu quan hệ.
Em được biết trong công nghệ PHP có Doctrine. Trong Java có EclipseLink, MyBatis, Hibernate. Trong C# có NHibernate. Trong Python có SQLAlchemy. Đó là các ví dụ về framework hỗ trợ cơ chế ORM.
Nhà tuyển dụng: HQL là gì?
Ứng viên: HQL là viết tắt của Hibernate Query Language (Ngôn ngữ truy vấn dùng trong framework Hibernate), có nhiều điểm tương đồng với SQL (Structed Query Language: Ngôn ngữ truy vấn có cấu trúc). HQL không phụ thuộc vào Hệ quản trị cơ sở dữ liệu (DBMS: Database Management System) sử dụng, dù là MySQL, Oracle, hay Microsoft SQLServer. HQL dùng trong lập trình lập trình hướng đối tượng, nằm bên trong mã nguồn ứng dụng Java.
Nhà tuyển dụng: Kể tên một số framework ORM trong Java?
Ứng viên: Hibernate, TopLink, MyBatis.
Nhà tuyển dụng: Làm thế nào để Hibernate hiển thị câu lệnh SQL tường minh trong màn hình console khi Run hoặc debug ứng dụng?
Ứng viên: Trong file hibernate.cfg.xml, đặt thêm thuộc tính:
1
|
<span style=“color: #333333;”><code class=“java”><property name=“show_sql”>true</property></code></span>
|
Nếu muốn cấu hình một cách tinh tế hơn, có thể làm như sau với hibernate.cfg.xml
1
2
3
|
<span style=“color: #333333;”><code class=“java”><property name=“show_sql”>true</property>
<property name=“format_sql”>true</property>
<property name=“use_sql_comments”>true</property></code></span>
|
Nhà tuyển dụng: Trong Hibernate, có 3 kiểu tạo câu lệnh truy vấn là: HQL (Hibernate Query Language), Named query và Criteria. Cho biết cơ chế hoạt động? Khi nào thì dùng HQL, khi nào dùng Named query, khi nào dùng Criteria?
Ứng viên: Nói chung, Criteria sẽ thích hợp cho các truy vấn tìm kiếm. Named query thích hợp cho các câu truy vấn ít thay đổi và gọi đến rất nhiều lần. HQL thường được dùng nhiều hơn cả (cũng do có cú pháp gần tương tự như SQL) dùng được trong tất cả các tình huống.
Criteria là một API nhằm đơn giản hóa việc lấy về các thực thể (entities) nhờ việc thêm các tiêu chí tìm kiếm vào đối tượng (object) Criterion. Đây là cách tiếp cận rất thuận tiện cho các chức năng như trên màn hình tìm kiếm nhiều điều kiện.
Bạn hãy hình dung màn hình tìm việc của SmartJob. Có 4 tiêu chí tìm kiếm là: từ khóa, địa điểm, mức kinh nghiệm, mức lương. Trong ngữ cảnh này, Criteria là cách tốt nhất để tạo truy vấn (tối ưu hơn so với dùng HQL và named query).
Một ứng viên đưa ra tiêu chí tìm kiếm như sau: Tìm cho tôi tất cả các công việc liên quan đến Java tại Hà Nội, yêu cầu từ 2 năm kinh nghiệm trở lên và mức lương tối thiểu là $300? Thì truy vấn Hibernate sử dụng Criteria sẽ là:
1
2
3
4
5
6
7
|
<span style=“color: #333333;”><code class=“java”> List jobs = session.createCriteria(Job.class)
.add( Restrictions.like(“title”, “java”) )
.add( Restrictions.like(“location”, “Hanoi”) )
.add( Restrictions.like(“experienceMin”, “2”) )
.add( Restrictions.like(“salaryMin”, “300”) )
.addOrder( Order.desc(“updateTime”) )
.list();</code></span>
|
Nhà tuyển dụng: Hibernate có hỗ trợ việc tạo truy vấn từ SQL thuần không?
Ứng viên: Hibernate có hỗ trợ việc truy vấn dùng cú pháp SQL thuần. Sử dụng phương thức Session.createSQLQuery() .
Ví dụ: Tìm các công việc tại công ty DCV?
1
2
3
4
5
6
|
<span style=“color: #333333;”><code class=“java”>Query query = session.createSQLQuery(
“SELECT * from job j WHERE j.company_name = :companyName”)
.addEntity(Job.class)
.setParameter(“companyName”, “DCV”);
List result = query.list();</code></span>
|
Nhà tuyển dụng: Nếu cấu hình trong hibernate.cfg.xml như sau?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<span style=“color: #333333;”><code class=“java”><?xml version=“1.0” encoding=“UTF-8”?>
<!DOCTYPE hibernate–configuration PUBLIC “-//Hibernate/Hibernate Configuration DTD 3.0//EN” “http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd”>
<hibernate–configuration>
<session–factory>
<property name=“hibernate.dialect”>org.hibernate.dialect.OracleDialect</property>
<property name=“hibernate.connection.driver_class”>oracle.jdbc.OracleDriver</property>
<property name=“hibernate.connection.url”>jdbc:oracle:thin:@10.10.1.142:1521:foo</property>
<property name=“hibernate.connection.username”>smart_job</property>
<property name=“hibernate.connection.password”>12345678</property>
<property name=“hibernate.show_sql”>true</property>
<property name=“hibernate.current_session_context_class”<thread</property>
<mapping resource=“com/smartJob/demo/entity/Users.hbm.xml”/>
<mapping resource=“com/smartJob/demo/entity/Notification.hbm.xml”/>
</session–factory>
</hibernate–configuration></code></span>
|
Hãy nhìn vào thuộc tính hibernate.dialect, Trong trường hợp này, Hibernate có tương tác (Creat, Read, Update, Delele, Search) được với cơ sở dữ liệu Oracle 11g không?
Ứng viên: Nếu cấu hình như trên thì Hibernate tương tác được với Cơ sở dữ liệu Oracle 11g, vì
1
|
<span style=“color: #333333;”><code class=“java”>hibernate.dialect = org.hibernate.dialect.OracleDialect</code></span>
|
hỗ trợ mọi phiên bản Oracle (ví dụ: Oracle 9i, Oracle 10g, Oracle 11g).
Nhà tuyển dụng: Hãy nhìn vào thuộc tính “hibernate.dialect”, Trong trường hợp này, Hibernate có tương tác (Creat, Read, Update, Delele, Search) được với cơ sở dữ liệu Oracle 11g không?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<span style=“color: #333333;”><code class=“java”><?xml version=“1.0” encoding=“UTF-8”?>
<!DOCTYPE hibernate–configuration PUBLIC “-//Hibernate/Hibernate Configuration DTD 3.0//EN” “http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd”>
<hibernate–configuration>
<session–factory>
<property name=“hibernate.dialect”>org.hibernate.dialect.Oracle10gDialect</property>
<property name=“hibernate.connection.driver_class”>oracle.jdbc.OracleDriver</property>
<property name=“hibernate.connection.url”>jdbc:oracle:thin:@10.10.1.142:1521:foo</property>
<property name=“hibernate.connection.username”>smart_job</property>
<property name=“hibernate.connection.password”>12345678</property>
<property name=“hibernate.show_sql”>true</property>
<property name=“hibernate.current_session_context_class”<thread</property>
<mapping resource=“com/smartJob/demo/entity/Users.hbm.xml”/>
<mapping resource=“com/smartJob/demo/entity/Notification.hbm.xml”/>
</session–factory>
</hibernate–configuration></code></span>
|
Ứng viên: Nếu cấu hình như trên thì Hibernate tương tác được với Cơ sở dữ liệu Oracle 11g, vì
1
|
<span style=“color: #333333;”><code class=“java”>hibernate.dialect = org.hibernate.dialect.Oracle10gDialect</code></span>
|
hỗ trợ cả hệ quản trị cơ sở dữ liệu Oracle 10g và Oracle 11g. (Không tồn tại org.hibernate.dialect.Oracle11gDialect nhé).
Nhà tuyển dụng: Mỗi bài viết trên blog SmartJob là 1 bản ghi trong CSDL quan hệ. Do ứng dụng blog SmartJob sử dụng Hibernate, cần có class entity Post như sau:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
<span style=“color: #333333;”><code class=“java”>package com.smartJob.entities;
// Generated Jan 10, 2016 3:53:05 PM by Hibernate Tools 4.3.1.Final
import java.util.Date;
/**
* Post generated by hbm2java
*/
public class Post implements java.io.Serializable {
private Integer id;
private Integer userId;
private Integer categoryId;
private String title;
private String sapo;
private String content;
private String tags;
private Integer previousPostId;
private Integer nextPostId;
private Date createTime;
private Date updateTime;
public Post() {
}
public Post(Integer userId, Integer categoryId, String title, String sapo, String content, String tags,
Integer previousPostId, Integer nextPostId, Date createTime, Date updateTime) {
this.userId = userId;
this.categoryId = categoryId;
this.title = title;
this.sapo = sapo;
this.content = content;
this.tags = tags;
this.previousPostId = previousPostId;
this.nextPostId = nextPostId;
this.createTime = createTime;
this.updateTime = updateTime;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUserId() {
return this.userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public Integer getCategoryId() {
return this.categoryId;
}
public void setCategoryId(Integer categoryId) {
this.categoryId = categoryId;
}
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public String getSapo() {
return this.sapo;
}
public void setSapo(String sapo) {
this.sapo = sapo;
}
public String getContent() {
return this.content;
}
public void setContent(String content) {
this.content = content;
}
public String getTags() {
return this.tags;
}
public void setTags(String tags) {
this.tags = tags;
}
public Integer getPreviousPostId() {
return this.previousPostId;
}
public void setPreviousPostId(Integer previousPostId) {
this.previousPostId = previousPostId;
}
public Integer getNextPostId() {
return this.nextPostId;
}
public void setNextPostId(Integer nextPostId) {
this.nextPostId = nextPostId;
}
public Date getCreateTime() {
return this.createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getUpdateTime() {
return this.updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
}</code></span>
|
Có 2 constructor. Nếu bỏ đi constructor không có đối số
1
2
|
<span style=“color: #333333;”><code class=“java”> public Post() {
}</code></span>
|
thì Hibernate có ghi-đọc-xóa-sửa (C.R.U.D) trên bảng dữ liệu Post không? Tại sao?
Ứng viên: Hibernate khởi tạo đối tượng Post như thế này:
1
|
<span style=“color: #333333;”><code class=“java”>Post.class.newInstance();</code></span>
|
dựa trên cơ chế reflection.
Nếu bỏ đi constructor không có đối số nói trên, Hibernate không khởi tạo được đối tượng (object) Post, do đó việc ghi-xóa-sửa-thêm (C.R.U.D) trên table Post bị lỗi (không thực hiện được).
Mời bạn xem tiếp phần 5 của series “Câu hỏi phỏng vấn LTV Java” tiếp tục với chủ đề Hibernate.
Đỗ Như Vý – developer tại SmartJob
API,
câu hỏi phỏng vấn,
Hibernate,
java,
JDBC,
Oracle,
ORM,
Phỏng vấn,
SQL,