Apache + PHP + MySQL

Posted at 2009. 11. 11. 08:20 | Posted in Server/Ubuntu
반응형

#  apt-get install mysql-server

utf-8, innodb 설정

# vi /etc/mysql/my.cnf

# utf-8
[client]
default-character-set=utf8  

[mysqld]   
character-set-client-handshake=FALSE  
init_connect="SET collation_connection=utf8_general_ci"  
init_connect="SET NAMES utf8"  
default-character-set=utf8  
character-set-server=utf8  
collation-server=utf8_general_ci  

# InnoDB
default-storage-engine=INNODB

# 테이블명의 대소문자를 가리지 않게 한다.
lower_case_table_names = 1

[mysqldump]    
default-character-set=utf8

[mysql]   
default-character-set=utf8

# 외부에서도 접속 가능하게 한다.
# bind-address          = 127.0.0.1

mysql 재시작

# /etc/init.d/mysql restart

설정 확인

# mysql -uroot -p비밀번호
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 35
Server version: 5.1.37-1ubuntu5 (Ubuntu)
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> status
--------------
mysql  Ver 14.14 Distrib 5.1.37, for debian-linux-gnu (i486) using  EditLine wrapper

Connection id:          35
SSL:                    Not in use
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server version:         5.1.37-1ubuntu5 (Ubuntu)
Protocol version:       10
Connection:             Localhost via UNIX socket
Client characterset:    utf8
Server characterset:    utf8
UNIX socket:            /var/run/mysqld/mysqld.sock
Uptime:                 1 min 59 sec

Threads: 1  Questions: 102  Slow queries: 0  Opens: 99  Flush tables: 1  Open tables: 23  ....
--------------

mysql> show engines;
| InnoDB     | DEFAULT | Supports transactions, row-level locking, and foreign keys ....

mysql> exit
Bye



apache2

# apt-get install apache2
# apt-get install libapache2-mod-auth-mysql

ServerName 등록

# vi /etc/apache2/apache2.conf

# ServerName
ServerName nerv-team.co.kr

가상 호스트 설정

#  vi /etc/apache2/sites-enabled/000-default

# nerv-team.co.kr
<VirtualHost *:80>
        ServerName nerv-team.co.kr
        Redirect / http://www.nerv-team.co.kr/
</VirtualHost>
# www.nerv-team.co.kr
<VirtualHost *:80>
        ServerAdmin antop@nerv-team.co.kr
        ServerName www.nerv-team.co.kr
        ServerAlias nerv-team.co.kr
        DocumentRoot /var/www
        ....
</VirtualHost>

http://nerv-team.co.kr 으로 접속해도 http://www.nerv-team.co.kr 으로 갈 수 있도록 수정


apache2 재시작

# /etc/init.d/apache2 restart

테스트





php5

# apt-get install php5
# apt-get install php5-gd php5-imap
# apt-get install php5-mhash
# apt-get install php5-mysql
# apt-get install php5-pgsql

설정

# vi /etc/php5/apache2/php.ini

; 추가
date.timezone = Asia/Seoul
[PHP]
default_charset = "UTF-8"
output_buffering = 4096

....

; 수정
magic_quotes_gpc = Off

apache2 재시작

# /etc/init.d/apache2 restart

테스트

# echo '<?php phpinfo(); ?>' > /var/www/phpinfo.php





phpmyadmin

# apt-get install phpmyadmin

apache2 선택



기본 http://www.nerv-team.co.kr/phpmyadmin 으로 되어 있지만 http://mysql.nerv-team.co.kr 으로 변경

# rm /etc/apache2/conf.d/phpmyadmin.conf

서브 도메인 설정

# vi /etc/apache2/sites-enabled/000-default

# 추가
# mysql.nerv-team.co.kr
<VirtualHost *:80>
        ServerName mysql.nerv-team.co.kr
        DocumentRoot /usr/share/phpmyadmin
</VirtualHost>

apache2 재시작

# /etc/init.d/apache2 restart

테스트



반응형

'Server > Ubuntu' 카테고리의 다른 글

Openfire  (0) 2010.05.25
Webmin  (0) 2009.11.18
Squirrelmail  (0) 2009.11.12
SparkWeb  (0) 2009.11.12
Cacti  (0) 2009.11.12
Apache + SSL  (0) 2009.11.12
Oracle Express Edition 10g  (0) 2009.11.11
Apache + Tomcat with Tomcat Connector  (0) 2009.11.11
bind9 - domain name service  (0) 2009.11.11
Ubuntu 9.10 Desktop  (0) 2009.11.11
//

bind9 - domain name service

Posted at 2009. 11. 11. 01:17 | Posted in Server/Ubuntu
반응형
https://help.ubuntu.com/community/BIND9ServerHowto



bind9 설치

# apt-get install bind9

zone 등록

# vi /etc/bind/named.conf.local

//
// Do any local configuration here
//
zone "nerv-team.co.kr" {
        type master;
        file "/etc/bind/db.nerv-team.co.kr";
};
// Consider adding the 1918 zones here, if they are not used in your
// organization
//include "/etc/bind/zones.rfc1918";

zone 설정파일 작성 ( 기본 설정 파일을 복사한 후 편집 )

# cp /etc/bind/db.local /etc/bind/db.nerv-team.co.kr

# vi /etc/bind/db.nerv-team.co.kr

;
; BIND data file for local loopback interface
;
; 도메인 주소 뒤에 ' . ' 주의!!

