티스토리 툴바


org.hibernate.AnnotationException: referencedColumnNames(columnName) of A... referencing B... not mapped to a single property
at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:180)
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:88)
at org.hibernate.cfg.AnnotationConfiguration.processEndOfQueue(AnnotationConfiguration.java:456)
at org.hibernate.cfg.AnnotationConfiguration.processFkSecondPassInOrder(AnnotationConfiguration.java:438)
at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:309)
at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1134)
at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1226)
at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:173)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:854)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:425)

Hibernate/JPA로 개발하는 도중 위의 에러가 발생하여 원인을 찾았는데 그 원인이 너무 사소한 실수로 인한 것이어서 포스팅을 한다.

일단 에러의 내용을 살펴보면 
  B...를 참조하는 A...의 참조컬럼이 단일속성으로 매핑되지 않는다. 
로 해석된다. 즉, 하나의 컬럼으로는 FK를 선언할 수 없다는 내용으로 이해하면 되며 결국 PK가 하나가 아니라는 말이된다.

위의 내용만을 본다면 @IdClass 나 @EmbeddedId 로 선언하여 단일키가 아닌 복합키로 PK를 선언했어야 했는데 아래와 같이 단일키로 생성했다. 

그런데 자세히 보면 이 도메인객체는 그 자체로 문제가 있다. 왜냐하면 @Id 선언이 두개가 되어 있기 때문이다.(붉은색 굵은 글씨 참고)
나중에 해결했을 땐 너무 어이없었지만 Copy&Paste 를 하는 과정에서 이런 실수를 할 수도 있을 것 같다. 아무쪼록 이글이 나와 같은 상황에서 빠른 문제해결이 될 수 있도록 도움이 되었으면 한다.

B:
@Entity
@Table(name = "TT_TROUBLE_TICKET")
public class TroubleTicket implements Serializable {

    /** UID */
    private static final long serialVersionUID = -6144092108662486502L;

    /** 장애아이디 */
    @Id
    @GeneratedValue(generator = "SQ_TT_TROUBLE_TICKET")
    @SequenceGenerator(name = "SQ_TT_TROUBLE_TICKET", initialValue = 1, allocationSize = 1, sequenceName = "SQ_TT_TROUBLE_TICKET")
    @Column(name = "TROUBLE_TICKET_ID", nullable = false)
    private long troubleTicketId;

    /** 샵아이디 */
    @Id // 제거해야함
    @Column(name = "SHOP_ID", length = 8)
    private String shopId;

}

A:
@Entity
@Table(name = "TT_COMMENT")
public class TroubleTicketComment implements Serializable {

    /** UID */
    private static final long serialVersionUID = 765699083453512999L;

    /** 조치내역아이디 */
    @Id
    @GeneratedValue(generator = "SQ_TT_COMMENT")
    @SequenceGenerator(name = "SQ_TT_COMMENT", initialValue = 1, allocationSize = 1, sequenceName = "SQ_TT_COMMENT")
    @Column(name = "COMMENT_ID", nullable = false)
    private long commentId;

    /** 장애 */
    @ManyToOne
    @JoinColumn(name = "TROUBLE_TICKET_ID", referencedColumnName = "TROUBLE_TICKET_ID", nullable = false)
    private TroubleTicket troubleTicket;
}



저작자 표시
크리에이티브 커먼즈 라이선스
Creative Commons License
JPA구현을 Unitils + DBUnit으로 테스트를 수행할 때 다음과 같은 에러가 발생한 경우
DBUnit이 초기화하는 테이블의 순서에 주의해야한다.
즉, A OneToMany B, C OneToMany B 와 같이 정의한 경우 A, C, B 순서로 정의해야만한다.
이때 DBUnit은 A, C, B의 순서로 데이터를 로드하고 B, C, A의 순서로 클리어한다.
그런나 만약 B를 C앞에 정의하게 되면 다시말해 A, B, C의 순서로 정의하면 삭제할 때 아래와 같은 제약사항 오류를 보게된다.


