데이터 일괄 삭제 작업과 관련해 transaction을 이용해 처리하는 stored procedure가 있었다.
로직을 좀 변경한 뒤에 테스트를 하려고 하는데, 다 지워버리면 다시 테스트하기가 어려워 transaction을 걸고 테스트 후 rollback할 생각으로 테스트를 했는데...
예상과는 다르게 trasaction이 rollback이 되지 않는 것이었다. --;;
원인은 drop table!!
fk가 걸린 테이블이 있어 지우고자 하는 원본 데이터를 임시테이블에 담아 지우는 로직이 있는데, 거기서 기존 임시테이블 남아있으면 안되서, drop table을 하고 있었는데 이 drop table문의 경우에는 transaction이 시작되면 기존 transaction을 commit하고 수행해버린 것이다.
ORDER BY 구문을 이용할 때 아래와 같이 order 방식을 다르게 SELECT를 할 필요가 있는 경우가 있다.
SELECT *
FROM tablename
ORDER BY A DESC, B ASC, C ASC
위와 같이 쿼리를 날리게되면, index를 만들 때 A,B,C 컬럼에 composit index가 생성이 되어 있더라도, 정렬이 모두 DESC나 ASC로 되어 있다면 결국 index를 제대로 활용 못하고 filesort가 나게 된다.
도움말을 찾아보면 아래와 같이 INDEX 생성 시점에 columnname [ASC | DESC] 와 같이 정렬 순서를 컬럼별로 줄 수 있다고 써있다.
CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
[index_type]
ON tbl_name (index_col_name,...)
[index_option ...]
index_col_name:
col_name [(length)] [ASC | DESC]
index_type:
USING {BTREE | HASH | RTREE}
index_option:
KEY_BLOCK_SIZE value | index_type | WITH PARSER parser_name
그래서 실제로 적용해 봤는데, 그래도 계속 filesort가 발생해서 도움말을 좀 더 읽어봤더니... 역시나 --;;
An index_col_name specification can end
with ASC or DESC. These
keywords are allowed for future extensions for specifying ascending or
descending index value storage. Currently, they are parsed but ignored; index
values are always stored in ascending order.
Prefix lengths are storage engine-dependent (for example, a prefix can be up to 1000 bytes long for MyISAM tables, 767 bytes for InnoDB tables). Note that prefix limits are measured in bytes, whereas the prefix length inCREATE INDEX statements is interpreted as number of characters for non-binary data types (CHAR, VARCHAR,TEXT). Take this into account when specifying a prefix length for a column that uses a multi-byte character set. For example, utf8 columns require up to three index bytes per character.
참고로 InnoDB의 index page size는 16Kb이다. (컬럼의 길이가 너무 길면 index 자체도 별 효과가 없을 수 있으니 제한을 두는건 맞는 것 같은데. 767이라는 제한은 어디서 온걸까 싶어서.. 대충 256*3하면 768인데...)
역시나 별로 관심 없지만 뭐가 바뀌었는지 궁금하긴 한 사람들을 위해 중요 point만 정리해볼까 합니다.
가장 큰 변화
Lucene 2.4.0 includes index format changes that are not readable by older versions of Lucene. Lucene 2.4.0 can both read and update older Lucene indexes. Adding to an index with an older format will cause it to be converted to the newer format.
index format을 또(과거 2.1.0에서 한번 변경 되었다.) 변경하셨다. 그래서 이전 버젼으로 만든 lucene서버에서는 새 index format을 읽을 수 없다. 당연하지만 새 버젼으로 만든 lucene으로는 기존 버젼의 index를 읽을 수 있지만...
기타 변화들 중 중요한 변화를 change log에서 뽑아볼까 했으나 이미 여기에 정리가 다 되어 있는 것 같아서 그냥 한글로만 정리해 볼까 합니다.
- "InstantiatedIndex"라는 class가 생겼는데, 기존의 RAMDirectory보다 훨씬 빠르다고 한다. 테스트 해 봐야겠네요.
- IndexWrite가 indexing 중에 OS의 문제나 갑자가 power가 꺼져도 index가 깨지지 않는다고 한다. 이건 맘에 들지만.. 여지껏 index가 깨지는 걸 경험하질 못해서... --;;
- LUCENE-997 : 검색 시 시간 제약을 둘 수 있게 되었다. 특정 시간이 넘어가지 않도록... 해당 시간이 넘어가면 "TimeExceeded Exception"를 발생시킨다고 한다. 이걸 외부에서 wrapping해서 처리한다고 삽질했던 기억이....
- NIOFSDirectory : to allow multiple threads to read from the same open file without locking. 이걸 쓰면 퍼포먼스가 좀 향상될라나??
- "now the filter is applied to a document before scoring is done" : 예전엔 filter로 거르기 전에 scoring을 다 했었나보네요 --;; filter 쿼리가 많이 빨라지지 않았을까요? 아이고 궁금해라...
- "IndexReader can be opened with new readOnly=true mode" : IndexReader를 readOnly모드로 열면 multithread환경에서 보다 나은 성능을 기대할 수 있다는데... 그럼 IndexSearcher를 그냥 만들면 알아서 readonly 모드로 열릴라나... 이것도 테스트 해봐야겠네요~
소스 받아서 확인해 봤는데... IndexSearcher를 생성하면 내부적으로 알아서 IndexerReader를 readonly로 생성하는군요.
public IndexSearcher(String path) throws CorruptIndexException, IOException {
this(IndexReader.open(path), true);
}
위에 나열한 변화 외의 변화들도... 평소의 변화들에 비해는 조금 큰 변화이니 처음 접하는 분들이야 그냥 쓰면 되겠지만 예전부터 사용하는 분들은 꼼꼼히 살펴보는 게 좋을 것 같네요~
오늘 lucene 홈페이지 들어갔다가 알게됐다. 2월 14일에 새 release가 발표됐다.
lucene으로 프로그래밍 한 지 좀 지나서 또 가물가물 해졌지만... 그래도 관심이 있어 좀 읽어 봤는데, 몇 가지 내용만 정리해 봤다.
Changes * 's'와 't'가 StopAnalyzer(StandardAnalyzer에서도 사용됨)의 stopword에서 제거됨. * StandardAnalyzer의 CJK에 대한 unicode code point ranges가 update됐다.(CJ와 K로 분리됨) * WildcardQuery의 queryString에 ? 나 *가 포함되어 있지 않으면 알아서 TermQuery를 수행한다. 이전 버젼의 경우에는 StringIndexOutOfBoundsException이 발생했었다 * deprecated되었던 doc.fields() 와 Enumeration을 제거 * write lock 파일이 Index directory에 생성됨. 이전에는 "org.apache.lucene.lockDir" or "java.io.tmpdir"였음. - 첨엔 write lock이 어디 있는지 몰라 헤맸었는데, 찾기 쉬워진 듯
New Feature * ThaiAnalyzer와 ThaiWordFilter가 추가됨 - 태국어쪽 작업하는 사람은 별로 없겠지만... 요즘 게임업체는 태국에 많이 진출했으니, 그 업체들에서 CS 툴의 검색 기능을 lucene으로 붙일 수 있을 듯 ^^'' * NGramTokenizer와 EdgeNGramTokenizer class 추가됐고, unit test를 통과 - cjk analyzer는 특정 unicode 범위에 대해서는 2-gram 방식인걸로 알고 있는데, NGram을 응용하면 보다 나은 검색 시스템을 만들 수 있을까??? * IndexWriter에 document를 update(내부적으로는 delete then add)할 수 있는 method추가 - 귀찮게 delete했다가 add할 것 없이 바로 update할 수 있으니 조금 편할 듯
일단은 내가 직접 해 본, list control, datagrid control에 대해 간략히 정리해 보면...
동적으로 두 control들에 넣을 데이터를 담을 data class를 정의한다.
1. DataGrid control
public class Bookmark {
public var tags:String;
public var description:String;
public var time:String;
public function Bookmark (pTags:String, pDesc:String, pTime:String)
{
tags = pTags;
description = pDesc;
time = pTime;
}
}
이렇게 Bookmark라는 class를 정의하고,
var b1:Bookmark = new Bookmark("tag1, tag2", "bookmark1", "2006-01-01");
var b2:Bookmark = new Bookmark("tag3, tag1", "bookmark2", "2006-01-11");
var tagArray:Array = new Array();
tagArray.push(b1);
tagArray.push(b2);
grid1.dataProvider = tagArray;
이렇게 해 주면 된다. 그런데 여기서 실제 datagrid에는 세개의 컬럼이 있는데 어떤 컬럼에 어떤 데이터를 보여주는지는 datagrid를 넣은 XML에서 설정할 수 있다.
2. List Control
list control의 경우 객체 배열을 data provider로 지정했을 경우, 화면 출력에 사용하는 컬럼의 설정은 default로는 label이라는 이름을 먼저 찾고, 별도로 지정하고자 할 경우에는 아래와 같이 labelField를 지정하면 된다.
SQL Server 2000까지는 없던 내용이라 SQL Server 사용자는 생소할 만한 object에 대해 간단히 소개해 볼까 합니다.
SYNONYM : 동의어, 유의어
아직 제대로 번역된 글을 보지 못해 한글로는 어떻게 표현해야 할지 궁금하지만... 유사객체(?)ㅋㅋ (인포믹스에서는 동의어라고 하나보네요. - 출처)
뜻만으로 미뤄 짐작해보면 alias(별칭)과 유사한 그런 개념입니다.
엔진 차원에서 이렇게 만들어진 object를 어떻게 관리하는지를 정확히는 모르는 관계로 deep한 내용은 건너뛰고...
문법은 간략히 설명하자면 CREATE SYNONYM name FOR objectName
object에 올 수 있는 것은 도움말을 참조하시고... 대략 stored procedure류, view, table 등이 올 수 있습니다.
유의할 점은... 생성시 대상이 되는 object가 존재하지 않아도 된답니다. 실행 시 object의 여부를 check한다고 하네요.
SYNONYM은 local, remote object 모두에 만들 수 있습니다.
그럼 이런 넘은 어디에 쓰라고 만들었을까?? 함 고민해 봤는데..
처음엔 원격 DB table에 check constraint(관계설정)을 걸 수 있을 줄 알았는데, 여기를 보니 그건 안된다고 나와있네요 --;; 해보진 않아서 아는 사람한테 해 보라고 부탁만 해 놨지만..
You cannot reference a synonym in a DDL statement. For example, the following statements, which reference a synonym named dbo.MyProduct, generate errors:
ALTER TABLE dbo.MyProduct
ADD NewFlag int null;
EXEC ('ALTER TABLE dbo.MyProduct
ADD NewFlag int null');
The following permission statements are associated only with the synonym and not the base object:
GRANT
DENY
REVOKE
Synonyms are not schema-bound and, therefore, cannot be referenced by the following schema-bound expression contexts:
CHECK constraints
Computed columns
Default expressions
Rule expressions
Schema-bound views
Schema-bound functions
그럼 도대체 어디에 쓸까???
함 생각해봤는데...
이미 구축된 database를 물리적으로 여러대로 분산할 때, program source를 전혀 고치지 않고 분리가 가능할거 같더라구요. 분리된 database object에 대해 실제 program에 사용되는 database object name과 동일한 synonym만 만들어 주면 되니까요.
또 뭐가 있을까???
생각나는게 없네요 --;; 오라클에는 원래 있었던 기능이라니 혹시 또 다른 좋은 쓰임새를 아시는 분은 덧글 부탁드립니다.
(추가) Synonym의 쓰임새
SQL Server 2005 adds the capability to create synonyms for database objects, which simplifies the readability of the queries that use objects outside of their own schema (that is, objects with multipart names). Synonyms can also be used to create a level of abstraction over their base objects, thus enabling the easy switching of base objects without affecting the code that references them.
(출처 : http://www.informit.com/articles/article.asp?p=364263&seqNum=3&rl=1)
1. 가독성을 높혀준다.
2. 쉽게 실제 object를 교체 가능하므로 해당 object를 참조하는 코드에 영향을 주지 않는다.
라는 이점이 있다네요.
(추가2) 글 쓰고나니 계속 더 찾아지는 article들... 이 기사에서는 'Synonyms as an Abstraction Layer'라고 표현하는데.. 아주 적절한 표현인 것 같네요.
OS : Microsoft Windows 2000 Server / Advanced Server
SQL : Microsoft SQL Server 2000 Standard / Enterprise Edition
그동안 Oralce을 많이 이용했었습니다.
저의 개념으로 이해가 안되는 부분이 있어서 질문드립니다.
현재 제가 아는 System이 MS SQL Server 2000 Standard를 사용하고 있는데
원인은 정확히 파악할 수 없으나 수시로(LOCK)이 걸린다고 합니다.
Strored Procedure는 몇개 이용하고 있습니다. 이 SP는 스케쥴러(작업)에 의해 Call되어지고 있구요...
해결책으로 애플리케이션이든 SP든 모든 Query에 (NOLOCK)을 추가해 주었더군요.
DB를 알고있는 관계자들이
"MS SQL Server는 기본적으로 Select문을 날리면 Lock이 걸린다"
"Default다"
라고들 합니다.
책을 찾아보고 인터넷을 뒤져봐도 이런내용은 없는것 같은디...
맞는 이야기인지,
맞다면 왜 단순 Select문을 던지는데 기본적으로 Lock을 잡아야 하는지 답변 좀 부탁 합니다.
----------------------------------------
대학원에서 간단히 테이블 한 두개 만들어 놓고 VB로 연결해서 DB Programming을 해 본게 전부라 오라클에 대한 지식이 거의 없는터라 오라클에서 왜 그렇게 동작하는지 정말 그런지 뭐 그런건 잘 모른채 SQL Server의 격리 수준에 대한 내용이 생각나서 답변해 주기위해 좀 더 검색해 보며 내가 알고 있는 내용을 정리하던 중, 오라클과 SQL Server의 병행제어 방법이 다르다는 것을 알게 되었다.
혹 관심이 있는 분들이나 나 자신을 위해 간단히 정리해 보려 합니다.
처음 위 질문을 보고, 'SQL Server의 기본 isolation level이 read committed니가 그런거겠지... 그럼 Oracle은 그게 아닌가?'라고 생각하고 Oracle쪽을 찾다가 다음과 같은 글을 보았습니다.
'SQL Server와 Oracle의 격리와 병행제어에는 차이가 있습니다....'
그래서 당연히 default isolation level이 달라서 나타나는 차이라고 생각하고 답글을 올려버렸습니다. --;; (사실 상당히 주의하고 답글을 올리는 편임에도 불구하고 실수를 했죠).
그리고 이 내용에 흥미가 생겨 블로그에 정리하다가 그게 아니라는걸 알게되었습니다.
다시 검색하다가 아래의 내용을 보았습니다.
'The default isolation level for Oracle is read committed'
쩝 --;; 그럼 isolation level이 같은데 왜 그럴까?? 차이는 병행제어 알고리즘의 차이입니다.
데이터의 일관성과 데이터의 동시성
여러 가지 정의가 있겠지만, Oracle 9i의 교재에서는 다음과 같이 정의하고 있습니다.
Data concurrency means that many users can access data at the same time.
Data consistency means that each user sees a consistent view of the data, including visible changes made by the user's own transactions and transactions of other users.
동시성이란 다수의 사용자가 동시에 데이터에 접근할 수 있어야 한다는 의미이고, 일관성이란, 각각의 사용자가 자신의 트랜잭션이나 다른 사람의 트랜잭션에 의해 변경된 내용을 포함하여 일관된 값을 본다라는 의미라고 합니다.
다수의 사용자가 데이터베이스에 동시에 접근하게 될 경우, 각각의 사용자가 다른 데이터에 접근을 한다면 문제 없겠지만, 같은 데이터에 접근을 한다면 잘못된 데이터의 변경을 막기 위해선 반드시 어떠한 제어를 해 주어야 합니다.
그것이 병행 제어(concurrency control)입니다.
대학원 수업시간에 배운 내용 중 기억 나는 부분만 소개하자면...
병행 제어 알고리즘은 다음과 같은 분류의 알고리즘이 있습니다.
* 낙관적 병행제어 알고리즘 : 다른 사용자가 동시에 같은 데이터에 접근할 경우가 적다고 보고 구현한 알고리즘
* 비관적 병행제어 알고리즘 : 낙관적과는 반대로 다른 사용자가 동시에 같은 데이터에 접근할 경우가 많다고 보고 구현한 알고리즘
위의 내용은 머리속에 남은 조그마한 지식의 일부분이고..
대학원때 배웠던 교제 중, Distributed Systems Concepts and Design 이라는 책에 나온 내용을 소개하자면,
병행제어 알고리즘에는 다음과 같은 것 들이 있습니다.
1. Locking (비관적 병행제어 알고리즘)
2. optimistic concurrency control (낙관적 병행제어 알고리즘)
3. timestamp ordering (비관적 병행제어 알고리즘)
각 알고리즘에 대한 소개는 skip하고 ^^''
SQL Server에서 사용하는 병행제어 알고리즘은 Locking입니다.
그러나 Oracle에서 사용하는 병행제어 알고리즘은 일반적인 Locking과는 조금 다릅니다. Oracle에서는 Multiversion Concurrency Control이라고 말하는 방법을 사용하는데, 중요한 것은 SQL Server와 다른 알고리즘을 사용 한다는 것입니다.
아래의 내용은 첨부된 문서의 내용 중 일부입니다.
오라클의 잠금 정책 요약입니다.
* 오라클은 변경의 경우에만 테이블의 행단위로 잠금을 한다. 블록이나테이블 수준으로잠금을 확대하지는 않는다.
* 오라클은 단지 데이터를 읽기 위해서 잠금을 하지 않는다. 즉, 간단한 읽기에 의한 데이터 행들에 잠금을 두지는 않는다.
* 데이터 기록기(writer)는 데이터 판독기(reader)를 방해하지 않는다. 즉, 읽기는 쓰기에 의해서 방해받지 않는다. 이는 기본적으로 읽기가 쓰기에 의해서 차단되는 거의 모든 다른 데이터베이스들과 구별된다.
* 데이터 기록기는 다른 데이터 기록기가 먼저 접근하고자 하는 데이터에 대해서 잠금을 했을 때에만 차단된다.
* 데이터 판독기는 데이터 기록기에 의해서 전혀 차단되지 않는다.
그러므로, SQL Server에서는 read T가 write T와 충돌이 발생하여, 둘 중 하나의 T는 blocking이 걸리게 되지만, Oracle에서는 read T와 write T가 서로 충돌하지 않습니다.
Historically, the concurrency control model in SQL Server at the server level has been pessimistic and based on locking. While locking is still the best concurrency control choice for most applications, it can introduce significant blocking problems for a small set of applications.
The biggest problem arises when locking causes the writer-block-reader or reader-block-writer problem. If a transaction changes a row, it holds exclusive locks on the changed data. The default behavior in SQL Server is that no other transactions can read the row until the writer commits. Alternatively, SQL Server supports ‘read uncommitted isolation’, which can be requested by the application either by setting the isolation level for the connection or by specifying the NOLOCK table hint. This nonlocking scan should always be carefully considered prior to use, because it is not guaranteed to return transactional consistent results.
간단히 정리해 보면...
"SQL Server는 병행제어 모델로 비관적 알고리즘인 locking을 사용해 왔다. locking은 아직까지 대부분의 application에서 병행제어 방법으로는 가장 좋은 방법이긴 하지만 작은 규모의 application에서 중요한 blocking 문제를 야기시킬 수 있다.
가장 큰 문제점은 locking이 writer-block-reader 혹은 reader-block-writer의 원인이 되는 것이다. 기본적으로 SQL Server에서는 writer가 commit하기 전까지 어떤 트랜잭션도 row를 읽을 수 없다. 대신 application에서 isolotion level을 지정하거나 NOLOCK 테이블 힌트를 이용해 요청할 수 있는 'read uncommitted isolation'을 지원한다. 일관성 있는 결과를 보장하지 않으므로 이런 방법으로 locking하지 않은 채 사용하는 것은 주의해야 한다."
대략 정리했는데, 큰 틀은 맞겠지만 소소하게 틀린 부분은 많을테니 잘못된 부분 지적해 주시면 감사하고 이해하고 보시거나 ㅋㅋ
나머지는 시간날 때 날 잡고...
그리고 Oracle 최신 버전에는 혹시 다른 변화가 있는지도 같이 한번...
Oracle 10i의 메뉴얼 중 Concurrency Control 관련 부분 메뉴얼은 여기
파일은
특정 조건을 AND로 추가해서 Query할 수도 있고,
특정 조건을 Filter로 추가해서 Query할 수도 있다.
총 검색되는 갯수는 같지만, 간단하지만 보이지 않는 차이를 정리해 보면...
* AND로 검색을 하면 score에 해당 내용이 반영이 되어 정확도로 정렬할 경우 해당 내용이 반영된다.
* AND로 검색을 하면 별로도 추가로 검색을 하는 것이므로, 부하가 있는 쿼리의 경우는 AND조건 검색보다 Filter로 걸러내는 것이 속도가 빠르다. (검색된 것들 중에서 filtering을 하는 것이니 당연히 빠르겠죠? 전체 인덱스의 크기가 크면 클 수록 and query를 이용한 것 보다 훨씬 빠를테니까요.)
조금 더 자세히 몇 가지를 설명하자면...
Lucene in Action과 현재 licene 2.0 버젼이 filter 부분이 차이가 좀 있는데
DateFilter라는건 없어졌다.
그리고 내 경우는 기존에 사용하던 Filter도 있어서...
추가로 한가지 Filter를 추가한 case라서..
주로 MS-SQL에서 작업을 하다, mysql에서 처음으로 stored procedure(이하 sp)를 만들면서, 5분이면 될 것을 수십분은 걸린 것 같다 --;;
에러가 정확한 위치를 알려주질 않는다.
아래의 정리한 내용은 MS-SQL에 익숙하고 mysql을 사용해 보지 않은 분이 보면 무자게 도움이 될 것 같다.
- IF문을 쓸 때 END IF문이 있어야 하며, END IF문 뒤에는 ;를 붙여야 한다.
ex> IF (test IS NULL) THEN
SELSET 'ok';
END IF;
- auto increment값을 얻어올 때는 LAST_INSERT_ID()을 이용한다.
ex> SET serverId = LAST_INSERT_ID();
- CREATE PROCEDURE문 전에 delimeter문을 이용해 delimeter를 ';'가 아닌 다른 걸로 변경하고 뒤에 다시 변경할 것
ex> delimiter // # delimeter를 //로 변경
CREATE PROCEDURE xxx
.....
.....
END;
// # 실제 한 command가 종료됨을 의미
CREATE PROCEDURE getServerId(ip VARCHAR(15), OUT serverId tinyint)
BEGIN
SELECT id INTO serverId FROM tServer WHERE serverIp = ip;
END;
//
delimiter ;
- mysql에서는 ;가 command의 종료를 의미하는데 stored procedure의 경우 여러 query의 조합이라 중간에 ;가 들어갈 수 있는데, 그러면 문법 오류로 간주되므로 delimiter를 임시로 다른 걸로 바꾼 후 sp를 만들고 다시 예전 delimiter로 변경하는 것임.
lucene을 이용해 검색을 구현할 때, 검색어에 lucene에서 사용하는 특수기호를 넣으면, 잘못 반영 될 소지가 있어, lucene에서 사용하는 특수 기호들에 대해서는 escape(기호 앞에 \를 추가)을 해 줘야 한다.
정규식을 이용해 간단하게 구현했는데, Lucene in Action 책을 보니 sandbox에 있는 js를 참고하라고 해서 홈페이지에 가 보니 없었다.
결국 알고보니 api에 추가가 되었다.
QueryParse.escape();
나 처럼 뻘짓하는 분 없기를...
but....
http://lucene.apache.org/java/docs/queryparsersyntax.html
여기 가 보면 lucene에서 사용하는 특수기호들에 대한 설명이 나와 있다.
'+ - && || ! ( ) { } [ ] ^ " ~ * ? : \'
그런데 lucene의 escape 코드를 보면 '&&'와 '||'은 빠져 있다. (2007년 6월 19일 발표된 2.2.0버젼에서 bugfix 되었습니다.)
직관적으로 이해 하겠지만 search value에 &&는 and로 ||는 or로 변환되어 처리되므로,
실제 &&나 ||를 검색해야 하는 경우 코드를 따다 수정해서 사용해야 할 듯.
실제 lucene 코드
public static String escape(String s) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
// NOTE: keep this in sync with _ESCAPED_CHAR below!
if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '(' || c == ')' || c == ':'
|| c == '^' || c == '[' || c == ']' || c == '\"' || c == '{' || c == '}' || c == '~'
|| c == '*' || c == '?') {
sb.append('\\');
}
sb.append(c);
}
return sb.toString();
}
현재 아래의 언어들에 대한 reference를 제공한다. C, C++, CSS, HTML, HTML DOM, Java, JavaScript, MySQL, Perl, PHP, and Ruby
더 좋은 점은 실제 doc문서를 바로 보여준다. ajax를 이용해 해당 사이트의 내용을 바로 보여주는 듯...
프로그래밍 할 때 이용할 수 있는 자동 완성 기능이 구현되어 정확히 모르고 찾을 때도 매우 유용할 듯.
* 오늘 날짜 구하기
- new Date();
- Calendar now = Calendar.getInstance();
now.getTime();
* 어제 날짜 구하기
Calendar now = Calendar.getInstance();
now.add(Calendar.DAY_OF_MONTH, -1);
now.getTime();
* 날짜 포맷을 원하는 형태로 바꾸기
Calendar now = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.format(now.getTime()); // 결과는 String
* 지 맘데로의 날짜를 담은 문자열을 다른 형태로 convert
String dateStr = "200707211541122"; SimpleDateFormat oldFormat = new SimpleDateFormat("yyyyMMddHHmmss"); SimpleDateFormat newFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
1. 객체를 이용하여 저장하는 방법
Transaction tx = session.beginTransaction();
Cafe cafe = new Cafe();
cafe = new Cafe();
cafe.setId(Id);
cafe.setName(name);
session.save(cafe);
tx.commit();
2. key 값을 이용해 값이 존재하는지 확인한 후 저장하는 방법
Session session = HibernateUtil.getCurrentSession();
if (existCafe == null) {
Transaction tx = session.beginTransaction();
Cafe cafe = new Cafe();
cafe = new Cafe();
cafe.setId(id);
cafe.setName(name);
session.save(cafe);
tx.commit();
System.out.println("inserted");
}
else{
System.out.println("already exist");
}
HibernateUtil.closeSession();
3. key가 아닌 값을 이용해 존재하는지 확인한 후 저장하는 방법
* createQuery 안의 문장은 SQL Query가 아니라 Hibernate에서 사용하는 HQL(Hibernate Query Language) 이다.
* 자세한 문법은 http://www.hibernate.org/hib_docs/v3/reference/ko/html/queryhql.html
Keyword k = (Keyword) session.createQuery(
"select k from Keyword as k where keyword = ?").setString(0,
keyword).uniqueResult();
if (k == null) {
Transaction tx = session.beginTransaction();
Keyword kw = new Keyword();
kw.setKeyword(keyword);
4. 자동 증가값 받기
* 걍 강제 casting
int id = (Integer) session.save(kw);
5. DB의 identity 컬럼 관련 XML 설정
<?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="net.daum.cafe.search.weblog.entity">
<class name="Keyword" table="tKeyword">
<id name="id" column="id">
<generator class="identity" />
</id>
<property name="keyword" type="string" column="keyword" />
</class>
</hibernate-mapping>
6. 복합키 관련 XML 설정
<?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="net.daum.cafe.search.weblog.entity">
<class name="DTBC" table="tableD">
<composite-id>
<key-property name="Id" type="int" column="Id" />
<key-property name="keywordId" type="int" column="keywordId" />
</composite-id>
<property name="count" type="int" column="count" />
</class>
</hibernate-mapping>
* 참고 : 복합키를 구현하려면 Serializable을 반드시 implements해 주어야 한다. 그렇지 않으면 'composite-id class must implement Serializable' 예외가 발생한다.