태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.


Hibernate의 Criteria를 이용하여 프로그래밍시에

Entity class가 다른 entity를 참조하고 있을 경우에 Sort Ordering을 하기 위하여서는 다음과 같이 해줘야 합니다.


예를 들어서 다음과 같은 코드가 있다고 한다면...

Class A  {
   String someProperty;
   Class B otherObject;
}

Class B {
   String name;
}


A Entity를 select하여 올때 B Class의 name으로 Sorting을 하고 싶다면...

다음과 같이 하면 될것 같으나 해보면 에러가 발생합니다.

Criteria fooCriteria = session.createCriteria(A.class);
fooCriteria.addOrder(Order.asc("otherObject.name"));


실제는 아래와 같이 해줘야 합니다.

Criteria fooCriteria = session.createCriteria(A.class);
fooCriteria.createAlias("otherObject", "otherObjectAlias");
fooCriteria.addOrder(Order.asc("otherObjectAlias.name"));

이런식으로 하는 이유는 inner Join을 발생시켜야 name에 대한 ordering이 가능해지기 때문입니다.
Posted by Breeze.Kang

댓글을 달아 주세요

Spring 3.0을 이미 Project에 적용하고 계신 분들도 있으시리라고 생각합니다.

웹서핑을 하다가 보니 Spring 3.0의 새로운 기능에 대하여 잘 설명하고 있는 자료가 있어서 퍼왔습니다.

2009년 5월에 열린 Java User Group 세미나에서 발표된 자료구요,

원본 출처는 다음과 같습니다.

http://www.intertech.com/UserGroups/JUGPresentation.aspx?TopicID=135

무엇보다 REST URL을 지원해주는 부분이 눈에 띄는 부분입니다.

기존에 이 부분이 지원이 안되서 외부 라이브러리를 사용하거나 직접 구현하여 사용하곤 했었는데,

아주 깔끔하게 이 부분이 적용이 되었네요.

PPT에 그 내용도 설명이 나와있습니다.

한번 읽어보시기 바랍니다.

좀 더 자세한 내용은 아래 링크에서 문서를 보실 수 있습니다.

http://www.epril.com/resources/spring3/reference/html/index.html



Description : Spring MVC is the core component of the Spring Framework's web strategy. It provides a robust, flexible framework for building web applications built on the Model 2 architecture. In this presentation, Bob McCune will provide an overview of the new features and capabilities of Spring MVC including its @Controller annotations, REST support, and new data validation integrations.

Spring MVC 3
Posted by Breeze.Kang

댓글을 달아 주세요


Effective Java에 나오는 내용이긴 합니다만, 우리가 자주 저지르는 실수가 있습니다.

프로그램을 하다가 보면 자주 난수(Random number)를 발생시켜야 할 때가 있습니다.

아래와 같은 코드를 사용하여 많이 발생을 시키죠.


private static final Random rnd = new Random();

static int random(int n) {
   return Math.abs(rnd.nextInt()) % n;
}


논리적으로는 아무런 문제가 없어 보입니다.

그렇지만 실제적으로 다음과 같은 코드를 사용하여 테스트를 해보도록 합시다.

public static void main(String[] args) {
   int n = 2 * (Integer.MAX_VALUE / 3);
   int low = 0;
   for (int i = 0; i < 1000000; i++)
       if (random(n) < n/2)
           low++;
   System.out.println(low);
}

위의 코드데로라면  100만번 테스트를 해서 기준값보다 작은 수가 나오는 경우는 50% 가깝게 나와야 정상입니다.

그렇지만 실제로 돌려보면 항상 666,666에 가까운 수가 나옵니다.

난수가 제대로 발생하고 있지 않다는 이야기죠.

실제적으로 이런식의 버그는 찾아내기가 쉽지 않습니다.

로직상으로는 아무런 문제가 없기 때문이죠.


따라서 저런 프로그램으로 Load Balancing하거나 데이터를 분산하고 있다면 제대로 처리가 되고 있지 않을 것입니다.