$TTL    604800
@       IN      SOA     ns.nerv-team.co.kr. root.nerv-team.co.kr. (
                              2         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@       IN      NS      ns.nerv-team.co.kr.
@       IN      A       220.86.83.10
www  IN      A       220.86.83.10
mail    IN      A       220.86.83.10
*        IN      A       220.86.83.10

bind9 재시작

# /etc/init.d/bind9 restart

※ 설정을 변경하면 바로 적용이 안되고 '$TTL    604800' 갱신 주기마다 적용됨.


테스트

# ping nerv-team.co.kr
PING nerv-team.co.kr (220.86.83.10) 56(84) bytes of data.
64 bytes from 220.86.83.10: icmp_seq=1 ttl=64 time=0.039 ms
64 bytes from 220.86.83.10: icmp_seq=2 ttl=64 time=0.036 ms
64 bytes from 220.86.83.10: icmp_seq=3 ttl=64 time=0.035 ms
64 bytes from 220.86.83.10: icmp_seq=4 ttl=64 time=0.034 ms
64 bytes from 220.86.83.10: icmp_seq=5 ttl=64 time=0.034 ms
64 bytes from 220.86.83.10: icmp_seq=6 ttl=64 time=0.036 ms
64 bytes from 220.86.83.10: icmp_seq=7 ttl=64 time=0.026 ms
64 bytes from 220.86.83.10: icmp_seq=8 ttl=64 time=0.027 ms
^C
--- nerv-team.co.kr ping statistics ---
8 packets transmitted, 8 received, 0% packet loss, time 7009ms
rtt min/avg/max/mdev = 0.026/0.033/0.039/0.006 ms

# named-checkzone nerv-team.co.kr /etc/bind/db.nerv-team.co.kr
zone nerv-team.co.kr/IN: NS 'ns.nerv-team.co.kr' has no address records (A or AAAA)
zone nerv-team.co.kr/IN: loaded serial 2
OK

# dig nerv-team.co.kr
; <<>> DiG 9.6.1-P1 <<>> nerv-team.co.kr
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49830
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 0
;; QUESTION SECTION:
;nerv-team.co.kr.               IN      A
;; ANSWER SECTION:
nerv-team.co.kr.        604800  IN      A       220.86.83.10
;; AUTHORITY SECTION:
nerv-team.co.kr.        604800  IN      NS      ns.nerv-team.co.kr.
;; Query time: 4 msec
;; SERVER: 168.126.63.1#53(168.126.63.1)
;; WHEN: Wed Nov 11 01:13:33 2009
;; MSG SIZE  rcvd: 66


반응형

'Server > Ubuntu' 카테고리의 다른 글

Openfire  (0) 2010.05.25
Webmin  (0) 2009.11.18
Squirrelmail  (0) 2009.11.12
SparkWeb  (0) 2009.11.12
Cacti  (0) 2009.11.12
Apache + SSL  (0) 2009.11.12
Oracle Express Edition 10g  (0) 2009.11.11
Apache + Tomcat with Tomcat Connector  (0) 2009.11.11
Apache + PHP + MySQL  (0) 2009.11.11
Ubuntu 9.10 Desktop  (0) 2009.11.11
//

Ubuntu 9.10 Desktop

Posted at 2009. 11. 11. 01:15 | Posted in Server/Ubuntu
반응형
http://www.ubuntu.com/



패키지 업데이트

# apt-get update
# apt-get upgrade



Vim[각주:1] 설치

# apt-get install vim



telnet 설치

# apt-get install xinetd
# apt-get install telnetd



ssh 설치 ( openssh 도 같이 설치됨 )

# apt-get install ssh








  1. Vim(Vi IMproved)은 Bram Moolenaar가 만든 vi 호환 텍스트 편집기이다. 본래 아미가 컴퓨터 용 프로그램이었으나 현재는 마이크로소프트 윈도, 리눅스, 맥 오에스 텐을 비롯한 여러 환경을 지원한다.Vim은 vi와 호환되면서도 독자적으로 다양한 기능을 추가하여 사용자의 편의를 돕고 있다. 특히 Vim 스크립트 등을 사용해서 자유롭게 편집 환경을 변경하거나, 확장된 정규 표현식 문법, 강력한 문법 강조 기능, 다중 되돌리기, 유니코드를 비롯한 다국어 지원, 문법 검사 등을 쓸 수 있다는 점이 강점으로 꼽힌다. 한편으로는 vi와 마찬가지로 처음에 배우기 어렵다는 점이 단점으로 지적되는데, 이를 극복하기 위해 쉬운 Vim 모드를 지원한다. [본문으로]
반응형

'Server > Ubuntu' 카테고리의 다른 글

Openfire  (0) 2010.05.25
Webmin  (0) 2009.11.18
Squirrelmail  (0) 2009.11.12
SparkWeb  (0) 2009.11.12
Cacti  (0) 2009.11.12
Apache + SSL  (0) 2009.11.12
Oracle Express Edition 10g  (0) 2009.11.11
Apache + Tomcat with Tomcat Connector  (0) 2009.11.11
Apache + PHP + MySQL  (0) 2009.11.11
bind9 - domain name service  (0) 2009.11.11
//

계정 생성

Posted at 2009. 11. 8. 23:11 | Posted in Database/MySQL
반응형
- 관리자 로그인
$ mysql -uroot -p비밀번호 mysql

- 계정 생성
mysql> insert into user ( host, user, password ) values ( 'localhost', '사용자명', password('패스워드') );

- 데이터베이스 생성
mysql> create database 디비명;

- 데이터베이스 권한 주기
mysql> insert into db ( host, db, user, select_priv, insert_priv, update_priv, delete_priv, create_priv, alter_priv, drop_priv) values ( 'localhost', '디비명', '사용자명', 'y', 'y', 'y', 'y', 'y', 'y', 'y' );

- 새로 적용
mysql> flush privileges;

반응형

'Database > MySQL' 카테고리의 다른 글

SELECT 쿼리 연습용 샘플 스키마  (1) 2009.12.22
//

Criteria 사용하여 질의 하기 #2

Posted at 2009. 10. 3. 10:03 | Posted in Framework/Hibernate
반응형
JOIN

http://docs.jboss.org/hibernate/stable/core/api/org/hibernate/Criteria.html





부서와 사원의 1:n 관계에 JOIN 쿼리를 날려봅시다.

원래 하이버네이트에서는 매핑을 잘 맺어주면, 단순 getter 로도 관계를 가지는 테이블의 내용을 가져올 수 있습니다.

Criteria crit = sess.createCriteria(Emp.class);

List<Emp> emps = crit.list();
   
int size = emps.size();
for(int i=0 ; i < size ; i++) {
   Emp emp = emps.get(i);
   Dept dept = emp.getDept();

   String empName = emp.getName();
   String deptName = dept != null ? dept.getDeptName() : "";
    
   System.out.println("row: " + (i+1));
   System.out.println(emp);
   System.out.println(dept);
}

이렇게하면 사원에 해당하는 부서의 정보를 가져올 수 있습니다.

로그를 보면 select문이 여러번 출력되는 것을 볼 수 있습니다.

List<Emp> emps = crit.list(); 에서 ' select empno, ename, job, hire_date from tbl_emp; ' 쿼리가 실행되고,

dept.getDeptName(); 에서 사원의 부서번호에 따라 ' select deptno, dname, loc from tbl_dept; ' 쿼리가 실행 됩니다.

부서의 종류가 엄청나게 많다면 두번째 select 쿼리가 많이 실행 되게 될 것입니다.

쿼리를 할때 최소한의 I/O로 실행되게 하고, 뭐.. 서브쿼리보다는 조인이 빠르고 흘러가면서 들은 것들이 있기 땜시... JOIN ㄱㄱ



INNER JOIN

키를 기준으로 일치하는 데이터만 가져옵니다. (다 아시졍? +_+)

// select * from tbl_emp e
Criteria crit = sess.createCriteria(Emp.class, "e");
// join tbl_dept d on this.deptno = d.deptno
crit.createCriteria("dept", "d");
   
// Result 를 Map 형태로 변환
crit.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);

