MySQL 설치 후 처음으로 로긴하기

참조 : http://itn.pe.kr/ttools/1

MySQL을 yum 설치하고나서 접속을 시도합니다.

mysql -u root -p

기본으로 root의 암호는 공백이니까 그냥 엔터를 칩니다. 그런데.. 들어가지지는 않고 에러가 나옵니다.

ERROR 2002 (HY000): Can’t connect to local MySQL server through socket ‘/var/lib/mysql/mysql.sock’ (2)

아.. 이 끔찍한 에러. 이전에도 몇 번 만난적이 있는데, 그 때 잘 정리해 두지 않고 어찌저찌해서 접속 한 다음에 그냥 사용하고 있다가 다시 오랜만에 서버에 깔다가 만나니.. 참으로 난감한 에러입니다.

1. 프로세스가 돌고 있지 않아서 에러가 납니다. 그럼 프로세스를 돌려줍니다.  mysqld (MySQL 데몬)을 실행하면 되는데, 이 파일이 여러군대에 있더군요. 그중에서 저는

/usr/local/mysql/bin/mysqld_safe –user=mysql&

이렇게 하니까 동작 됐습니다.
Starting mysqld daemon with databases from /usr/local/mysql/var 이런 메시지가 출력됩니다.

2. 그 다음 다시 로그인을 시도하면 또 똑같은 에러가 나타납니다. 이번에는 링크를 만들어 줍니다.
temp 폴더에 생성되는 sock 파일을 mysql이 원츄하고 있는 이름으로 심볼릭 링크를 만들어 줍니다.

ln -s /tmp/mysql.sock /var/lib/mysql/mysql.sock

3. 이제 끝. 이제는 로그인이 됩니다.

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1 to server version: 5.0.26

Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the buffer.

mysql>

Persistence context 확장하기

특징

  • 요청을 처리한 다음에 Persistent context를 닫지 않고 DB Connection을 끊은 상태에서
    사용자의 다음 요청을 기다린다. 사용자의 다음 요청이 오면 다시 DB에 연결하고 다음 요청을 처리한다. Conversation이
    끝나면, Persistent context를 DB에 동기화하고, 닫는다. 다음 Conversation을 시작할 때는 새로운
    Persistence context를 시작하고, 이전 Conversation에서 사용했던 entity 객체들을 재사용하지 않는다.
  • Detached 상태의 객체가 없다. 모든 객체는 Transient 상태이거나 Persistent 상태다.
  • 손수 reattachment 하거나 merging할 필요가 없다.
  • 이 책의 나중에 두 가지 Conversation 구현 전략에 대해 자세하게 다룰 것이다.

The identity of detached objects

특징

  • Reference to a detached object: 객체의 레퍼런스가 identity를 보장받는 범위를 벗어나는 것을 말한다.
  • Set Collection에 객체들을 담을 때, 동일한 주키로 읽어들인 Detached 상태의 객체와
    Persistent 상태의 객체는 모두 동일한 레코드를 나타내는 것들이기 때문에, 이전 예제에서 다음의 코드의 결과 Set에는
    하나의 객체만 들어가야 한다.
Set<Member> members = new HashSet<Member>();
members.add(loadedMember1);
members.add(loadedMember2);
members.add(loadedMember3);

assertEquals(1, members.size());
  • 그러나..2개가 들어가있다. loadedMember1과 loadedMember2는 같은 레퍼런스를 가지고
    있으니까, loadedMember2는 추가되지 않고, loadedMember3는 전혀 다른 레퍼런스를 가지고 있기 때문에 추가
    된다.
  • Set에 add()를 할 때, equals()로 비교를 하는데, Object 클래스에서 equals()를 ==으로 구현해 두었기 때문에 그렇게 된다.
  • 따라서 위의 결과가 1이 되게 하려면, equals()와 hashCode()를 재정의 해주어야 한다.

equals()와 hashCode() 이해하기

  • Detached 상태의 객체를 Set에 집어넣는 일이 절대로 없다면, 굳이 equals()와 hashCode()를 구현하지 않아도 된다.
  • Conversation 구현 전략으로 Extended Persistence Context를 선택하고 Detached 상태의 객체들을 애플리케이션에 제거하면 된다.
  • 이렇게 하면 당연히 Persistence Context도 Conversation으로 확장되었으니, Scope of Object identity의 범위도 Conversation으로 확장된다.
  • equlas()를 재정의 하면 반드시 hashCode()도 재정의 해야 한다. 왜? 같은 객체들은 반드시 같은 해시코드를 반환해야 하니까.

Data identity 비교하기

@Override
public boolean equals(Object other) {
if (this == other)
return true;
if (id == null)
return false;
if (!(other instanceof Member))
return false;
final Member that = (Member) other;
return this.id.equals(that.getId());
}

@Override
public int hashCode() {
return id == null ? System.identityHashCode(this) : id.hashCode();
}
  • 비추하는 방법니다.
  • Transient 객체를 Set에 넣은 다음에, Session.save()를 사용해서 Persistent
    상태로 바꾸면 Set에 포함되어 있는 상태에서 hashCode 값이 바뀌게 된다. 이것은 Set의 제약을 위반하게 되는 것이다.
    왜 그럴까? 생각해보자. 0이라는 hashCode를 가진 녀석이 Set에 들어간 다음에 1로 바꼈다. 그러면 나중에 1이라는
    hashCode를 가진 녀석을 Set에 집어 넣으면 어떻게 될까? 처음에 0을 가지고 있다가 1로 바뀐 녀석은 사라지고, 뒤에
    추가된 객체만 남아있을 것이다.(테스트 코드로 확인해 볼 것.)