java 1.2부터 추가된 Random.nextInt(int) 를 사용하거나,  apache commons의 RandomUtils.nextInt()를 사용해야 제대로 동작을 합니다.



Posted by Breeze.Kang

댓글을 달아 주세요


Java Object를 XML로 변환하고자 할때 과거에는 포맷에 맞춰서 XML을 일일이 출력해주는 방식도 사용을 했었다.

그렇지만 굉장히 노가다이고, 짜증나는 작업이 아닐수 없다. 

이런 노가다를 줄이기 위하여 Java Object를 XML로 변환해주는 많은 툴들이 나와있다.

그중에 가장 많이 사용되는 것이 JAXB(Java Architecture for XML Binding) 이다.

Using JAXB

기본적인 지식을 얻고 싶다면 아래의 주소에서 확인을 하자.
http://java.sun.com/developer/technicalArticles/WebServices/jaxb/


Maven을 사용하고 있다면 Pom.xml에 Dependency를 추가하여 필요한 라이브러리를 다운받자. 

         <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.0.5</version>
        </dependency>


Java annotation을 사용하여 편리하게 어떤 내용을 XML에 포함 시킬것인가 말것인가, 그리고 어떤 이름으로 XML에 표현할 것인가를 나타낼 수 있다.


아래 예제 소스는 Hibernate Entity class로써 DB table에 매핑되는 데이터를 나타낸다.

굵은 글쓰로 나타낸것이 JAXB에서 참조하는 annotation이다.

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;


@Entity
@Table(name="vct")
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Vct extends AbstractEntity<Long>{
   
    /**
     *
     */
    private static final long serialVersionUID = 8595404797996134818L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
   
    @ManyToOne(targetEntity = VctInfo.class, optional = false)
    @JoinColumn(name = "vctinfo_id", nullable = false, updatable = false)
    @org.hibernate.annotations.ForeignKey(name = "fk_vct_vctinfo")
    private VctInfo vctinfo;
   
    @ManyToOne(targetEntity = Uct.class, optional = false)
    @JoinColumn(name = "uct_id", nullable = false, updatable = false)
    @org.hibernate.annotations.ForeignKey(name = "fk_vct_uct")
    private Uct uct;
   
    @Column(name = "name", length = 100, nullable = false)
    private String name;
   
    @Column(name="vct_parentid" , nullable=true)
    private Long vctParentId;
   
    @Column(name="sort_order" , nullable=false)
    private Integer sortOrder;
   
    @Column(name="visible" , nullable=false)
    private CategoryVisible visible;
   
    @Column(name="moved" , nullable=false)
    private CategoryMoved moved;
   
    @Column(name="shortcut" , nullable=false)
    private CategoryType shortcut;
   
    @Column(name="hierachy" , length=1024, nullable=false)
    private String hierachy;
   
    @Column(name="hierachyStr" , length=1024, nullable=false)
    private String hierachyStr;   

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public VctInfo getVctinfo() {
        return vctinfo;
    }

    public void setVctinfo(VctInfo vctinfo) {
        this.vctinfo = vctinfo;
    }

    public Uct getUct() {
        return uct;
    }

    public void setUct(Uct uct) {
        this.uct = uct;
    }
   
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Long getVctParentId() {
        return vctParentId;
    }

    public void setVctParentId(Long vctParentId) {
        this.vctParentId = vctParentId;
    }

    public Integer getSortOrder() {
        return sortOrder;
    }

    public void setSortOrder(Integer sortOrder) {
        this.sortOrder = sortOrder;
    }

    public CategoryVisible getVisible() {
        return visible;
    }

    public void setVisible(CategoryVisible visible) {
        this.visible = visible;
    }

    public CategoryMoved getMoved() {
        return moved;
    }

    public void setMoved(CategoryMoved moved) {
        this.moved = moved;
    }

    public CategoryType getShortcut() {
        return shortcut;
    }

    public void setShortcut(CategoryType shortcut) {
        this.shortcut = shortcut;
    }

    public String getHierachy() {
        return hierachy;
    }

    public void setHierachy(String hierachy) {
        this.hierachy = hierachy;
    }
   
    public String getHierachyStr() {
        return hierachyStr;
    }

    public void setHierachyStr(String hierachyStr) {
        this.hierachyStr = hierachyStr;
    }

    @Override
    public boolean equals(final Object other) {
        if (!(other instanceof Vct))
            return false;
        Vct castOther = (Vct) other;
        return new EqualsBuilder().append(id, castOther.id).isEquals();
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this).append("id", id).append("vctinfo",
                vctinfo).append("uct", uct).append("vctParentId", vctParentId)
                .append("sortOrder", sortOrder).append("visible", visible)
                .append("moved", moved).append("shortcut", shortcut).append(
                        "hierachy", hierachy).append("hierachyStr", hierachyStr).toString();
    }
}