List<Map<String, Object>> joinList = crit.list();

int size = joinList.size();
for(int i=0 ; i < size ; i++) {
   Map<String, Object> map = joinList.get(i);
   Emp emp = (Emp) map.get("e");
   Dept dept = (Dept) map.get("d");

   System.out.println("row: " + (i+1));
   System.out.println(emp);
   System.out.println(dept);
}


Criteria crit = sess.createCriteria(Emp.class);

Session.createCriteria(클리스명) 를 통해서 생성한 Critereria 객체에 다시 createCriteria(String associationPath, String alias) 를 사용해서 JOIN 을 하면 됩니다.

이렇게 JOIN 한 결과는 Emp 객체도 Dept 객체도 아니기 때문에, Criteria의 setResultTransformer 메소드를 사용하여 Criteria를 이용한 조회 결과를 별도 정의한 객체 형태나 Map 형태로로 전달받아야 하겠습니다.

근데 전 객체로 변형하는 법은 잘 안되서... 걍 Map 으로 ㄱㄱㄱ!

여기서 두번째 인자로 넣는 엘리어스명은 쿼리에서 쓰는 엘리어스명도 되지만 나중에 Map 에서 꺼 낼때의 키도 되기 때문에 꼭 지정해줘야 할 것입니다....

실행 되는 쿼리는 아래와 같습니다.

    select
        this_.empno as empno0_1_,
        this_.ename as ename0_1_,
        this_.job as job0_1_,
        this_.hire_date as hire4_0_1_,
        this_.deptno as deptno0_1_,
        d1_.deptno as deptno1_0_,
        d1_.dname as dname1_0_,
        d1_.loc as loc1_0_
    from
        tbl_emp this_
    inner join
        tbl_dept d1_
            on this_.deptno=d1_.deptno


이러면 당연히 부서가 없는 'TOM' 은 목록에 나오지가 않겠죠? 만약 사원 목록을 본다면 부서가 없는 사원이 나오면 안되겠죠?



LEFT JOIN

두개의 테이블을 조인할 때 왼쪽 테이블을 기분으로 오른쪽 테이블을 조인 시키는 LEFT JOIN 을 해봅시다...

createCriteria(String associationPath, String alias, int joinType) 를 사용하면 됩니다.

// select * from tbl_emp e
Criteria crit = sess.createCriteria(Emp.class, "e");
// join tbl_dept d on this.deptno = d.deptno
crit.createCriteria("dept", "d", Criteria.LEFT_JOIN);
   
// Result 를 Map 형태로 변환
crit.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);

List<Map<String, Object>> joinList = crit.list();

int size = joinList.size();
for(int i=0 ; i < size ; i++) {
   Map<String, Object> map = joinList.get(i);
   Emp emp = (Emp) map.get("e");
   Dept dept = (Dept) map.get("d");

   System.out.println("row: " + (i+1));
   System.out.println(emp);
   System.out.println(dept);
}