주키 속성을 제외한 모든 속성을 비교하기

@Override
public boolean equals(Object other) {
if (this == other)
return true;
if (!(other instanceof Member))
return false;
final Member that = (Member) other;
if (!this.getName().equals(that.getName()))
return false;
return true;
}

@Override
public int hashCode() {
int result = 14;
result = 29 * result + getName().hashCode();
return result;
}
  • 콜렉션은 비교하지 않는다. 객체 하나의 동일성을 확인하려고 전체 객체 맵을 확인할 필요는 없으니까.
  • 단점1: 같은 레코드를 표현하는 두 개의 객체가 서로 다른 Session에서 존재하다가 누군가 속성을 바꾸면 그 둘은 다른 객체가 되버린다.
  • 단점2: 서로 다른 DB indentity를 가진 객체들이 같은 객체로 취급될 여지가 있다.

비즈니스 키를 사용해서 구현하기

  • business key: 각 개체들마다 유일한 값을 가지는 속성이나 속성들의 집합. natural primary key와 다른 점은 바뀔 수 있다는 것이다.
  • Entity 클래스에는 반드시 business key가 있어야 한다고 주장한다. 심지어 그 키가 개체의 모든 속성을 포함하는 것일지라도.(보통 immutable 클래스가 그렇다.)
  • surrogate key가 DB와 application이 사용하는 것이라면, business key는 사용자가 단일 레코드를 식별하기 위해 사용하는 것들이다.
@Override
public boolean equals(Object other) {
if (this == other)
return true;
if (!(other instanceof Member))
return false;
final Member that = (Member) other;
if (!this.email.equals(that.getEmail()))
return false;
return true;
}

@Override
public int hashCode() {
return email.hashCode();
}
  • 위에서 언급했던 모든 문제가 해결된다.
  • equals() 메소드에서 other객체의 속성에 접근할 때, .으로 바로 접근할 수 있는데도 굳이 gette를 사용하는 이유? 프록시 일수도 있기 때문에…

참조할 것

The Scope of Object Identity

특징

  • Java identity: a==b
  • Database identity: x.getId().equals(y.getId())
  • Scope of object identity: Java Identity와 Database identity모두 보장되는 상태.

Scope of object identity 종류

  • No identity scope: 하나의 DB 레코드가 같은 자바 객체로 여러번 애플리케이션으로 반환되든지
    말든지 신경 안 쓴다. 문제가 생긴다. (만약에 두 개의 객체가 하나의 레코드를 표현하고 있는데, 그 두 개의 객체의 정보를
    수정하면, DB에는 어떤 객체의 변화를 반영해야 하는가? 어떻게 하든 둘 중 하나는 손실 되겠군.)
  • Persistence context-scoped identity: 단일 Persistence context
    내부에서는 오직 하나의 객체만이 하나의 DB 레코드를 표현할 수 있도록 보장한다. 위에서 언급했던 문제가 없어지고 context
    레벨에서의 cache를 보장할 수 있다.
  • Process-scoped identity: 한 단계 더 나가서, 전체 JVM 프로세스 내부에서 오직 하나의 객체만이 하나의 DB 레코드를 표현할 수 있다.
  • 하이버는 persistence context-scope으로 구현했다.

Persistence context-scope 예제

@Test
public void persistenceContextScope() throws Exception {
Session session = sessionFactory.openSession();
Member member = new Member();
session.save(member);
Long memberId = member.getId();

Member loadedMember1 = (Member) session.get(Member.class, memberId);
Member loadedMember2 = (Member) session.get(Member.class, memberId);

// Java Identity In Persistence Context
assertTrue(loadedMember1 == loadedMember2);
// DB Identity In Persistence Context
assertTrue(loadedMember1.getId().equals(loadedMember2.getId()));
session.flush();
session.close();

Session session2 = sessionFactory.openSession();
Member loadedMember3 = (Member) session2.get(Member.class, memberId);

// Java Identity Out Persistence Context
assertFalse(loadedMember1 == loadedMember3);

// DB Identity Out Persistence Context
assertTrue(loadedMember1.getId().equals(loadedMember3.getId()));

session2.flush();
session2.close();
}
  • Persistent Context 내에서는(Persistent 상태) 같은 주키로 가져온 객체는 Java identity와 DB identity 모두 동일하다.
  • 하지만 Detached 상태의 객체와 Persistence 상태의 객체의 Java Identity는 보장되지 않는다. 물론 이 때도 주키 속성은 가지고 있으니까 DB Identity는 보장된다.
  • Detached 상태의 객체를 가지고 작업하는 것는 위와 같이 Scope of Object identity가 보장되지 않는 상태에서 작업하는 것이다.

Conversation 소개

특징

  • Persistence를 사용하는 여러 화면에 걸쳐 사용자의 요청을 처리해야 하는 경우.
  • 두 가지 구현 방법이 있다.

Detached Object를 이용하는 방법

  • session-per-request-with-detatched-objects
  • Persistent context는 오직 하나의 요청을 처리하는 동안만 지속되고, Detached 상태의
    객체들은 Conversation 내부에서는 계속해서 reattach하거나 merge를 해서 다시 Persistent 상태로
    만들어서 사용한다.

Persistence context를 확장하는 방법

  • session-per-conversation
  • Persistent context를 전체 작업의 단위로 확장시킨다.