Thứ Sáu, 17 tháng 1, 2014

PostgreSQL : Giới thiệu hàm viết bằng ngôn ngữ thủ tục PL/pgSQL

1. Giới thiệu

Với PL/pgSQL ta có thể dùng tất cả các kiểu dữ liệu, các toán tử và các hàm của SQL.
Ngoài ra, PL/pgSQL còn cho phép ta định nghĩa các hàm động (hàm liên quan đến các cột khác nhau, các bảng khác nhau mỗi khi ta thực thi nó), thực thi các lệnh điều kiện (IF, ELSE, CASE), các vòng lặp (LOOP, WHILE, FOR, FOREACH), xử lý các ngoại lệ và lỗi (EXCEPTION, RAISE), định nghĩa TRIGGER, con trỏ (CURSOR, FETCH, MOVE)  ...
Kể từ PostgreSQL 9.0, PL/pgSQL được cài mặc định.

Định nghĩa một hàm đơn giản viết bằng PL/pgSQL có dạng sau :
CREATE FUNCTION function_name (argument_name argument_type, argument_name argument_type, ...) 
RETURNS return_type AS $$
[ DECLARE
    declarations ]
BEGIN
    statements
END;
$$ language plpgsql;

Định nghĩa thân hàm phải là một lốc DECLARE-BEGIN-END. Trong đó, mỗi khai báo (declaration) và mỗi dòng lệnh (statement) kết thúc bằng dấu chấm phẩy.

Trong trường hợp phức tạp, lốc gốc này có thể có nhiều lốc con DECLARE-BEGIN-END, khi đó mỗi lốc con này kết thúc bằng END và dấu chấm phẩy theo sau.

Chú ý không nên nhầm lẫn : BEGIN/END của PL/pgSQL nhằm nhóm các lệnh vào một lốc. Còn BEGIN/END của SQL nhằm khởi đầu và kết thúc một giao dịch (transaction).

2. Ví dụ

Ví dụ 1
Ví dụ sau định nghĩa một hàm động cho phép lấy một giá trị ngẫu nhiên trong một cột của một bảng
CREATE OR REPLACE FUNCTION get_field(field_name varchar, table_name varchar, numrow int)
RETURNS SETOF varchar AS
$BODY$
BEGIN
    RETURN QUERY EXECUTE 'SELECT ' || $1 || ' from ' || $2 ||' ORDER BY random()*' || $3 || ' LIMIT 1';
END;
$BODY$
LANGUAGE plpgsql VOLATILE;

SELECT get_field('name','mobile',10);

Giải thích :
- Ở đây ta không cần dùng biến nên không có đoạn DECLARE.
- Câu truy vấn SQL được phát sinh động bằng cách nối chuỗi dùng các tham số là tên cột, tên bảng và một số. "ORDER BY random()*số LIMIT 1" cho phép lấy dòng đầu tiên của kết quả trả về với thứ tự ngẫu nhiên.
- Lệnh EXECUTE cho phép thực thi câu truy vấn SQL động định nghĩa bằng một chuỗi.
- RETURN QUERY trả về kết quả của một câu truy vấn (chứ không chỉ là một giá trị đơn giản) đó là lý do tại sao trong khai báo hàm ta dùng RETURNS SETOF.
- Ở đây ta dùng dấu nháy ' để định nghĩa các chuỗi, trong trường hợp chuỗi bao gồm nhiều dấu nháy ta có thể dùng bởi dấu ngoặc đô-la để bọc chuỗi để câu truy vấn dễ hiểu hơn.
- Câu gọi lệnh ở cuối trả về giá trị ngẫu nhiên của cột name trong bảng mobile.

Ví dụ2
Viết lại hàm trên để trả về một giá trị đơn giản
DROP FUNCTION IF EXISTS get_field(varchar, varchar, int);
CREATE OR REPLACE FUNCTION get_field(field_name varchar, table_name varchar, numrow int)
RETURNS varchar AS
$BODY$
DECLARE
    field varchar;
BEGIN
    EXECUTE 'SELECT ' || $1 || ' from ' || $2 ||' ORDER BY random()*' || $3 || ' LIMIT 1' 
    INTO field;
    RETURN field;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
SELECT get_field('name','mobile',10);