실행되는 쿼리는 아래와 같습니다. 엘리어스 사용에 주의 하세요~

    select
        this_.empno as empno0_1_,
        this_.ename as ename0_1_,
        this_.job as job0_1_,
        this_.hire_date as hire4_0_1_,
        this_.deptno as deptno0_1_,
        d1_.deptno as deptno1_0_,
        d1_.dname as dname1_0_,
        d1_.loc as loc1_0_
    from
        tbl_emp this_
    left outer join
        tbl_dept d1_
            on this_.deptno=d1_.deptno


※ RIGHT JOIN 은 없네요 테이블의 좌 우 를 바꾸셔요~ 히힛

간단하게 사원명과 부서명으로 조회하는 페이지 만들어 봤어요~








Pagination

많은 자료를 조회할 때 일정한 양의 자료를 한 페이지만 보여주도록 하는 기능입니다.

꼭 필요한 기능이고, 그다지 복잡할 것도 없지만, 막상 쿼리 날리려면 DBMS 마다 쿼리도 틀리고... 쉽지 안쵸 ㅠ_ㅠ

하지만 하이버네이트에서는

setFirstResult(int firstResult) 과 setMaxResults(int maxResults) 메소드 두개면 해결 됩니다! ㅋㅋㅋ

전부터 해오던 우편번호 테이블 가지고 해봅시다...


Criteria crit = sess.createCriteria(Zipcode.class);
crit.setFirstResult(40);   // 시작 로우 라인 번호(?)
crit.setMaxResults(10);    // 시작 로우 라인 번호로 부터 몇개?!

List<Zipcode> list = crit.list();
   
int size = list.size();
for(int i=0 ; i < size ; i++) {
   Zipcode z = list.get(i);
   System.out.println(z.toString());
}

한 페이지에 10개씩 보여준다고 하고 4페이지의 내용을 보여주게 됩니다. 


페이징 처리가 되있는 우편번호 검색 페이지를 만들어봤습니다.




몇개의 DMBS 에서 돌려보니까 아래와 같은 쿼리가 나오네요


MySQL 5.1.38
    select
        this_.seq as seq0_0_,
        this_.zipcode as zipcode0_0_,
        this_.sido as sido0_0_,
        this_.gugun as gugun0_0_,
        this_.dong as dong0_0_,
        this_.ri as ri0_0_,
        this_.bldg as bldg0_0_,
        this_.st_bunji as st8_0_0_,
        this_.ed_bunji as ed9_0_0_
    from
        tbl_zipcode this_ limit ?,
        ?


Oracle 10g Express Edition
    select
        *
    from
        ( select
            row_.*,
            rownum rownum_
        from
            ( select
                this_.seq as seq0_0_,
                this_.zipcode as zipcode0_0_,
                this_.sido as sido0_0_,
                this_.gugun as gugun0_0_,
                this_.dong as dong0_0_,
                this_.ri as ri0_0_,
                this_.bldg as bldg0_0_,
                this_.st_bunji as st8_0_0_,
                this_.ed_bunji as ed9_0_0_
            from
                tbl_zipcode this_ ) row_
        where
            rownum <= ?
        )
    where
        rownum_ > ?


Microsoft SQL Server 2005
    select
        top 20 this_.seq as seq0_0_,
        this_.zipcode as zipcode0_0_,
        this_.sido as sido0_0_,
        this_.gugun as gugun0_0_,
        this_.dong as dong0_0_,
        this_.ri as ri0_0_,
        this_.bldg as bldg0_0_,
        this_.st_bunji as st8_0_0_,
        this_.ed_bunji as ed9_0_0_
    from
        tbl_zipcode this_


MSSQL 은 일단 페이지번호 * 갯수 만큼 가져와서 내부적으로 처리를 하나봐요.....




http://blog.naver.com/oyukihana?Redirect=Log&logNo=60002506896

반응형

'Framework > Hibernate' 카테고리의 다른 글

PK 두개 이상시 매핑  (2) 2009.12.24
Reverse Engineering  (0) 2009.12.24
Hibernate 시작하기  (0) 2009.12.23
Criteria 사용하여 질의 하기 #1  (4) 2009.09.10
다대다(n:m) 관계 설정하기  (0) 2009.09.02
일대다(1:n) 관계 설정하기  (1) 2009.08.31
일대일(1:1) 관계 설정하기  (0) 2009.08.27
하이버네이트(Hibernate) 사용하기  (6) 2009.08.24
//

Criteria 사용하여 질의 하기 #1

Posted at 2009. 9. 10. 15:52 | Posted in Framework/Hibernate
반응형
Hibernate에서는 HQL에 익숙하지 못하거나 HQL 작성시 발생할 수 있는 오타로 인한 오류를 최소화 하기 위해 org.hibernate.Criteria API를 사용할 수 있도록 합니다.
Creteria API 호출을 통해 특정 객체에 대한 조회가 가능하고 org.hibernate.criterion.Restrictions API 호출을 통해 WHERE문에 해당하는 기본 조회 조건을 정의할 수 있습니다..

쉽게 말해서 select 쿼리입니다.

우편번호 데이터(50353건)로 여러가지 조회를 해봅시다! (Type 4 사용)



package com.tistory.antop;

public class Zipcode {
    // 데이터 순서(5)
    private int seq;
    // 우편번호(7)
    private String zipcode;
    // 특별시,광역시,도(4)
    private String sido;
    // 시,군,구(15)
    private String gugun;
    // 읍,면,동(26)
    private String dong;
    // 리(18)
    private String ri;
    // 건물명(40)
    private String bldg;
    // 시작번지(11)
    private String stBunji;
    // 끝번지(9)
    private String edBunji;

    // constructor, getter and setter (private setter seq)

    @Override
    public String toString() {
        // 길어서 생략...
    }
}