Caused by: org.unitils.core.UnitilsException: Error while executing DataSetLoadStrategy
at org.unitils.dbunit.datasetloadstrategy.impl.BaseDataSetLoadStrategy.execute(BaseDataSetLoadStrategy.java:48)
at org.unitils.dbunit.DbUnitModule.insertDataSet(DbUnitModule.java:230)
at org.unitils.dbunit.DbUnitModule.insertDataSet(DbUnitModule.java:153)
... 22 more
Caused by: java.sql.SQLException: Integrity constraint violation FK1258F61560459CB5 table: CU_SHOP_EXTRA_CONTACT
at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
at org.hsqldb.jdbc.jdbcStatement.fetchResult(Unknown Source)
at org.hsqldb.jdbc.jdbcStatement.execute(Unknown Source)
at org.dbunit.database.statement.SimpleStatement.executeBatch(SimpleStatement.java:67)
at org.dbunit.operation.DeleteAllOperation.execute(DeleteAllOperation.java:125)
at org.dbunit.operation.CompositeOperation.execute(CompositeOperation.java:78)
at org.unitils.dbunit.datasetloadstrategy.impl.CleanInsertLoadStrategy.doExecute(CleanInsertLoadStrategy.java:45)
at org.unitils.dbunit.datasetloadstrategy.impl.BaseDataSetLoadStrategy.execute(BaseDataSetLoadStrategy.java:44)
... 24 more
저작자 표시
크리에이티브 커먼즈 라이선스
Creative Commons License

struts OGNL에서 static method 사용하기

2010/01/18 16:24 | Posted by 포데브(엄지사랑) 엄지사랑
사실 포스팅 하기에는 너무 간다한한 내용이라 망설여지긴 하지만 알면 간단하나 모르면 너무 어려운것이므로...^^;

<constant name="struts.ognl.allowStaticMethodAccess" value="true" />

와 같이 한줄을 struts.xml 이나 struts.properties 에 추가해 주면 된다.
그리고 <s:property value="@class.full.name@staticMethodName()"/>와 같이 사용하면 된다. 사실 정적메소드 접근에 대한 기본값이 false 이므로 


에서 설명하는 내용이 동작하지 않는 것처럼 보이고 이런 내용이 인터넷 상에 다수 보이고 있다. ㅋㅋ 사실 나도 왜 안나오나 하고 순간 당황 ^^;

저작자 표시
크리에이티브 커먼즈 라이선스
Creative Commons License

struts에서 ContextPath 사용하기

2010/01/18 15:17 | Posted by 포데브(엄지사랑) 엄지사랑

"올바른 성장과 따뜻한 나눔"

<s:set name="ctx">${pageContext.request.contextPath}</s:set>
1. [${ctx}]
2. [<s:property value="%{#ctx}" />]
3. [<s:property value="#ctx" />]

참간단해 보이지만 또 막상 사용하려고 하면 서핑을 하게 됩니다.

또한 거의 대부분 ${pageContext.request.contextPath}와 같은 방식만 언급되어 있지 변수로 선언하고 설정한 다음 사용하는 방법에 대해서는 언급이 없습니다.

그래서 간단하게 접근하기 위한 방법을 공유합니다.

위에서 3가지 방법으로 접근하는 방법을 소개하고 있는데 ${}방식은 프리마커 스타일이구요

밑에 두가지 방식은 OGNL 방식입니다.