Giải thích :
- Hàm này thực hiện cùng một chức năng như hàm trong ví dụ 1.
- Ta định nghĩa một biến field (trong đoạn DECLARE), thực thi câu truy vấn động và gán giá trị trả về vào biến này (EXCECUTE ... INTO ...) . Cuối cùng trả về kết quả này cho hàm.
- Hàm này trả về một giá trị đơn giản nên trong định nghĩa hàm ta không dùng SETOF.


Ví dụ3
Ta có bảng customer như sau :
            Table "public.customer"
   Column   |         Type          | Modifiers 
------------+-----------------------+-----------
 id         | integer               | not null
 address    | character varying(64) | 
 first_name | character varying(32) | 
 last_name  | character varying(32) | 
 email      | character varying(64) | 
Indexes:
    "customer_pkey" PRIMARY KEY, btree (id)

Ta muốn tạo một bảng temp_customer có cấu trúc giống hệt bảng customer; và bảng này có dữ liệu là dữ liệu lấy ngẫu nhiên từ bảng customer
DROP TABLE IF EXISTS temp_customer;
CREATE TABLE temp_customer
(
    id integer NOT NULL,
    address character varying(64),
    first_name character varying(32),
    last_name character varying(32),
    email character varying(64),
    CONSTRAINT temp_customer_pkey PRIMARY KEY (id)
);

Để điền tự động thông tin vào bảng temp_customer ta định nghĩa hàm sau :
CREATE OR REPLACE FUNCTION fill_temp_customer()
RETURNS VOID AS
$BODY$
DECLARE
    num_row int;
BEGIN
    SELECT COUNT(*) INTO num_row FROM customer;
    FOR i IN 1..1000 
    LOOP
        INSERT INTO temp_customer(id, address, first_name, last_name, email)
            values(i, get_field('address', 'customer', num_row), 
            get_field('first_name', 'customer', num_row), get_field('last_name', 'customer', num_row),
            concat('customer_', i, '@openspace.vn'));
        EXIT WHEN i > num_row;
    END LOOP;
    SELECT COUNT(*) INTO num_row FROM temp_customer;
    IF num_row = 0 THEN
        INSERT INTO temp_customer(id, address, first_name, last_name, email)
            values(1, 'address 1', 'first_name 1', 'last_name 1', 'customer_1@openspace.vn');
        INSERT INTO temp_customer(id, address, first_name, last_name, email)
            values(2, 'address 2', 'first_name 2', 'last_name 2', 'customer_2@openspace.vn');
    END IF;
    RETURN;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
SELECT fill_temp_customer();

Giải thích :

- Hàm định nghĩa biến  num_row.
- Hàm này nhằm điền dữ liệu vào bảng temp_customer và không trả về giá trị nên khai báo hàm dùng RETURNS VOID.
- Câu lệnh SELECT INTO đầu tiên nhằm đếm tổng số dòng của bảng customer. Chú ý lệnh SELECT INTO của PL/PgSQL này (nhằm gán kết quả trả về vào một biến) hoàn toàn khác lệnh SELECT INTO của PostgreSQL (nhằm tạo ra một bảng mới từ kết quả của một câu truy vấn).
- Vòng lặp FOR từ 1 đến 1000 nhằm chèn thông tin vào bảng temp_customer, với giá trị của address, first_name, last_name là giá trị tương ứng lấy ngẫu nhiên từ bảng customer bằng cách dùng hàm get_field định nghĩa trong ví dụ 1.
- Lệnh EXIT nhằm kết thúc vòng lặp trong trường hợp tổng số dòng trong bảng customer ít hơn 1000.
- Câu lệnh SELECT INTO tiếp theo nhằm đếm tổng số dòng của bảng temp_customer.
- Trong trường hợp bảng customer không có dữ liệu, dẫn đến bảng temp_customer cũng không có dữ liệu, lệnh IF tiếp theo cho phép chèn hai dòng dữ liệu vào bảng temp_customer.

Thứ Tư, 8 tháng 1, 2014

PostgreSQL : Giới thiệu hàm viết bằng ngôn ngữ truy vấn SQL

1. Hàm do người dùng định nghĩa

