[JAVA 로만 이용(]
 
public static void main(String[] args) {
	
	JavaMailSender sender = getSender();
	/*
	SimpleMailMessage msg = new SimpleMailMessage();
	msg.setTo("ddakker@~");
	msg.setSubject("제목");
	msg.setFrom("ddakker@~");
	msg.setText("내용");
	sender.send(msg);
	*/
	
	MimeMessage msg = sender.createMimeMessage();
	MimeMessageHelper helper;
	try {
		helper = new MimeMessageHelper(msg, true, "UTF-8");
		helper.setSubject("제목");
		helper.setTo("ddakker@~");
		helper.setFrom("ddakker@~");
		helper.setText("내용", true);
		sender.send(msg);
	} catch (MessagingException e) {
		e.printStackTrace();
	}
    
}

private static JavaMailSenderImpl getSender(){
	JavaMailSenderImpl sender = new JavaMailSenderImpl();
	sender.setHost("도메인 및 아이피");
	sender.setUsername("계정 아이디");
	sender.setPassword("비밀번호");
	
	Properties props = new Properties();
	props.put("mail.smtp.auth", "true");
	
	sender.setJavaMailProperties(props);
	return sender;
}

[JAVA 와 Spring DI 와 함께 이용]

	
		${mailHost}
	
	
		${mailAdminId}
	
	
		${mailAdminPwd}
	
	
		
			true
		
	
 

 
JavaMailSender sender = (JavaMailSender) getBean("sender");

MimeMessage msg = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(msg, true, "UTF-8");
helper.setSubject(p_subject);
helper.setTo(p_to);
helper.setFrom(p_from);
helper.setText(p_message, true);
sender.send(msg);

1 : [Config] Table
     boardCode PK
N: [Board] Table
     BoardCode FK

Board를 조회 할 경우 항상 Config와 함께 JOIN이 필요 할 경우 Config Class 는 특별한 설정이 필요 없다.
Config 조회 할경우에는 단순히 Config 만 조회한다.

Board Class
     boardCode 변수를 생성할 필요 없다.


 
// fetch=FetchType.LAZY: 요청할때만 JOIN한다.,  EAGER: 무조껀 JOIN한다.
// cascade=CascadeType=ALL, MERGE, PERSIST, REFRESH, REMOVE
@ManyToOne(fetch=FetchType.LAZY, cascade = {CascadeType.REMOVE}, targetEntity=Config.class )
@JoinColumn(name = "boardCode")
@ForeignKey(name = "FK_CONFIG_BOARD_CODE")
private Config config; // getter, setter 만들어준다.


JOIN 시 FK로 Where을 걸 경우
 
Session session = getSession();
		
Criteria crit = session.createCriteria(Board.class, "B");
crit.createCriteria("Config", "C");
crit.add(Restrictions.eq("C.boardCode", boardCode));
crit.setFirstResult(firstIndex);
crit.setMaxResults(pageSize);
crit.addOrder(Order.desc("regdate"));
발송 시 "550 5.7.1 Unable to relay for" 이와 같은 메시지가 발생한다면,

SMTP 속성 - 액세스 - 릴레이 제한 - "아래 목록만 제외"를 체크한다.
표준 
event.target
element.addEventListener(name, observer, useCapture);

IE
event.srcElement
element.attachEvent('on' + name, observer);
wget -c http://lug.mtu.edu/ubuntu/pool/main/g/gcc-3.3/libstdc++5_3.3.6-10_i386.deb
dpkg -x libstdc++5_3.3.6-10_i386.deb libstdc++5
cp libstdc++5/usr/lib/libstdc++.so.5.0.7 /usr/lib 
ln -s libstdc++.so.5.0.7 libstdc++.so.5


Eclipse Subversion 계정정보 경로(XP)

C:\Documents and Settings\계정\Application Data\Subversion\auth\svn.simple


Repository 등록된 갯수 만큼 파일이 존재 한다.

메모장 같은 것으로 열어서 확인 후 삭제 하면 된다.

			/**
			 * component	표시할 컴포넌트
			 * message		툴팁 메시지
			 * position		툴팁 위치 default: right ect:top,bottom
			 * 해당 컴포넌트에 툴팁을 표시한다.
			 */
			private function showToolTip(component:UIComponent, message:String, position:String="right") : void {
				
				var toolTip : * = ToolTipManager.createToolTip("" , 0,0);
				toolTip.setStyle("fontSize", 12);
				toolTip.setStyle("styleName", "errorTip");
				toolTip.text = message;
				
				var objPoint : Point;
				if( position == "right" ){
					toolTip.setStyle("borderStyle", "errorTipRight");
					objPoint = component.localToGlobal(new Point(component.stage.x+component.width, component.stage.y));
				}else if( position == "top" ){
					toolTip.setStyle("borderStyle", "errorTipAbove");
					objPoint = component.localToGlobal(new Point(component.stage.x, component.stage.y - component.height*2));
				}else if( position == "bottom" ){
					toolTip.setStyle("borderStyle", "errorTipBelow");
					objPoint = component.localToGlobal(new Point(component.stage.x, component.stage.y + component.height));
				}

				var objTMetrix:TextLineMetrics	=component.measureText(message);
				
				toolTip.move(objPoint.x, objPoint.y);
				toolTip.setActualSize(objTMetrix.width+40, objTMetrix.height);
				toolTip.setVisible(true);
				
				component.addEventListener(Event.CHANGE, function(event:Event){
					if( toolTip ){
						ToolTipManager.destroyToolTip(toolTip);
						toolTip = null;
					}
				});
			}

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();
 
원하는 칼럼을 뽑아낼 때 쓰는 ProjectionList와 Projections을 사용합니다.(테이블 하나 조회하면서는 안쓸듯...)

해보니까 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[] { "서울", "부산" }) ) );


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



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페이지의 내용을 보여주게 됩니다. 


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


 pagination.war


몇개의 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_



소스상에서 직접 호출이 아닌 특정 문자열을 획득 및 다이나믹하게 조합한 문자열의 함수를 호출 하고자 할때 이용한다.
(commons-beanutils-1.7.0.jar 파일 필요) 

ActionScript3 에서는 간단히 처리할 수 있는 방법이지만 java에서는 약간 볶잡한 것 같다.


	public String execute(){
		String voidTest = (String) MethodUtils.invokeMethod(this, "testFun", null);
		System.out.println("voidTest: " + voidTest);
			
		Object arr[] = new Object[2];
		arr[0] = 1;
		arr[1] = "str";
		String paramTest = (String) MethodUtils.invokeMethod(this, "testFun", arr);
		System.out.println("paramTest: " + paramTest);
	}

	public String testFun(){
		System.out.println("Test1Action.testFun()");
		return "zzzz";
	}
	
	public String testFun(int test, String str){
		System.out.println("Test1Action.testFun(int test=" + test + ", String str=" + str + ")");
		return "zzzz";
	}




[출처] http://www.zeroturnaround.com/jrebel/

+ Recent posts