참조 : http://hmjkor.tistory.com/176
	
		
		 
		
		
		
		
		
		
		
		

'Framework > Spring' 카테고리의 다른 글

Spring 3.2.3 + myBatis 3.2.2  (0) 2013.07.19
Spring Framework 3.2.3 Maven으로 한번에 추가하기..  (0) 2013.07.18
Spring 3.2.2 + Tiles 3.0  (0) 2013.05.22
Spring Security 설정.  (2) 2011.08.30
[2011-05-26] Spring Security 설정 오류.  (0) 2011.05.26
MySQL AutoReconnect 설정.  (0) 2010.07.12
- iBatis 3.0 에서 간단하게 like 검색 하는 법

CB.CUSTOMER_NAME like CONCAT('%', #{customerName:VARCHAR}, '%')

사용 예 )
<-select id="expired_search" parametertype="java.util.HashMap" resulttype="net.autobrain.domain.ExpiredSearchResult" flushcache="false" usecache="false">
SELECT CB.COUPON_BOOK_NO, CN.COUPON_NAME_SEQ, CN.COUPON_NAME
		    , CASE WHEN CB.CHARGE_TYPE = 'F' THEN '무상' ELSE '유상' END AS CHARGE_TYPE
		    , AM.AUTO_MODEL_SEQ
		    , AM.MODEL_NAME
		    , IFNULL(CB.CAR_NUMBER, '') AS CAR_NUMBER
		    , CB.VIN_NO
		    , CB.CUSTOMER_NAME
		    , CONCAT(CB.CUSTOMER_PHONE_1, '-', CB.CUSTOMER_PHONE_2, '-', CB.CUSTOMER_PHONE_3) AS CUSTOMER_PHONE
		    , CB.AUTO_SALES_USER_SEQ
		    , SU.USER_NAME
		    , CB.COUPON_EXPIRED_DATE
		FROM COUPON_BOOK CB
		    INNER JOIN COUPON CP ON CP.COUPON_BOOK_SEQ = CB.COUPON_BOOK_SEQ
		    INNER JOIN COUPON_BOOK_SETUP CBS ON CBS.COUPON_BOOK_SETUP_SEQ = CB.COUPON_BOOK_SETUP_SEQ
		    INNER JOIN COUPON_NAME CN ON CN.COUPON_NAME_SEQ = CBS.COUPON_NAME_SEQ
		    INNER JOIN COUPON_SETUP CS ON CBS.COUPON_BOOK_SETUP_SEQ = CS.COUPON_BOOK_SETUP_SEQ
		    INNER JOIN AUTO_MODELS AM ON CBS.AUTO_MODEL_SEQ = AM.AUTO_MODEL_SEQ
		    INNER JOIN AUTO_CLASSES AC ON AM.AUTO_CLASS_SEQ AND AC.AUTO_CLASS_SEQ
		    INNER JOIN SALES_USERS SU ON SU.SALES_USER_SEQ = CB.AUTO_SALES_USER_SEQ
		    INNER JOIN SHOWROOM_CODES SC ON SU.SHOWROOM_SEQ = SC.SHOWROOM_SEQ
		WHERE CB.REFUND_DATE IS NULL AND CB.DISABLE IS NULL
		AND CN.COUPON_NAME_SEQ = #{couponNameSeq}
		AND CB.CUSTOMER_NAME like CONCAT('%', #{customerName:VARCHAR}, '%')
	        AND DATE_FORMAT(#{beginCriterionDate}, '%Y-%m-%d') <= DATE_FORMAT(DATE_SUB(CB.COUPON_EXPIRED_DATE, INTERVAL #{gubun} DAY), '%Y-%m-%d')
		AND DATE_FORMAT(DATE_SUB(CB.COUPON_EXPIRED_DATE, INTERVAL #{gubun} DAY), '%Y-%m-%d') <= DATE_FORMAT(#{endCriterionDate}, '%Y-%m-%d')
		AND (TO_DAYS(CB.COUPON_EXPIRED_DATE) - TO_DAYS(CAST(#{criterionDate} AS DATE)) BETWEEN #{criterionDay1:NUMERIC} AND #{criterionDay2:NUMERIC})
		GROUP BY COUPON_BOOK_NO
    <-/select>

'Framework > myBatis' 카테고리의 다른 글

프로시저 호출 시 주의 할 점..  (0) 2012.11.13
iBatis isEqual  (0) 2012.11.05
[3.0] forEach 사용  (0) 2010.07.15
[3.0] like 검색.  (0) 2010.07.09
[3.0] JDBC Type  (0) 2010.07.09
iBatis 3.0 Cache 문제 -  (0) 2010.07.08

쿼리~~
AND (TO_DAYS(CB.COUPON_EXPIRED_DATE) - TO_DAYS(CAST(#{criterionDate} AS DATE)) BETWEEN #{criterionDay1:NUMERIC} AND #{criterionDay2:NUMERIC})


'Framework > myBatis' 카테고리의 다른 글

프로시저 호출 시 주의 할 점..  (0) 2012.11.13
iBatis isEqual  (0) 2012.11.05
[3.0] forEach 사용  (0) 2010.07.15
[3.0] like 검색.  (0) 2010.07.09
[3.0] JDBC Type  (0) 2010.07.09
iBatis 3.0 Cache 문제 -  (0) 2010.07.08

1. Query 실행 후 그 결과를 Map에 담아 리턴해 페이지에 출력.
2. 다른 곳에서 위 출력 결과에 영향을 주는 컬럼 값을 변경한다. 
3. 다시 1번을 수행하면 2번의 결과가 반영되지 않고 수정하기 전의 결과가 딱 나온다.

iBatis로그가 아닌 일반 로그에서는 호출은 되나 iBatis가 실행되진 않았다.

- 조건을 다르게 해서 실행 했을경우 sql을 실행하지만, 결과 값인 Map에는 수정하기 전의 정보가 들어있다.
- statementType="CALLABLE" flushCache="false" useCache="false" 모두 헛 수고

왜 그런지 문서좀 뒤져야겠다..

일단.. iBatis 로그부터 찍어야하고..

'Framework > myBatis' 카테고리의 다른 글

프로시저 호출 시 주의 할 점..  (0) 2012.11.13
iBatis isEqual  (0) 2012.11.05
[3.0] forEach 사용  (0) 2010.07.15
[3.0] like 검색.  (0) 2010.07.09
[3.0] JDBC Type  (0) 2010.07.09
iBatis 3.0 Cache 문제 -  (0) 2010.07.08

description : only one may be defined as writable all others must be specified read-only

Many To One 매핑에서 자주 발생하는 문제이다..
또한 추가적으로 One쪽 PK가 Many쪽에서도 PK로 사용된다면 JPA 초기 설정된 상태로는 100% 에러난다.

A와 B의 관계가 N:1이면 A와 B의 PK들은 아래의 구조를 가지게 된다.


	//MasterCodes.java (A와 B의 관계에선 A, 즉 Many 쪽 table)
	@EmbeddedId
	private MasterCodesPK id; //복합키

	@Column(name="CODE_NAME")
	private String codeName;

	//생략~~

	//bi-directional many-to-one association to MasterCodeGroups
	@ManyToOne(cascade = REFRESH)
	@JoinColumn(name="CODE_GROUP_SEQ")
	private MasterCodeGroups masterCodeGroup;
	
	// getter / setter 생략~
	//MasterCodeGroups.java (A와 B의 관계에선 B, 즉 One에 해당)
	@Id
	@Column(name="CODE_GROUP_SEQ")
	@GeneratedValue(generator = "MASTER_CODE_GROUPS")
	private int codeGroupSeq;

	@Column(name="CODE_GROUP_NAME")
	private String codeGroupName;

	// 생략~~

	//bi-directional many-to-one association to MasterCodes
	@OneToMany(mappedBy="masterCodeGroup", cascade = REFRESH)
	private Set masterCodes;

	// getter - setter 생략~


위 내용이 JPA로 Table에서 불러와 세팅 된 것인데 이대로 했다가 에러가 빵 뜨더라..;;
그 에러가 제목과 같은 에러인데 -
복합키로 구성될 경우 자신의 PK가 아닌 다른 Table의 PK를 변경할 수 있다면? 있을수 없는 일이다;;
즉 A와 B에서 A의 키는 A_PK, B_PK를 사용하는데 A테이블에서 B_PK를 변경할 수 있다면? 무결성이 깨지게 된다.;;
이때는 차라리 B에서 B_PK가 변경된다면 A에서도 B_PK가 변경되게 제약 조건을 설정하는게 좋다 -

그래서 read-only로 하라는 에러가 나오는 것인데 -

아래와 같이 A테이블에 설정을 더 적어 주어야 한다..


	//MasterCodes.java (A와 B의 관계에선 A, 즉 Many 쪽 table)
	@EmbeddedId
	private MasterCodesPK id; //복합키

	@Column(name="CODE_NAME")
	private String codeName;

	//생략~~

	//bi-directional many-to-one association to MasterCodeGroups
	@ManyToOne(cascade = REFRESH)
	@JoinColumn(name="CODE_GROUP_SEQ", nullable=false, insertable=false, updatable=false)
	private MasterCodeGroups masterCodeGroup;
	
	// getter / setter 생략~



아까와 동일하나 JoinColumn Annotation에 기타 속성이 잔뜩 들어갔다;; 저렇게하면 read-only가 된다.

시간이 없어서 문서를 다 읽어보지 않고 중요 부분만 읽은 후에 썼는데 -
시간 있으신 분은 아래 사이트에서 다 읽어보면 좋을 것 같다.

http://trycatchfinally.blogspot.com/2006/01/mapping-relationships-in-ejb-30.html


왜 제네릭이 안되었는지 이제 알았다. 확실히...

먼저 제네릭이 안되었을때의 하이버네이트와 매핑한 bean을 살펴보면

 @Id
 @GeneratedValue(strategy=GenerationType.AUTO)
 public Integer getUserSeq() {
     return userSeq;
 }

오류난 로그

2010-01-09 23:06 [DEBUG] opened session at timestamp: 12630460153
2010-01-09 23:06 [DEBUG] about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
2010-01-09 23:06 [DEBUG] opening JDBC connection
2010-01-09 23:06 [DEBUG] select this_.userSeq as userSeq2_0_, this_.ANSWER as ANSWER2_0_, this_.BIRTH_DAY as BIRTH3_2_0_, this_.CREATE_DATE as CREATE4_2_0_, this_.DISABLE as DISABLE2_0_, this_.DOMAIN as DOMAIN2_0_, this_.E_MAIL as E7_2_0_, this_.EMAIL_DENY as EMAIL8_2_0_, this_.masterCodes as masterCo9_2_0_, this_.QUESTION as QUESTION2_0_, this_.RELATION_GROUP_SEQ as RELATION11_2_0_, this_.RELATION_SEQ as RELATION12_2_0_, this_.UPDATE_DATE as UPDATE13_2_0_, this_.USER_ID as USER14_2_0_, this_.USER_NAME as USER15_2_0_, this_.USER_NICK as USER16_2_0_, this_.USER_PW as USER17_2_0_, this_.USER_STATUS as USER18_2_0_ from MEMBER this_ where this_.USER_ID=? and this_.USER_PW=?
2010-01-09 23:06 [DEBUG] preparing statement
2010-01-09 23:06 [DEBUG] binding 'agnes0417' to parameter: 1
2010-01-09 23:06 [DEBUG] binding '~~~~~~~' to parameter: 2
2010-01-09 23:06 [DEBUG] about to open ResultSet (open ResultSets: 0, globally: 0)
2010-01-09 23:06 [DEBUG] processing result set
2010-01-09 23:06 [DEBUG] result set row: 0
2010-01-09 23:06 [DEBUG] returning null as column: userSeq2_0_
      -> primary key 가 null인게 있을리 없다..

2010-01-09 23:06 [DEBUG] result row: null
2010-01-09 23:06 [DEBUG] done processing result set (1 rows)
2010-01-09 23:06 [DEBUG] about to close ResultSet (open ResultSets: 1, globally: 1)
2010-01-09 23:06 [DEBUG] about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
2010-01-09 23:06 [DEBUG] closing statement



@Column을 명시하지 않았기에 하이버네이트가 매핑된 이름 그대로 컬럼을 찾는다.
DB의 컬럼명은 USER_SEQ인데.. 만약 DB 컬럼명이 USERSEQ였다면 제네릭이 되었을테지만..

아래처럼 고쳐주었다..

 @Id
 @GeneratedValue(strategy=GenerationType.AUTO)
 @Column(name="USER_SEQ")
 public Integer getUserSeq() {
      return userSeq;
 }

제대로 돌아간 로그 기록..

2010-01-09 23:01 [DEBUG] opened session at timestamp: 12630457058
2010-01-09 23:01 [DEBUG] about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
2010-01-09 23:01 [DEBUG] opening JDBC connection
2010-01-09 23:01 [DEBUG] select this_.USER_SEQ as USER1_2_0_, this_.ANSWER as ANSWER2_0_, this_.BIRTH_DAY as BIRTH3_2_0_, this_.CREATE_DATE as CREATE4_2_0_, this_.DISABLE as DISABLE2_0_, this_.DOMAIN as DOMAIN2_0_, this_.E_MAIL as E7_2_0_, this_.EMAIL_DENY as EMAIL8_2_0_, this_.masterCodes as masterCo9_2_0_, this_.QUESTION as QUESTION2_0_, this_.RELATION_GROUP_SEQ as RELATION11_2_0_, this_.RELATION_SEQ as RELATION12_2_0_, this_.UPDATE_DATE as UPDATE13_2_0_, this_.USER_ID as USER14_2_0_, this_.USER_NAME as USER15_2_0_, this_.USER_NICK as USER16_2_0_, this_.USER_PW as USER17_2_0_, this_.USER_STATUS as USER18_2_0_ from MEMBER this_ where this_.USER_ID=? and this_.USER_PW=?
2010-01-09 23:01 [DEBUG] preparing statement
2010-01-09 23:01 [DEBUG] binding 'agnes0417' to parameter: 1
2010-01-09 23:01 [DEBUG] binding '~~~~~' to parameter: 2
2010-01-09 23:01 [DEBUG] about to open ResultSet (open ResultSets: 0, globally: 0)
2010-01-09 23:01 [DEBUG] processing result set
2010-01-09 23:01 [DEBUG] result set row: 0
2010-01-09 23:01 [DEBUG] returning '2' as column: USER1_2_0_
2010-01-09 23:01 [DEBUG] result row: EntityKey[com.jaeyeollee.model.join.Member#2]
2010-01-09 23:01 [DEBUG] Initializing object from ResultSet: [com.jaeyeollee.model.join.Member#2]
2010-01-09 23:01 [DEBUG] Hydrating entity: [com.jaeyeollee.model.join.Member#2]

2010-01-09 23:01 [DEBUG] returning null as column: DISABLE2_0_
2010-01-09 23:01 [DEBUG] returning '@naver.com' as column: DOMAIN2_0_
2010-01-09 23:01 [DEBUG] returning 'leepcs' as column: E7_2_0_
2010-01-09 23:01 [DEBUG] returning null as column: EMAIL8_2_0_
2010-01-09 23:01 [DEBUG] returning null as column: masterCo9_2_0_
2010-01-09 23:01 [DEBUG] returning '어머니 성함' as column: QUESTION2_0_
2010-01-09 23:01 [DEBUG] returning 'CG0000' as column: RELATION11_2_0_
2010-01-09 23:01 [DEBUG] returning 'CS0000' as column: RELATION12_2_0_
2010-01-09 23:01 [DEBUG] returning null as column: UPDATE13_2_0_
2010-01-09 23:01 [DEBUG] returning 'agnes0417' as column: USER14_2_0_
2010-01-09 23:01 [DEBUG] returning 'Hibernate' as column: USER16_2_0_
2010-01-09 23:01 [DEBUG] returning null as column: USER18_2_0_
2010-01-09 23:01 [DEBUG] done processing result set (1 rows)
2010-01-09 23:01 [DEBUG] about to close ResultSet (open ResultSets: 1, globally: 1)
2010-01-09 23:01 [DEBUG] about to close PreparedStatement (open PreparedStatements: 1, globally: 1)

2010-01-09 23:01 [DEBUG] closing statement





그러니.. 제네릭이 된다.. 하하하;;;

아.. 볍신 인증했네...

난 Collection을 사용할때 항상 Generic 타입으로 객체를 생성하려한다.
이유야 generic을 사용하면 좀 간편해지니 (캐스팅을 할 필요도 없고..)

이유야 어쨋든 하이버 네이트에서도 제네릭을 붙여보았는데 ..


  1. Session session = getHibernateTemplate().getSessionFactory().openSession();
  2.  
  3. Criteria crit = session.createCriteria(Member.class);
  4. crit.add(Expression.eq("userId", member.getUserId()));
  5. crit.add(Expression.eq("userPw", member.getUserPw()));
  6.  
  7. List<Member> list = crit.list();

난 이게 될 줄 알았다. 정말 진짜...
심심풀이 만들어보고 있는데 이상하게 유저가 존재하는데도 session을 생성하려고하면 null을 뱉어내니 환장하는 수 밖에..

별 수단 다 써보다가 설마 싶어서 <Member>를 지우고 찍어보니.. 객체 주소가 찍히네...

그래서 도달한 결론은 7번 라인처럼 generic을 이용하여도 -
crit.list()를 하게 되면 return 되는 값들은 Object 형이므로 무조건 class Casting을 하여야 한다.

Membe rmember = (Member) list.get(0);

이렇게...  하면 틀린거고;;

http://yeory.tistory.com/46 여기를 참고하세요..

이글은 무식 인증 글임 ㅋ

+ Recent posts