PostgreSQL cung cấp bốn loại hàm sau cho người dùng định nghĩa
- Hàm viết bằng ngôn ngữ truy vấn (query language functions : hàm viết bằng SQL)
- Hàm viết bằng ngôn ngữ thủ tục (procedural language functions : viết bằng PL/pgSQL, PL/Tcl, PL/Perl, PL/Python chẳng hạn)
- Hàm cung cấp sẵn (internal functions : là các hàm được viết bằng C được cung cấp sẵn trong server PostgreSQL)
- Hàm viết bằng ngôn ngữ C (C-language functions)

Ở đây tôi giới thiệu sơ về hàm viết bằng SQL

2. Giới thiệu hàm viết bằng ngôn ngữ truy vấn

Một hàm viết bằng SQL cho phép thực thi các câu truy vấn SQL định nghĩa trong hàm, và trả về kết quả của câu lệnh cuối cùng. Trường hợp đơn giản, hàm trả về dòng đầu tiên của kết quả câu truy vấn cuối cùng, nếu câu truy vấn này không trả về dòng kết quả nào thì hàm trả về giá trị null.

Muốn hàm trả về toàn bộ các dòng của câu truy vấn cuối, ta phải định nghĩa SETOF return_type hoặc TABLE(columns) trong đoạn RETURNS

Trong thân hàm, các câu lệnh phải được phân cách bằng dấu chấm phẩy, và không được sử dụng các lệnh transaction (như COMMIT, SAVEPOINT, ...). Một định nghĩa hàm đơn giản có cấu trúc như sau :
CREATE FUNCTION function_name (argument_name argument_type, argument_name argument_type, ...) 
RETURNS return_type AS $$
     function_body_query;
$$ language sql;

Thân hàm được viết dưới dạng hằng chuỗi (string constant), thông thường ta sử dụng dấu ngoặc đô-la (dollar quoting : $) để bao hằng chuỗi này. Dấu ngoặc đô-la không phải là một chuẩn của SQL.

Một hằng chuỗi bao bởi dấu ngoặc đô-la có dạng sau $[tag]$<string constant>$[tag]$ tức dấu đô-la + một tag (có thể có hoặc không) bao gồm không hay nhiều ký tự + dấu đô-la + hằng chuỗi + dấu đô-la + cùng tag vừa định nghĩa + dấu đô-la. Ví dụ cụ thể :
$$Toan's string constant$$
$BODY$Toan's string constant$BODY$

3. Ví dụ đơn giản

Ví dụ  1
Trong ví dụ sau, ta định nghĩa hàm phát sinh ngẫu nhiên một chuỗi các số
CREATE OR REPLACE FUNCTION random_numero(amount int)
RETURNS TEXT AS
$BODY$
SELECT array_to_string(
    ARRAY(
        SELECT chr((48 + round(random() * 9)) :: integer) 
        FROM generate_series(1,$1)
    ), '');
$BODY$
LANGUAGE sql VOLATILE;