<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.tistory.antop">
    <class name="Zipcode" table="tbl_zipcode">
        <!-- 데이터 순서(5) -->
        <id name="seq" length="5">
            <generator class="native" />
        </id>
        <!-- 우편번호(7) -->
        <property name="zipcode" length="7" not-null="true" />
        <!-- 특별시,광역시,도(4) -->
        <property name="sido" length="4" not-null="true" />
        <!-- 시,군,구(15) -->
        <property name="gugun" length="15" not-null="true" />
        <!-- 읍,면,동(26) -->
        <property name="dong" length="26" not-null="true" />
        <!-- 리(18)  -->
        <property name="ri" length="18" />
        <!-- 건물명(40) -->
        <property name="bldg" length="40" />
        <!-- 시작번지(11) -->
        <property name="stBunji" column="st_bunji" length="11" />
        <!-- 끝번지(9) -->
        <property name="edBunji" column="ed_bunji" length="9" />
    </class>
</hibernate-mapping>


들어가기 전에 테스트 소스는 아래와 같습니다.
public class App {

    public static void main(String[] args) {
        Session sess = HibernateUtil.getCurrentSession();
        Transaction tx = sess.beginTransaction();

        // processing
  
        tx.commit();
        HibernateUtil.closeSession();
    }
 
    // Zipcode 객체가 들어있는 List를 출력
    private static void display(List<Zipcode> list) {
  
        try {
            int size = list.size();
   
            if(size == 0) {
                throw new Exception("리스트가 없습니다.(0건)");
            }
      
            for(int i=0 ; i < size ; i++) {
                System.out.println(list.get(i).toString());
            }
   
        } catch (NullPointerException e) {
            System.out.println("리스트가 존재하지 않습니다.");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}




SELECT

select * from tbl_zipcode
Criteria crit = sess.createCriteria(Zipcode.class);
List<Zipcode> zipcodeList = crit.list();

select seq, zipcode, st_bunji, ed_bunji from tbl_zipcode
Criteria crit = sess.createCriteria(Zipcode.class);
  
ProjectionList projectionList = Projections.projectionList();
projectionList.add(Projections.id().as("seq"));
projectionList.add(Projections.property("zipcode").as("zipcode"));
projectionList.add(Projections.property("stBunji").as("stBunji"));
projectionList.add(Projections.property("edBunji").as("edBunji"));
  
crit.setProjection(projectionList);
crit.setResultTransformer(new AliasToBeanResultTransformer(Zipcode.class));
  
List<Zipcode> zipcodeList = crit.list();
 
원하는 칼럼을 뽑아낼 때 쓰는 ProjectionListProjections을 사용합니다.(테이블 하나 조회하면서는 안쓸듯...)

해보니까 Projections 에서 꼭 as() 를 사용해서 Zipcode 클래스의 필드명과 이름을 맞춰줘야 하더군요... -0-/

Projections.id() 와 Projections.property() 는 뭐가 다른지 아시겠죠? ㅎㅎ;; id() 가 PK가 되는 필드 입니다.


select count(*) from tbl_zipcode
Criteria crit = sess.createCriteria(Zipcode.class);
crit.setProjection( Projections.rowCount() );
  
List<Integer> zipcodeList = crit.list();
System.out.println("count : " + zipcodeList.get(0));

select count(seq) as count from tbl_zipcode
Criteria crit = sess.createCriteria(Zipcode.class);
crit.setProjection(Projections.count("seq").as("count"));
   
List<Integer> zipcodeList = crit.list();
System.out.println("count : " + zipcodeList.get(0));




ORDER BY

select * from tbl_zipcode order by seq desc
Criteria crit = sess.createCriteria(Zipcode.class);
crit.addOrder(Order.desc("seq"));
   
List<Zipcode> zipcodeList = crit.list();

Order.asc(String propertyName) 도 있습니다~ +_+




Criteria crit = sess.createCriteria(Zipcode.class);
List<Zipcode> zipcodeList = crit.list();

생략하겠습니다~


WHERE

where문은 Restrictions을 사용합니다. 내용이 많으니 자세한것은 API를 봐주세요~

select * from tbl_zipcode where seq = 1555
crit.add(Restrictions.eq("seq", 1555));

select * from tbl_zipcode where seq = 45
crit.add(Restrictions.idEq(45));    // idEq() 를 사용하면 PK 칼럼으로 검색합니다.

select * from tbl_zipcode where dong like '방화%'
crit.add(Restrictions.like("dong", "방화", MatchMode.START));    // '방화%'

MatchMode 종류는 ANYWHERE, END, EXACT, START 4가지 종류가 있습니다.

딱 보면 아시겠지만 '%방화%', '방화%', '방화', '%방화' 이렇게 됩니다.


select * from tbl_zipcode where sido = '서울' and zipcode like '157%'
crit.add(Restrictions.eq("sido", "서울"));
crit.add(Restrictions.like("zipcode", "157", MatchMode.START)); 

여러개의 조건을 사용할 때에는 계속 .add() 해주면 됩니다.


select * from tbl_zipcode where where (st_bunji = '514' and sido = '서울' and dong = '방화2동')
Map<String, String> m = new Hashtable<String, String>();
m.put("sido", "서울");
m.put("dong", "방화2동");
m.put("stBunji", "514");
  
crit.add(Restrictions.allEq(m));

여러개의 eq를 사용할 경우 Map 을 사용할 수 있습니다.


select * from tbl_zipcode where seq >= 5300
crit.add(Restrictions.ge("seq", new Integer(50300)));

주의 해야 할 것은 2번째 인자는 Object 형태라는 것입니다. +_+;

ge(>=), gt(>), le(<=), lt(<) 가 있습니다.

    select * from tbl_zipcode where sido in ('서울', '부산')
    String[] in = {"서울", "부산"};
    crit.add(Restrictions.in("sido", in));    // Collection 또는 Object[] 사용 가능

    select * from tbl_zipcode where ( sido = '서울' and zipcode like '157%' )
    crit.add(
        Restrictions.conjunction()    // and 연산으로 그룹
            .add( Restrictions.eq("sido", "서울") )
            .add( Restrictions.like("zipcode", "157", MatchMode.START) )
    );

    and 조건을 여러개 사용할 경우 그냥 계속 .add() 해도 되지만 Restrictions.conjunction() 로 그룹할 수 있습니다.

    Restrictions.conjunction() 은 and 로 그룹하고, Restrictions.disjunction() 은 or 로 그룹합니다.


    select * from tbl_zipcode where ( (dong like '방화%' or dong like '%1동') and (zipcode like '157%' or zipcode like '431') )
    crit.add(
        Restrictions.conjunction()
            .add(
                Restrictions.disjunction()
                    .add(Restrictions.like("dong", "방화", MatchMode.START))
                    .add(Restrictions.like("dong", "1동", MatchMode.END))
            )
            .add(
                Restrictions.disjunction()
                    .add(Restrictions.like("zipcode", "157", MatchMode.START))
                    .add(Restrictions.like("zipcode", "431", MatchMode.START))
            )
    );

    - 동이 '방화'로 시작하거나 '1동'으로 끝나고 우편번호가 157로 시작하거나 431로 시작하는 데이터를 조회 합니다.
    - (동이 '방화'로 시작 or 동이 '1동'으로 끝) and (우편번호가 '157'로 시작 or 우편번호가 '431'로 시작)

    정도가 되겠네요... (헷갈리.. ㅠㅠ)


    select * from tbl_zipcode where st_bunji between '157' and '158'
    crit.add(Restrictions.between("stBunji", "157", "158"));

    select * from tbl_zipcode where ( dong like '방%' and dong like '%1동' )
    crit.add( Restrictions.and( Restrictions.eq("sido", "서울"), Restrictions.like("dong", "1동", MatchMode.END) ) );

    Restrictions.and(조건, 조건) 은 두개의 조건을 and 로 그룹합니다.
    Restrictions.or(조건, 조건) 은 두개의 조건을 or 로 그룹합니다.


    select * from tbl_zipcode where not ( sido in ('서울', '부산') )
    crit.add( Restrictions.not( Restrictions.in("sido", new String[] { "서울", "부산" }) ) );





    GROUP BY

    ProjectionListProjections을 사용합니다

    select sido, count(sido) as sidoCount from tbl_zipcode group by sido
    // 각 시도별 우편번호 갯수를 카운트
    ProjectionList projectionList = Projections.projectionList();
    projectionList.add( Projections.alias( Projections.count("sido"), "sido_count") );   // count(sido) as sido_count
    projectionList.add( Projections.groupProperty("sido").as("sido") );    // group by sido
      
    crit.setProjection(projectionList);
    crit.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
      
    List<Map<String, Object>> list = crit.list();
      
    for(int i=0 ; i < list.size() ; i++) {
        Map<String, Object> m = (Map<String, Object>) list.get(i);
        System.out.println(m);
    }

    Projections.groupProperty(String propertyName) 을 이용해서 GROUP BY 를 하고

    crit.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP); 는 조회해서 나온 결과를 Map 형태로 변환해 줍니다.