이 Entity class를 XML로 변환하고 싶다고 한다면 다음과 같이 해주면 된다.

        JAXBContext context = JAXBContext.newInstance(Vct.class);
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        m.marshal( vct, response.getWriter());

물론 vct에는 어떤 값이 들어있어야 한다.


이 Vct라는 class의 List값을 출력하고 싶을때는 다음과 같은 List용 class를 생성한다.

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "vcts")
@XmlAccessorType(XmlAccessType.FIELD)
public class VctList {

    @XmlElement(name = "vct")
    protected List<Vct> vcts;

    public List<Vct> getVctList() {
        if (vcts == null) {
            vcts = new ArrayList<Vct>();
        }
        return this.vcts;
    }

    public void setVctList(List<Vct> vcts) {
        this.vcts = vcts;
    }
}

VctList라는 class는 Vct의 리스트를 가지고 있는 class이고,

annotation으로 vcts라는 이름으로 XML의 root element를 만든다고 나타냈다.

아래의 class는 Spring의 View interface를 구현하여 웹상에서 xml을 바로 볼수 있게 해줄 목적으로 만들었다.

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

import org.springframework.web.servlet.View;


public class VctXmlView implements View {

    private Object modelKeyName;

    public VctXmlView(Object key) {
        modelKeyName = key;
    }

    @Override
    public String getContentType() {
        return "text/xml;charset=utf-8";
    }

    @SuppressWarnings("unchecked")
    @Override
    public void render(Map model, HttpServletRequest request,
            HttpServletResponse response) throws Exception {

        if (model == null) {
            return;
        }
        response.setContentType(getContentType());
        List<Vct> vcts = (List<Vct>) model.get(modelKeyName);
        VctList vctList = new VctList();
        vctList.setVctList(vcts);

        if (vcts == null) {
            return;
        }

        JAXBContext context = JAXBContext.newInstance(VctList.class);
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        m.marshal(vctList, response.getWriter());

    }
}

실행한 결과는 다음과 같다.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<vcts>
<vct>
<id>1</id>
<vctinfo>
<country>
<id>1</id>
<name>KR</name>
  </country>
<createUser>
<email></email>
<name></name>
<password></password>
<readLevel></readLevel>
<writeLevel></writeLevel>
  </createUser>
<createdAt>2009-05-18T15:05:51+09:00</createdAt>
<description></description>
<language>
<description>한국어</description>
<name>Ko</name>
</language>
            <name></name>
</vctinfo>
<uct>
<createUser>
<email></email>
<name>breeze</name>
<password></password>
                <readLevel>uctVct</readLevel>
<writeLevel>uctVct</writeLevel>
</createUser>
<createdAt>2009-05-14T14:28:10+09:00</createdAt>
<description></description>
<hierachy>6 7 8 9 11</hierachy>
            <hierachyStr></hierachyStr>
<name>itemshop</name>
<parentId>9</parentId>
</uct>
<name>아이템몰</name>
<sortOrder>1</sortOrder>
        <visible>show</visible>
<moved>notMoved</moved>
<shortcut>shortcut</shortcut>
<hierachy>1</hierachy>
<hierachyStr>아이템몰</hierachyStr>
</vct>
    <vct>
<id>2</id>
<vctinfo>
<country>
<id>1</id>
<name>KR</name>
</country>
            <createUser>
