반응형
Java에서 사용자가 정의한 클래스(Class)를 가지고 서로 같은 것인지 비교해야 할 때가 있다.
Java의 모든 클래스는 Object 클래스를 상속하고, Object 클래스가 기본으로 가지고 있는 메쏘드 중에서 equals와 hashCode가 있다.
예를 들어, 학교의 수업관리 시스템에서 학생(Student) 클래스를 사용한다고 가정하고 Student 클래스를 정의하면:
public class Student {
    private int studentId;
    private String name;
    private String major;
   
    public int getStudentId() {
        return studentId;
    }
    public void setStudentId(int studentId) {
        this.studentId = studentId;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getMajor() {
        return major;
    }
    public void setMajor(String major) {
        this.major = major;
    }
}


위 클래스를 사용하여 아래와 같이 똑같은 학생을 두 개의 다른 인스턴스(instance)로 만들어 비교해 보면:
public static void main(String[] args){
        Student s1 = new Student();
        s1.setStudentId(20101234);
        s1.setName("Gildong Hong");
        s1.setMajor("Computer Science");

        Student s2 = new Student();
        s2.setStudentId(20101234);
        s2.setName("Gildong Hong");
        s2.setMajor("Computer Science");
       
        System.out.println(s1.equals(s2));    // false
}
실행 결과는 false가 나온다.

위 상황에서 두 학생이 학번이 같고 이름도 같고 전공도 같기 때문에 의미상 똑같은 객체라는 것을 Java가 인식할 수 있게 하기 위한 방법이 equals 메쏘드를 override하는 것이다. Student 클래스에 equals를 override하여 구현하면:
public class Student {
    private int studentId;
    private String name;
    private String major;
   
    public int getStudentId() {
        return studentId;
    }
    public void setStudentId(int studentId) {
        this.studentId = studentId;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getMajor() {
        return major;
    }
    public void setMajor(String major) {
        this.major = major;
    }
   
    @Override
    public boolean equals(Object o){
        Student s = (Student) o;
        if(studentId == s.getStudentId()
            && name.equals(s.getName())
            && major.equals(s.getMajor())){
            return true;
        } else {
            return false;
        }
    }
}


이 클래스를 가지고 다시 equals 메쏘드로 위의 s1과 s2를 비교하면 같은 것으로 인식할 수 있다.
하지만 equals만 가지고는 HashMap, HashSet과 같이 key, value의 쌍으로 구성되는 자료구조에서는 제대로 작동하지 않는다. 이 때에는 hashCode 메쏘드를 추가로 override하여 구현하면, Student 클래스의 예와 같이 같은 학번, 이름, 전공을 가진 객체의 경우에는 동일한 key로 간주하도록 할 수 있다.
public class Student {
    private int studentId;
    private String name;
    private String major;
   