    이렇게 나온 결과가 Zipcode 클래스 자체 형태가 아니라면 Map 으로 변환해서 처리하면 됩니다.


    ※ groupPropery(String propertyName) 과 groupProperty(String propertyName).as(String alias) 와는 차이가 있습니다.

    select count(sido) as sido_count from tbl_zipcode group by sido
    projectionList.add( Projections.groupProperty("sido") );

    // 결과
    {sido_count=2800}
    {sido_count=8170}
    {sido_count=3614}
    {sido_count=4921}


    select count(sido) as sido_count, sido from tbl_zipcode group by sido
    projectionList.add( Projections.groupProperty("sido").as("sido") );    // sido 가 select 칼럼에 추가
    // 결과
    {sido=강원, sido_count=2800}
    {sido=경기, sido_count=8170}
    {sido=경남, sido_count=3614}



    여러 칼럼으로 GROUP BY 하려면 똑같이 Projections.groupProperty() 를 추가 하면 됩니다.

    select sido, gugun, count(sido) as sidoCount from tbl_zipcode group by sido, gugun
    // 각 시도별 우편번호 갯수를 카운트
    ProjectionList projectionList = Projections.projectionList();
    projectionList.add( Projections.alias( Projections.count("sido"), "sido_count") );   // count(sido) as sido_count
    projectionList.add( Projections.groupProperty("sido").as("sido") );    // group by sido
    projectionList.add( Projections.groupProperty("gugun").as("gugun") );    // group by gugun


    ※ 다른 WHERE(또는 다른 것들..)과 같이 쓸때 Projections에서 alias를 다른 이름으로 사용해야 합니다.

    crit.add(Restrictions.eq("sido", "서울"));
      
    // 각 시도별 우편번호 갯수를 카운트
    ProjectionList projectionList = Projections.projectionList();
    projectionList.add( Projections.alias( Projections.count("sido"), "sido_count") );   // count(sido) as sido_count
    projectionList.add( Projections.groupProperty("sido").as("sido") );    // group by sido