<email></email>
<name>breeze</name>
<password></password>
<readLevel>uctVct</readLevel>
<writeLevel>uctVct</writeLevel>
</createUser>
            <createdAt>2009-05-18T15:05:51+09:00</createdAt>
<description>Shop에서 사용할 VCT</description>
<language>
<description>한국어</description>
<name>Ko</name>
</language>
<name>Itene Shop</name>
        </vctinfo>
<uct>
<createUser>
<email></email>
<name>breeze</name>
<password></password>
<readLevel>uctVct</readLevel>
                <writeLevel>uctVct</writeLevel>
</createUser>
<createdAt>2009-05-19T16:23:26+09:00</createdAt>
<description>hair chage item</description>
<hierachy>6 7 8 9 11 20</hierachy>
<hierachyStr></hierachyStr>
            <name>Hair change</name>
<parentId>11</parentId>
</uct>
<name></name>
<vctParentId>1</vctParentId>
<sortOrder>1</sortOrder>
        <visible>show</visible>
<moved>notMoved</moved>
<shortcut>shortcut</shortcut>
<hierachy>1 2</hierachy>
<hierachyStr></hierachyStr>
</vct>
</vcts>


Posted by Breeze.Kang

댓글을 달아 주세요

  1. 으아니.. 프로그래밍 포스팅도하시네요? ㅎㅎㅎ 잘지내시죠? 저도 요기능 필요해서 검색하다가 눈에 익어서 들어왔네요.

    2009.06.03 17:01 [ ADDR : EDIT/ DEL : REPLY ]
    • Breeze

      ㅋㅋ 라이덴 오랜만!
      아, 이젠 프로그래밍 관련 포스팅도 하려고~

      2009.06.03 17:34 [ ADDR : EDIT/ DEL ]
  2. 오 좋네요. 좋은정보좀 많이 포스팅해주세요. 전 요새 트위터로 뭐할거 없을까 뒤져보는 중이에요. 트위터아이디 raidenz 입니다 :) 아 결혼도 곧 합니다. 연락드립죠. ㅎㅎ

    2009.06.03 18:07 [ ADDR : EDIT/ DEL : REPLY ]

Effective Java 3nd Edition을 회사사람들과 함께 스터디하는 중에 보게된 명언들이다.

More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason—including blind stupidity.
—William A. Wulf [Wulf72]

( 맹목적인 어리석음을 포함한 다양한 이유중에 죄악같은 프로그램을 행하게 되는 으뜸의 이유는 바로 efficiency라는 이름으로 행하여 지게 된다,  )


We should forget about small efficiencies, say about 97% of the time: premature
optimization is the root of all evil.
—Donald E. Knuth [Knuth74]( 작은 효율성따위는 잊어버려야 한다, 어설픈 Optimization은 모든 악의 근원이다)


We follow two rules in the matter of optimization:
Rule 1. Don’t do it.
Rule 2 (for experts only). Don’t do it yet—that is, not until you have a
perfectly clear and unoptimized solution.
—M. A. Jackson [Jackson75 ]
( Optimization문제에 대하여 두가지 원칙을 따라야 한다. 첫번째는 하지 말라.두번째도 하지 말라이다. 단, 전문가의 경우, 당신의 솔루션이 명백하게 unoptimized되어있다는것이 명백해 지기 전까지는 절대 하지 말아라.)


약간의 의역과 오역이 있을수 있다;;
즉 결론은 잘 모르면서 성능 튜닝이나 Optimization을 하지 말라는 이야기다.

절대적으로 맞는 말이다.

내가 하는일이 어떤 결과를 나을지 어느정도 예측이 불가능하다면 하지 않는 편이 더 나은 경우를 많이 보아왔다.

또한 성능상의 이유로 좋은 아키텍처를 포기하지 말라는 말도 빼먹지 않고 있다.

Don’t sacrifice sound architectural principles for performance. Strive to write good programs rather than fast ones


이건 내가 기억해야 할 부분인 것 같다.



Posted by Breeze.Kang

댓글을 달아 주세요