Giải thích :
- Hàm có tên là random_numero, nhận một tham số kiểu int
- Hàm trả về kết quả là một chuỗi kiểu TEXT
- Trong ngoặc đô-la $BODY$ là thân hàm
- Thân hàm là một câu truy vấn SQL select trả về một chuỗi ngẫu nhiên gồm n số, với n là tham số amount hàm nhận vào. Chú ý, hàm không nhận biết tên tham số chuyển vào : Các tham số được sử dụng trong hàm dưới dạng $n; $1 trỏ đến tham số đầu tiên, $2 đến tham số thứ hai, vân vân.
- Với tham số truyền vào chỉ có kiểu (type) là bắt buộc, do đó hàm trên có thể được định nghĩa random_numero(int). Nhưng ta nên định nghĩa hàm với tên tham số cho dễ hiểu
- Trong trường hợp nếu tham số chuyển vào có dạng phức thì ta dùng đến toán tử dấu chấm để truy xuất đến thuộc tính của biến truyền vào. VD : $1.name
- Trong câu truy vấn này ta sử dụng hàm định nghĩa sẵn array_to_string để chuyển một mảng thành một chuỗi. Sử dụng hàm generate_series ở đây chủ yếu để phát sinh vòng lặp từ 1 đến n với n là giá trị của biến $1 truyền vào. Với mỗi vòng lặp này, ta phát sinh một số ngẫu nhiên trong khoảng từ 0 đến 9 để tạo thành một phần tử của mảng. :: integer dùng để ép kiểu biểu thức chr((48 + round(random() * 9)) về số nguyên. round(random() * 9) trả về giá trị từ 0 đến 9
- Cuối cùng "LANGUAGE sql VOLATILE" định nghĩa hàm này được viết bằng ngôn ngữ truy vấn SQL, volatile là giá trị mặc định của một phân loại (volatility classification) dùng để tối ưu hàm (hay không).

Gọi hàm này như sau : SELECT random_numero(5);
openspace_vn_db=# SELECT random_numero(5);
 random_numero 
---------------
 08182
(1 row)

Ví dụ 2
Định nghĩa hàm cộng hai số với tham số trả về (ouput parameter)
CREATE OR REPLACE FUNCTION add_two (IN a int, IN b int, OUT sum int)
AS 'SELECT $1 + $2'
LANGUAGE SQL;

SELECT add_two(4,58);
 add_two 
---------
      62
(1 row) 

Giải thích :
- Hàm này nhận vào hai tham số và trả về tổng của hai giá trị này
- Tiện ích của cách định nghĩa này là ta có thể trả về nhiều giá trị, chẳng hạn
CREATE FUNCTION sum_n_product (a int, b int, OUT sum int, OUT product int)
AS 'SELECT $1 + $2, $1 * $2'
LANGUAGE SQL;
- Chú ý khi gọi hàm ta chỉ truyền vào các tham số in (tức chỉ 2 tham số a và b)
- Các tham số có thể được đánh dấu là IN, OUT, INOUT hay VARIADIC.
- Dấu chấm phẩy ở câu lệnh cuối của một hàm là tuỳ ý tức có cũng được hay không có cũng được. Do vậy, ở đây tuy không có dấu chấm phẩy ở cuối nhưng hàm vẫn hợp lệ.

Ví dụ3
Nếu hàm của bạn chỉ thực hiện các việc như UPDATE hoặc DELETE và không trả về giá trị gì, bạn có thể định nghĩa hàm trả về VOID.
Trong ví dụ sau, hàm thực hiện việc giấu thông tin về tên và tên nước của provider với việc dùng hàm md5 như sau :
CREATE OR REPLACE FUNCTION mask_provider()
RETURNS VOID AS
$BODY$
    UPDATE provider SET name = md5(name), country = md5(country);
$BODY$
LANGUAGE sql VOLATILE;

SELECT mask_provider();

Giải thích :
- Hàm thực hiện việc cập nhật và giấu thông tin tên và tên nước của provider bằng cách mã hoá hai thông tin này bằng hàm md5.

4. Ví dụ trả về nhiều dòng kết quả

Ví dụ 1
Hàm trả về danh sách tên của điện thoại di động trong bảng mobile.
CREATE OR REPLACE FUNCTION get_mobile_name()
RETURNS SETOF TEXT AS
$BODY$
    SELECT name FROM mobile;
$BODY$
LANGUAGE sql VOLATILE;

SELECT get_mobile_name();
get_mobile_name  
-------------------
 Samsung Galaxy S4
 iPhone 6
(2 rows)

Giải thích :
- Ở đây ta dùng từ khoá SETOF sau RETURNS để hàm trả về toàn bộ kết quả của câu truy vấn cuối trong hàm (trong ví dụ, hàm chỉ có một câu truy vấn).


Ví dụ 2
Hàm trả về danh sách tên của điện thoại di động trong bảng mobile, với kiểu trả về cũng chính là kiểu của cột name trong bảng mobile.
CREATE OR REPLACE FUNCTION get_mobile_name()
RETURNS SETOF mobile.name%TYPE AS
$BODY$
    SELECT name FROM mobile;
$BODY$
LANGUAGE sql VOLATILE;

Giải thích :
- %TYPE thực hiện việc chép kiểu : mobile.name%TYPE cung cấp kiểu của cột name trong bảng mobile.


Ví dụ 3
Hàm trả về nội dung của toàn bộ bảng mobile
CREATE OR REPLACE FUNCTION get_mobile()
RETURNS SETOF mobile AS
$BODY$
    SELECT * FROM mobile;
$BODY$
LANGUAGE sql VOLATILE;

SELECT * FROM get_mobile();

Giải thích :
- Ta có thể dùng bảng có sẵn trong CSDL làm kiểu trả về (ở đây là bảng mobile)


Ví dụ 4
Ta có thể định nghĩa lại kiểu của bảng trả về như sau
CREATE OR REPLACE FUNCTION get_mobile()
RETURNS TABLE(id integer, name text) AS
$BODY$
    SELECT id, name FROM mobile;
$BODY$
LANGUAGE sql VOLATILE;

SELECT * FROM get_mobile();

Giải thích :
- TABLE(id integer, name text) định nghĩa kiểu của bảng trả về gồm hai cột có kiểu lần lượt là integer và text. RETURNS TABLE(colums) thuộc về chuần gần đây của SQL nên nó có tính khả chuyển (portable) hơn là dùng SETOF.

5.Tóm tắt
Ta có thể tóm gọn việc định nghĩa hàm bằng ngôn ngữ truy vấn như sau
CREATE FUNCTION function_name ([ [ [IN | OUT | INOUT | VARIADIC
[argument_name] argument_type] [,  ...] ]) 
[RETURNS {[SETOF] return_type | TABLE(columns)} ] AS $$
     function_body_query;
$$ language sql;

Xem cụ thể tại đây CREATE FUNCTION

Thứ Hai, 30 tháng 12, 2013

PostgreSQL : Giới thiệu psql - giao diện tương tác dòng lệnh với PostgreSQL

psql là một giao diện tương tác dòng lệnh của PostgreSQL (PostgreSQL interactive terminal) cho phép ta gõ các câu truy vấn SQL gởi đến PostgreSQL và nhận về kết quả hiển thị

Truy cập cơ sở dữ liệu (CSDL) có tên openspace_db với username là toan
$ psql d openspace_db -U toan 

Ở đây ngầm định host là local, nếu muốn truy cập PostgreSQL cài ở máy khác thì phải cung cấp thông tin host, chẳng hạn như sau :
$ psql d openspace_db -U toan -h <host name>

Sau khi truy cập ta có thể dùng meta-command \l để hiển thị các cơ sở dữ liệu (database) hiện có trong PostgreSQL
openspace_db=# \l

                                       List of databases
         Name          |  Owner   | Encoding |  Collate   |   Ctype    |   Access privileges   
-----------------------+----------+----------+------------+------------+-----------------------
 openspace_db          | toan     | UTF8     | en_US.utf8 | en_US.utf8 | 

Thoát khỏi hiển thị này bằng cách gõ lệnh \q

Tạo một cơ sở dữ liệu mới mang tên openspace_vn_db, nhớ đừng quyên dấu chấm phẩy (;) ở cuối, vì psql nhận biết kết thúc dòng lệnh bằng dấu này
openspace_db=# create database openspace_vn_db;
CREATE DATABASE

Truy cập đến cơ sở dữ liệu mới tạo này bằng cách gõ lệnh \c như sau
openspace_db=# \c openspace_vn_db 
You are now connected to database "openspace_vn_db" as user "postgres".
openspace_vn_db=# 

Gõ lệnh \d để xem các quan hệ (relation : table, view, index, sequence, foreign talbe) của CSDL này
openspace_vn_db=# \d
No relations found.

Tạo một bảng dữ liệu có tên là mobile
openspace_vn_db=# create table mobile(id int, name varchar);
CREATE TABLE

Gõ lại lệnh \d, ta có
openspace_vn_db=# \d
         List of relations
 Schema |  Name  | Type  |  Owner   
--------+--------+-------+----------
 public | mobile | table | toan
(1 row)

Thêm dữ liệu vào bảng
openspace_vn_db=# insert into mobile values(0, 'Samsung Galaxy S4');
INSERT 0 1
openspace_vn_db=# insert into mobile values(1, 'iPhone 6');
INSERT 0 1

Xem dữ liệu trong bảng
openspace_vn_db=# select * from mobile;
 id |       name        
----+-------------------
  0 | Samsung Galaxy S4
  1 | iPhone 6
(2 rows)

Ta có thể nhập đọc dữ liệu vào (input) từ tập tin với lệnh \i, chẳng hạn tạo tập tin data.sql với nội dung sau :
create table provider(id int, name varchar, country varchar);
insert into provider values(0, 'Samsung', 'Korea');
insert into provider values(1, 'Apple', 'United States');

Rồi gõ lệnh
openspace_vn_db=# \i data.sql
CREATE TABLE
INSERT 0 1
INSERT 0 1
openspace_vn_db=# \d
          List of relations
 Schema |   Name   | Type  |  Owner   
--------+----------+-------+----------
 public | mobile   | table | toan
 public | provider | table | toan
(2 rows)

Ta có thể nhập nội dung vào PostgreSQL từ giao diện tương tác dòng lệnh của hệ điều hành (Ubuntu chẳng hạn). Trước hết ta xoá bảng dữ liệu provider vừa tạo và thoát khỏi psql với lệnh \q như sau
openspace_vn_db=# drop table provider;
DROP TABLE
openspace_vn_db=# \q

Rồi nhập dữ liệu vào từ tập tin như sau
$ psql -d openspace_vn_db -U toan -f data.sql
CREATE TABLE
INSERT 0 1
INSERT 0 1

Ta có thể tìm kiếm các quan hệ wildchar như sau (mo* : Các quan hệ có tên bắt đầu bằng mo)
openspace_vn_db=# \d mo*
         Table "public.mobile"
 Column |       Type        | Modifiers 
--------+-------------------+-----------
 id     | integer           | 
 name   | character varying | 


Thứ Tư, 18 tháng 12, 2013

Ubuntu : Cài đặt Glassfish trong Ubuntu

Tải glassfish về, ở đây tôi cài glassfish 3.1.2.2 tại thư mục gốc của người dùng (home)
$ wget http://download.java.net/glassfish/3.1.2.2/release/glassfish-3.1.2.2-unix.sh

Gọi thực thi tập tin vừa tải về để cài đặt glassfish
$ sh glassfish-3.1.2.2-unix.sh

Đổi tên thư mục vừa tạo thành cho gọn
$ mv ~/glassfish3 ~/glassfishv3.1.2.2

Mở tập tin .profile
$ gedit ~/.profile

rồi thêm định nghĩa biến môi trường cho Glassfish vào cuối tập tin này
# Glassfish
export GLASSFISH_HOME=/home/tcminh/glassfishv3.1.2.2/glassfish/
export PATH="$GLASSFISH_HOME/bin:$PATH"

Sau đó gọi thực thi tập tin để cập nhật biến vừa thêm vào
$ . ~/.profile

Nếu cần thiết, định nghĩa địa chỉ 127.0.0.1 cho localhost; <machine name> thay bằng tên máy của bạn chẳng hạn pc12991. Mở tập tin /etc/hosts
$ sudo gedit /etc/hosts
Thêm/sửa dòng sau
127.0.0.1    localhost <machine name>

Kiểm tra hoạt động glassfish, ở đây không chỉ rõ domain thì glassfish tự hiểu là domain1, khởi động :
$ asadmin start-domain

Dừng glassfish
$ asadmin stop-domain

Kiểm tra số tập tin tối đa cho process cho "người dùng" tên glassfish (dùng cho hoạt động của máy chủ glassfish):
$ sudo su - glassfish
$ ulimit -n

Trong truờng hợp của bạn, nếu không định nghĩa một "người dùng" glassfish thì kiểm tra với tên người dùng là bạn (trong lệnh trên thay glassfish bằng login của bạn khi đăng nhập ubuntu)

Nếu cần thiết, thay đổi giới hạn số tập tin có thể mở cùng lúc cho một người dùng bằng cách thêm thông tin sau trong tập tin /etc/security/limits.conf :
glassfish soft nofile 4096
glassfish hard nofile 8192

rồi khởi động lại Ubuntu. Chú ý, trong trường hợp của bạn nên thay "glassfish" trong hai dòng trên bằng login của bạn.

Kiểm tra một số tham số của Linux. Đôi khi ta cần điều chỉnh tham số về dung lượng bộ nhớ chia sẻ [SHMMAX : Maximum size of shared memory segment (bytes);
SHMMIN : Minimum size of shared memory segment (bytes)] với các dòng lệnh sau :
$ sysctl -e kernel.shmmax
$ sysctl -e kernel.shmall

Nếu cần, gán cứng các tham số này trong tập tin /etc/sysctl.conf bằng cách thêm các dòng sau :
kernel.shmmax=134217728
kernel.shmall=8388608

134217728 tương ứng 128MB; 8388608 tương ứng 8MB

Hoặc có thể thay đổi các giá trị này trong phiên (session) hiện hành bằng cách gõ các dòng lệnh sau :
$ sudo sysctl -w kernel.shmmax=134217728
$ sudo sysctl -w kernel.shmall=8388608

Một số lệnh khác khi dùng glassfish, ở đây không chỉ rõ domain thì glassfish tự hiểu là domain1 :
Triển khai (deploy) ear, <application name> thay bằng tên của ứng dụng cần triển khai
$ asadmin deploy <application name>.ear

Gỡ bỏ (undeploy) một ứng dụng được triển khai khỏi glassfish
$ asadmin undeploy <application name>

Liệt kê các ứng dụng hiện được triển khai trong glassfish
$ asadmin list-applications

Khởi động lại
$ asadmin restart-domain
Lệnh này tương đương với lệnh sau
$ asadmin restart-domain domain1

Thay đổi cấu hình của một ứng dụng triển khai trong glassfish được định nghĩa trong tập tin domain.xml (ở đây glassfish được cài đặt tại thư mục gốc của người dùng)
$ gedit ~/glassfishv3.1.2.2/glassfish/domains/domain1/config/domain.xml

Nếu ứng dụng của bạn xài hệ quản trị cơ sở dữ liệu PostgreSQL chẳng hạn, bạn cần tải driver của PostgreSQL về chẳng hạn cho phiên bản postgresql-9.3 tại đường dẫn sau http://repo1.maven.org/maven2/org/postgresql/postgresql/9.3-1100-jdbc41/postgresql-9.3-1100-jdbc41.jar

Sau đó chép driver này vào thư mục /usr/share/java/ cho dễ quản lý
Vào thư mục sau của glassfish
$ cd ~/glassfishv3.1.2.2/glassfish/domains/domain1/lib/ext

Rồi tạo đường dẫn biểu tượng đến driver vừa chép vào thư mục /usr/share/java/ như sau :
$ ln -s /usr/share/java/postgresql-9.3-1100-jdbc41.jar postgresql.jar


Thứ Ba, 17 tháng 12, 2013

Ubuntu : Cài đặt Java trong Ubuntu

Bài này giới thiệu cách cài đặt thủ công Java (jdk) trong Ubuntu.

Trước hết cần kiểm xem máy của bạn là 32 hay 64 bit để tải gói jdk thích hợp về cài đặt với lệnh sau :
$ uname -a

Sau đó tải gói jdk tương ứng về máy của bạn, ở đây tôi tải jdk-6u37-linux-x64.bin (cho 64 bit) (hay jdk-6u37-linux-i586.bin cho 32 bit) tại đường dẫn sau http://www.oracle.com/technetwork/java/javase/downloads/jdk6u37-downloads-1859587.html

Chép tập tin tải về (trong thư mục Downloads tại Home) vào thư mục /usr/lib/jvm bằng tài khoản root (sudo)
$ sudo cp Downloads/jdk-6u37-linux-x64.bin /usr/lib/jvm/

Vào thư mục /usr/lib/jvm/
$ cd /usr/lib/jvm/

rồi gán quyền thực thi cho tập tin với lệnh chmod như sau
$ sudo chmod u+x jdk-6u37-linux-i586.bin

Sau đó ta có thể gọi thực thi tập tin này
$ sudo ./jdk-6u37-linux-i586.bin

lệnh này sẽ tạo thư mục /usr/lib/jvm/jdk1.6.0_37 chứa jdk cài đặt
Xoá đường dẫn tượng trưng (symbolic link) /usr/lib/jvm/java-6-sun nếu có. Rồi tạo đường dẫn tượng trưng mới đến thư mục vừa cài đặt jdk
$ sudo ln -s /usr/lib/jvm/jdk1.6.0_37 /usr/lib/jvm/java-6-sun 

Mở tập tin .profile; <user name> ở đây là tên thư mục gốc của người dùng
$ gedit /home/<user name>/.profile


Rồi thêm biến JAVA_HOME bằng cách thêm vào cuối tập tin này nội dung sau :
# Java
export JAVA_HOME="/usr/lib/jvm/java-6-sun"
export PATH="$JAVA_HOME/bin:$PATH"


Trong /home/<user name> gọi thực thi tập tin .profile như sau
$ . .profile

Kiểm tra phiên bản java vừa cài đặt bằng cách gõ lệnh sau
$ java -version


Tôi có kết quả như sau
java version "1.6.0_37"
Java(TM) SE Runtime Environment (build 1.6.0_37-b06)
Java HotSpot(TM) 64-Bit Server VM (build 20.12-b01, mixed mode)


Trong trường hợp gõ lệnh này mà thấy lỗi, nên kiểm tra biến môi trường JAVA_HOME có được định nghĩa chính xác hay không với lệnh : 
$ export


Một khi cài đặt xong xuôi, xoá tập tin jdk-6u37-linux-i586.bin
$ sudo rm jdk-6u37-linux-x64.bin


Thứ Sáu, 14 tháng 6, 2013

Telnet : Dùng telnet trong windows

- Gõ dòng lệnh này trong command prompt để khởi động telnet phía khách (client)
telnet.exe

- Sau khi telnet khởi động, kích hoạt chế độ echo những kí tự được gõ vào màn hình lệnh
set localecho

- Kích hoạt chế độ chuyển phím Enter thành ký tự xuống dòng và về đầu dòng (CR & LF : carriage return và line feed)
set crlf

- Mở kết nối đến một trang web (ở đây là trang google.com) tới cổng TCP 80
o www.google.com 80

- Chú ý là telnet không thông báo cho biết là bạn đã thực sự kết nối hay chưa. Nhấn Enter để con trỏ chuyển đến dòng tiếp theo hay đầu trang.

- Thử lấy trang mặc định của trang google.com bằng cách nhập các dòng sau. Sau khi nhập dòng thứ hai, nhấn hai lần Enter để cho biết đây là thông điệp gửi đến máy chủ (server)
GET / HTTP/1.1
Host: www.google.com

- Nếu mã trạng thái (status code) là 200, tức máy chủ trả lời thành công và nội dung trả lời được gởi trong phần body. Nếu mã là 302 chẳng hạn, tức máy chủ tìm thấy trang web và chuyển tới (redirect) trang khác để trả lời, chẳng hạn trang http://www.google.vn/

- Nhấn Ctrl+[ để trở về trang lệnh của Telnet

Thứ Ba, 7 tháng 5, 2013

Model 1/2, MVC : Sơ lược về Mô hình 1 (Model 1), Mô hình 2 (Model 2) và mẫu Mô hình - Mặt nhìn - Khối điều khiển (MVC : Model-View-Controller) và các biến thể của nó MVP, PM, MVVM

1. Mô hình 1 và 2

Trong bản tiền phát hành của đặc tả JavaServer Pages, Sun có đề cập đến hai mô hình khi dùng công nghệ JSP gọi là Mô hình 1 (Model 1) và Mô hình 2 (Model 2). Tuy sau này, hai mô hình này không xuất hiện trong bản đặc tả chính thức nhưng hai thuật ngữ này vẫn được tiếp tục sử dụng.

Trong Mô hình 1, JSP được sử dụng để xử lý mọi tác vụ bao gồm việc xử lý truy vấn gửi từ phía khách, thực hiện các logic xử lý, phát sinh trả lời ...Tuy có thể được sử dụng để phát triển ứng dụng web đơn giản và nhỏ, mô hình này không được khuyến khích sử dụng. Vì mặc dù có tách bạch phần trình bày (presentation) và nội dung (content) do mọi truy vấn dữ liệu được thực hiện thông qua các JavaBeans; nhưng nó gây ra việc viết nhiều mã java xử lý truy vấn ở trang jsp và việc lặp lại mã nên phức tạp khi bảo trì và thay đổi.

Trong Mô hình 2, servlet được sử dụng cho phần xử lý truy vấn từ người dùng và JSP cho việc phát sinh trả lời. Servlet nhận truy vấn từ phía khách, thực hiện những tác vụ cần thiết để có được thông tin nhằm khởi tạo các beans cho trang JSP dùng, và thực hiện việc điều phối, tức việc chuyển đến trang JSP trả lời. Mô hình này phân tách phần logic lấy và thao tác xử lý nội dung với phần hiển thị nội dung nên nó thường được gắn với mẫu Mô hình - Mặt nhìn - Khối điều khiển MVC