    select count(sido) as sido_count, sido from tbl_zipcode where sido = '서울' group by sido

    정도의 쿼리를 예상 했지만 실제로 해보면 잘못된 쿼리라는 에러가 납니다.

    이유는 하이버네이트에서 쿼리를 만들때 내부적으로 alias 를 사용하는데,

    select count(this_.sido) as y0_, this_.sido as y1_ from tbl_zipcode this_ where y1_=? group by this_.sido

    위와 같은 쿼리가 나오게 됩니다. 이상하죠? ㅎㄷ;;

    crit.add(Restrictions.eq("sido", "서울"));
      
    // 각 시도별 우편번호 갯수를 카운트
    ProjectionList projectionList = Projections.projectionList();
    projectionList.add( Projections.alias( Projections.count("sido"), "sido_count") );   // count(sido) as sido_count
    projectionList.add( Projections.groupProperty("sido").as("g_sido"));    // group by sido

    // 결과
    {g_sido=서울, sido_count=7807}

    위와 같이 Projections 에서 다른 alias 를 사용하면 where 문의 칼럼이 제대로 나옵니다.

    select count(this_.sido) as y0_, this_.sido as y1_ from tbl_zipcode this_ where this_.sido=? group by this_.sido





    HAVING

    having 은 Criteria 에서 지원이 안되는 것 같습니다. HQL 을 사용하면 되겠지만 쿼리문을 쓰기 싫으므로...

    열시미 찾아서 having 이 지원되게 수정(3.1 rc1 버젼) 된 라이브러리를 찾았습니다! (찾았는데 오류나서 개인적으로 수정 -_-)

     - 수정된 java 파일 입니다.

     - 하이버네이트 jar 에 통합시킨 파일입니다. ( 3.2.4.GA + 수정된 java(3.1 rc1) )


    수정 된 부분은 Criteria 클래스에서 public Criteria addHaving(Criterion criterion); 메소드가 추가되었습니다.


    select count(sido) as sido_count, sido from tbl_zipcode group by sido having sido in ('서울', '경기', '부산')
    ProjectionList projectionList = Projections.projectionList();
    projectionList.add( Projections.alias( Projections.count("sido"), "sido_count") );
    projectionList.add( Projections.groupProperty("sido").as("g_sido"));
      
    crit.addHaving( Restrictions.in("sido", new String[] {"서울", "경기", "부산"}) );    // having sido

    // select count(this_.sido) as y0_, this_.sido as y1_ from tbl_zipcode this_ group by this_.sido having this_.sido in (?, ?, ?)
    {g_sido=경기, sido_count=8170}
    {g_sido=부산, sido_count=3287}
    {g_sido=서울, sido_count=7807}



    이 group by 와 having 부분은 이것저것 해보면 아시겠지만 제약(?)이 있군요.. ㅠ_ㅠ

    select count(sido) as sido_count, sido, gugun from tbl_zipcode group by sido, gugun having count(sido) > 500

    이거 할 줄 아시는분... 젭알!!!!!!! ㅠ_ㅠ





    간단히 우편번호 검색하는 걸 만들어 봤습니다. ㄷㄷ;


    반응형

    'Framework > Hibernate' 카테고리의 다른 글

    PK 두개 이상시 매핑  (2) 2009.12.24
    Reverse Engineering  (0) 2009.12.24
    Hibernate 시작하기  (0) 2009.12.23
    Criteria 사용하여 질의 하기 #2  (1) 2009.10.03
    다대다(n:m) 관계 설정하기  (0) 2009.09.02
    일대다(1:n) 관계 설정하기  (1) 2009.08.31
    일대일(1:1) 관계 설정하기  (0) 2009.08.27
    하이버네이트(Hibernate) 사용하기  (6) 2009.08.24
    //

    *.jsp 접근 막기

    Posted at 2009. 9. 3. 09:29 | Posted in Framework/Struts
    반응형
    struts 사용시 *.jsp 접근을 막기 위한 설정입니다.

    web.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="......ID" ...... version="2.5">
        <display-name>many-to-many_mysql</display-name>
            <welcome-file-list>
                <welcome-file>index.html</welcome-file>
                ...
        </welcome-file-list>

        <!-- 웹으로 접속한 사용자가 JSP 파일로 직접 접근할 수 없게 한다. -->
        <security-constraint>
            <web-resource-collection>
                <web-resource-name>PreventViewingJSPs</web-resource-name>
                <description>웹으로 접속한 사용자가 JSP파일로 직접 접근할 수 없도록 한다.</description>
                <url-pattern>*.jsp</url-pattern>
                <http-method>GET</http-method>
                <http-method>POST</http-method>
            </web-resource-collection>
            <auth-constraint>
                <role-name></role-name>
            </auth-constraint>
        </security-constraint>

    </web-app>


    반응형

    'Framework > Struts' 카테고리의 다른 글

    스트러츠(Struts) 기본 세팅  (6) 2009.06.22
    Struts 파일 업로드  (2) 2009.05.05
    //

    다대다(n:m) 관계 설정하기

    Posted at 2009. 9. 2. 11:05 | Posted in Framework/Hibernate
    반응형
    이번에는 사람과 세미나 사이의 다대다(n:m) 관계를 설정해보겠습니다. ^^;;

    사람은 여러개의 세미나를 등록할 수 있고, 세미나는 여러 사람이 올 수 있죠~

    Java 1.6.0_15
    Eclipse 3.5
    Hibernate 3.3.2.GA
    Apache Tomcat 6.0.18
    MySQL 5.1 (HSQLDB 1.9.0 rc4)