(결과는 같지만 %{}는 non-String 일때 문자열로 분석하게 하는 기능입니다. 여기서는 필요가 없죠?..  ㅎㅎ

그래도 이런 표현도 있다는 것을 알아 두세요. 문자열이 아닌 값을 출력할 때는 반드시 써야합니다.^^;

참고: http://struts.apache.org/2.0.14/docs/tag-syntax.html)

OGNL에서는 프리마커스타일을 사용할 수 없기 때문에 첫 문장처럼 태그의 바디문자열로 접근해야만 합니다.

유용한 정보가 되었으면 하네요^^;

끝.

저작자 표시
크리에이티브 커먼즈 라이선스
Creative Commons License

HttpClient의 GetMethod 사용시 URL의 한글처리

2008/04/04 21:17 | Posted by 포데브(엄지사랑) 엄지사랑

GetMethod 사용시 [코드1]과같이 URL을 생성하고 실행하면 [코드2]와 같은 예외가 발생한다.
    

[코드1]

        // Create a method instance.
        StringBuilder searchURL = new StringBuilder(this.urlRoot + "/term/search.json");
        searchURL.append('?').append("dictionaryId").append('=').append(dictionary.getId());
        searchURL.append('&').append("queryString").append('=').append(queryString);
        searchURL.append('&').append("start").append('=').append(0);
        GetMethod httpMethod = new GetMethod(searchURL.toString());


 

[코드2]

java.lang.IllegalArgumentException: Invalid uri 'http://localhost:8080/bcf/term/search.json?dictionaryId=6&queryString=윤*&start=0': Invalid query
 at org.apache.commons.httpclient.HttpMethodBase.<init>(HttpMethodBase.java:222)
 at org.apache.commons.httpclient.methods.GetMethod.<init>(GetMethod.java:89)
 at kr.nextree.nexdic.facade.DictionaryFacade.searchTerms(DictionaryFacade.java:175)
 at kr.nextree.nexdic.facade.DictionaryFacadeTest.testSearchTerm(DictionaryFacadeTest.java:68)

이를 해결하기위해서는 [코드3]과 같이 인코딩되어야할 파라메터값은 인코딩을 해준다.

[코드3]

        try {
            queryString = URLEncoder.encode(queryString, "UTF-8");
        }
        catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
크리에이티브 커먼즈 라이선스
Creative Commons License

Content-Type 정리

2008/03/19 19:42 | Posted by 포데브(엄지사랑) 엄지사랑


contentType

application/acad
AutoCAD drawing files
dwg

application/clariscad
ClarisCAD files
ccad

application/dxf
DXF (AutoCAD)
dxf

application/msaccess
Microsoft Access file
mdb

application/msword
Microsoft Word file
doc

application/octet-stream
Uninterpreted binary
bin

application/pdf
PDF (Adobe Acrobat)
pdf

application/postscript-x
PostScript-x, encapsulated PostScript-x,
Adobe Illustrator
ai, ps, eps

application/rtf
Rich Text Format file
rtf rtf

application/vnd.ms-excel
Microsoft Excel file
xls

application/vnd.ms-powerpoint
Microsoft PowerPoint file
ppt

application/x-cdf
Channel Definition Format file
cdf

application/x-csh
C-shell script-x
csh csh

application/x-dvi
TeX
dvi dvi dvi

application/x-javascript-x
JavaScript-x source file
js

application/x-latex
LaTeX source file
latex

application/x-mif
FrameMaker MIF format
mif

application/x-msexcel
Microsoft Excel file
xls

application/x-mspowerpoint
Microsoft PowerPoint file
ppt

application/x-tcl
TCL script-x
tcl

application/x-tex
TeX source file
tex

application/x-texinfo
Texinfo (emacs)
texinfo, texi

application/x-troff
troff file
t, tr, roff t, tr, roff

application/x-troff-man
troff with MAN macros
man

application/x-troff-me
troff with ME macros
me

application/x-troff-ms
troff with MS macros
ms

application/x-wais-source
WAIS source file
src

application/zip
ZIP archive
zip

audio/basic
Basic audio (usually m-law)
au, snd

audio/x-aiff
AIFF audio
aif, aiff, aifc

audio/x-wav
Windows WAVE audio
wav

image/gif
GIF image
gif

image/ief
Image Exchange Format file
ief

image/jpeg
JPEG image
jpeg, jpg jpe

image/tiff
TIFF image
tiff, tif

image/x-cmu-raster
CMU Raster image
ras

image/x-portable-anymap
PBM Anymap image format
pnm

image/x-portable-bitmap
PBM Bitmap image format
pbm

image/x-portable-graymap
PBM Graymap image format
pgm

image/x-portable-pixmap
PBM Pixmap image format
ppm

image/x-rgb
RGB image format
rgb

image/x-xbitmap
X Bitmap image
xbm

image/x-xpixmap
X Pixmap image
xpm

image/x-xwindowdump
X Windows Dump (xwd)
xwd

multipart/x-gzip
GNU ZIP archive
gzip

multipart/x-zip
PKZIP archive
zip

text/css
Cascading style sheet
css

text/html
HTML file
html, htm

text/plain
Plain text
txt

text/richtext
MIME Rich Text
rtx

text/tab-separated- values
Text with tab-separated values
tsv

text/xml
XML document
xml

text/x-setext
Struct-Enhanced text
etx

text/xsl
XSL style sheet
xsl

video/mpeg
MPEG video
mpeg, mpg, mpe

video/quicktime
QuickTime video
qt, mov

video/x-msvideo
Microsoft Windows video
avi

video/x-sgi-movie
SGI movie player format
movie


JSP에서 강제 파일다운로드 트릭
<%
    response.setHeader("Content-Type", "application/x-msdownload");
    response.setHeader("Content-Disposition", "attachment;filename=파일명;");
%>


크리에이티브 커먼즈 라이선스
Creative Commons License
이전 1 다음