    public int getStudentId() {
        return studentId;
    }
    public void setStudentId(int studentId) {
        this.studentId = studentId;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getMajor() {
        return major;
    }
    public void setMajor(String major) {
        this.major = major;
    }
   
    @Override
    public boolean equals(Object o){
        Student s = (Student) o;
        if(studentId == s.getStudentId()
            && name.equals(s.getName())
            && major.equals(s.getMajor())){
            return true;
        } else {
            return false;
        }
    }
   
    @Override
    public int hashCode(){
        String s = ""+studentId+name+major;
        return s.hashCode();
    }
}


public static void main(String[] args){
        Student s1 = new Student();
        s1.setStudentId(20101234);
        s1.setName("Gildong Hong");
        s1.setMajor("Computer Science");

        Student s2 = new Student();
        s2.setStudentId(20101234);
        s2.setName("Gildong Hong");
        s2.setMajor("Computer Science");
       
        HashMap<Student, String> advisors = new HashMap<Student, String>();
        advisors.put(s1, "prof. Kim");              // s1 클래스를 key로 사용
        System.out.println(advisors.get(s2));   // s2 클래스를 key로 사용
}

위 예제는 같은 멤버변수 값을 가질 경우 같은 hashCode를 리턴하도록 hashCode를 override함으로써 s2 인스턴스를 가지고 "prof. Kim"을 얻을 수 있다.


반응형
블로그 이미지

Bryan_

,
반응형
다른 버전 리눅스는 안써봐서 모르겠고,
일단 Ubuntu에는 bash, sh, csh 같은 여러 종류의 쉘이 있다.
사용자 계정을 만들고 로그인했을 때 나타나는 프롬프트의 모양이
사용중인 쉘을 어느정도 알려주는 것 같다.

*대표적인 예:
/bin/sh
$

/bin/bash
[사용자 계정이름]@[시스템 이름]:~$

/bin/csh
%


로그인 후에 다른 쉘을 사용하는 법은 간단하다.
일반적으로 bin 디렉토리가 $PATH에 있기 때문에 바로 쉘 이름으로 실행할 수 있다.
(예) sh를 쓰는 상황에서 bash를 쓰고 싶을 때,
$ bash
usera@superman:~$
usera@superman:~$ exit
$


하지만 리눅스에 로그인할 때마다 뜨는 쉘 대신, 다른 쉘을 쓰고 싶을 때는
매번 로그인 후에 쉘 이름을 다시 입력하는 것은 번거로우므로
(그리고 로그아웃할 때도 exit를 두번 쳐야 하므로-_-)
시작할 때 계정에 연결된 쉘 경로를 바꾸는 것이 편하다.

먼저 시스템에서 현재 사용할 수 있는 쉘의 목록을 보려면:
$ cat /etc/shells
# /etc/shells: valid login shells
/bin/csh
/bin/sh
/usr/bin/es
/usr/bin/ksh
/bin/ksh
/usr/bin/rc
/usr/bin/tcsh
/bin/tcsh
/usr/bin/esh
/bin/dash
/bin/bash
/bin/rbash
/usr/bin/screen

Ubuntu 8.0.4 기준으로 목록이 위와 같고, 실제로 이 쉘들이 다 깔려있지는 않다.
원하는 쉘의 경로를 기억해 두었다가 "chsh" 명령으로 쉽게 바꿀 수 있다.
$ chsh
Password: [계정 암호 입력]
Changing the login shell for usera
Enter the new value, or press ENTER for the default
        Login Shell [/bin/sh]: /bin/bash
$

쉘을 바꿨다고 해서 현재 프롬프트에 바로 적용되지는 않는다.
로그아웃 후 다시 들어가 보면 바뀐 쉘로 로그인됨을 알 수 있다.


반응형
블로그 이미지

Bryan_

,
반응형

간혹 시스템에서 아주 긴~ log파일 같은 것을 확인해야 할 때가 있는데, vi를 굳이 열어서 맨 끝까지 이동하는 것보다는 계속 기록되고 있는 log파일의 맨 끝부분만 화면을 통해 보는 것이 더 편할 때가 있다.
그럴 때는 tail [filename]을 치면 파일의 맨 끝에서부터 10줄을 화면에 보여준다. 보여지는 줄 수를 변경하고 싶으면 -n 옵션을 통해서 조정 가능하다.

$ tail [filename] -n [라인 수]


추가로, 실시간으로 갱신되어 저장되는 로그 파일의 경우에 변경된 내용을 실시간으로 화면상에서 보고 싶으면 옵션에 "-f"를 추가해 준다.

tail [filename] -f -n [라인 수]

반응형
블로그 이미지

Bryan_

,
반응형

파일(sql구문)로 DB 백업:
$ mysqldump -u[사용자] -p[암호] [백업할 데이터베이스 이름] > db091130.sql
참고로 -d 옵션을 주면 데이터 없이 스키마만 백업한다.

생성된 DB가 utf8을 사용하고 있고 데이터에 한글이 포함되었을 때는 가급적
구문을 추가해줄 것.


백업파일로부터 DB 복구:
$ mysql -u[사용자] -p[암호] [복구될 데이터베이스 이름] < db091130.sql

복구할 때 복구될 데이터베이스는 "create database [데이터베이스이름]"에 의해 미리 생성되어 있어야 한다.
반응형
블로그 이미지

Bryan_

,
반응형
만들어진 테이블들:
mysql> create table DEPARTMENT (
    -> DEPT_CD varchar(10) not null,
    -> NAME varchar(30) not null,
    -> PHONE int(11) not null,
    -> primary key(DEPT_CD)
    -> );

desc RESERVATION;
+----------------+-------------+------+-----+---------+-------+
| Field          | Type        | Null | Key | Default | Extra |
+----------------+-------------+------+-----+---------+-------+
| RESERVATION_ID | varchar(10) | NO   | PRI | NULL    |       |
| PATIENT        | int(13)     | NO   | MUL | NULL    |       |
| DEPARTMENT     | varchar(10) | NO   | MUL | NULL    |       |
| DOCTOR         | varchar(5)  | NO   | MUL | NULL    |       |
| DATE           | varchar(10) | NO   |     | NULL    |       |
| TIME           | varchar(10) | NO   |     | NULL    |       |
| TYPE           | varchar(20) | NO   |     | NULL    |       |
| GRANTED        | varchar(10) | NO   |     | NO      |       |
+----------------+-------------+------+-----+---------+-------+



발생한 에러:
mysql> alter table RESERVATION drop column DEPARTMENT;
ERROR 1025 (HY000): Error on rename of '.\db_project\#sql-d0_2' to '.\db_project\reservation' (errno: 150)



또다른 시도:
mysql> alter table RESERVATION drop foreign key DEPARTMENT;
ERROR 1025 (HY000): Error on rename of '.\db_project\#sql-d0_2' to '.\db_project\reservation' (errno: 152)


이 두 경우에 대한 문제의 원인분석:
(1) 일단 foreign key constraint부터 지운 후에 drop column을 하는 것이 정상적인 순서이다.
(2) 그런데 foreign key constraint를 내가 테이블 생성할 때에 지정해 주지 않았다.
(3) 따라서 내부적으로 MySQL이 직접 정해준 foreign key constraint의 이름을 알아내야 한다.


마지막으로 foreign key와 관려하여 에러난 상황을 자세히 보고 싶을 때:
mysql> SHOW INNODB STATUS;


그러면 중간쯤에서 아래와 같은 자세한 설명을 볼 수 있고, 거기서 contraint name을 찾을 수 있다.
------------------------
LATEST FOREIGN KEY ERROR
------------------------
091130 21:10:55 Error in foreign key constraint of table db_project/reservation:

there is no index in the table which would contain
the columns as the first columns, or the data types in the
table do not match the ones in the referenced table
or one of the ON ... SET NULL columns is declared NOT NULL. Constraint:
,
  CONSTRAINT "reservation_ibfk_2" FOREIGN KEY ("DEPARTMENT") REFERENCES "departm
ent" ("DEPT_CD") ON DELETE CASCADE


이제 foreign key constraint와 column name을 차례대로 지워주면 된다.
mysql> alter table reservation drop foreign key reservation_ibfk_2;
Query OK, 0 rows affected (0.05 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table reservation drop column DEPARTMENT;
Query OK, 0 rows affected (0.05 sec)
Records: 0  Duplicates: 0  Warnings: 0

반응형
블로그 이미지

Bryan_

,