    사람(Person)과 세미나(Person) 을 매핑 합시다~

    Person.java
    package com.tistory.antop;

    public class Person {

        private int seq;
        private String name;
        private Gender gender;
     
        private enum Gender {
            남, 여
        }
     
        // constructor, getter and setter (private setter seq)
    }

    Person.hbm.xml
    <hibernate-mapping package="com.tistory.antop">
        <class name="Person" table="tbl_person">
            <id name="seq">
                <generator class="native" />
            </id>
      
            <property name="name" />
            <property name="gender" />
      
        </class>
    </hibernate-mapping>


    Seminar.java
    package com.tistory.antop;

    import java.util.Date;

    public class Seminar {

        private int sid;
        private String title;
        private Date sDate = new Date();
        private String area;

        // constructor, getter and setter (private setter sid)
     }

    Seminar.hbm.xml
    <hibernate-mapping package="com.tistory.antop">
        <class name="Seminar" table="tbl_seminar">
            <id name="sid">
                <generator class="native" />
            </id>
      
            <property name="title" />
            <property name="sDate" column="s_date" />
            <property name="area" />
      
        </class>
    </hibernate-mapping>


    hibernate.cfg.xml
    <hibernate-configuration>
        <session-factory>
            ...

            <!-- Mapping -->
            <mapping resource="com/tistory/antop/Person.hbm.xml" />
            <mapping resource="com/tistory/antop/Seminar.hbm.xml" />

        </session-factory>
    </hibernate-configuration>


    관계가 맺어지지 않은 테이블이 매핑 되었습니다~



    이제 n:m 관계를 맺어봅시다~

    논리적(생각)으로는 두 테이블이 n:m 관계가 나오지만, 물리적(실제)으로는 n:m 관계를 만들려면 두 테이블을 이어줄 테이블이 하나 더 껴들어가야 합니다... ㅠ_ㅠ




    클래스와 매핑 XML 에 n:m 관계(양방향)를 추가 합시다.

    서로를 n 개만큼 참조해야하므로 Set 으로 하겠습니다.


    Person.java
    package com.tistory.antop;

    import java.util.HashSet;
    import java.util.Set;

    public class Person {
       
        ...

        // person n:m seminar
        private Set<Seminar> seminars = new HashSet<Seminar>();

        public Set<Seminar> getSeminars() {
            return seminars;
        }

        public void setSeminars(Set<Seminar> seminars) {
            this.seminars = seminars;
        }

        // 세미나 등록
        public void addSeminar(Seminar s) {
            this.seminars.add(s);
        }
        
        // 세미나 취소
        public void cancelSeminar(Seminar s) {
            this.seminars.remove(s);
        }
    }

    Person.hbm.xml
    <hibernate-mapping package="com.tistory.antop">
        <class name="Person" table="tbl_persons">
            ...

            <!-- person n:m seminar -->
            <set name="seminars" table="tbl_persons_seminars">
                <key column="seq" />
                <many-to-many class="com.tistory.antop.Seminar" column="sid" />
            </set>
     
        </class>
    </hibernate-mapping> 

    <set name="seminars" table="tbl_persons_seminars">
       java.util.Set 을 사용 했고 담고있을 필드는 seminars, n:m 관계를 맺어주는 테이블명은 tbl_persons_seminars

    <key column="seq" />
       자기 테이블(Person)의 FK(Foreign Key) 되는 칼럼명입니다.

    <many-to-many class="com.tistory.antop.Seminar" column="sid"  />
      m 관계를 맺게되는 테이블(tbl_seminar)의 클래스명과 그쪽의 FK가 되는 칼럼명입니다.


    Seminar 쪽도 마친가지로 매핑해 줍니다.

    Seminar.java
    package com.tistory.antop;

    import java.util.HashSet;
    import java.util.Set;

    public class Seminar {

        // person n:m seminar
        private Set<Person> persons = new HashSet<Person>();

        // 누가 이 세미나에 신청 했는지 알기위해 getter 만 public
        public Set<Person> getPersons() {
            return persons;
        }

        @SuppressWarnings("unused")
        private void setPersons(Set<Person> persons) {
            this.persons = persons;
        }
     
        // 사람(person)이 세미나 등록, 취소를 할 수 있다고 보고 세미나를 기준으로 등록 삭제는 없슴!
    }

    Seminar.hbm.xml
    <hibernate-mapping package="com.tistory.antop">
        <class name="Seminar" table="tbl_seminars">

            ...  

            <!-- person n:m seminar -->
            <set name="persons" table="tbl_persons_seminars">
                <key column="sid" />
                <many-to-many class="com.tistory.antop.Person" column="seq" />
            </set>
      
     </class>
    </hibernate-mapping>




    테스트 해봅시다~

    request.getParameter() 안쓰려고 스트러츠 썻는데 더 꼬여뿌렀네용 -_-;;

    하이버네이트 부분은 dao 에 있습니다.




    반응형

    'Framework > Hibernate' 카테고리의 다른 글

    PK 두개 이상시 매핑  (2) 2009.12.24
    Reverse Engineering  (0) 2009.12.24
    Hibernate 시작하기  (0) 2009.12.23
    Criteria 사용하여 질의 하기 #2  (1) 2009.10.03
    Criteria 사용하여 질의 하기 #1  (4) 2009.09.10
    일대다(1:n) 관계 설정하기  (1) 2009.08.31
    일대일(1:1) 관계 설정하기  (0) 2009.08.27
    하이버네이트(Hibernate) 사용하기  (6) 2009.08.24
    //