public List getReservations( ) { return getHibernateTemplate( ).find("from Reservation"); }당신이 찾지 못한 것을 말해봐라. 트랜잭션 처리 과정이 없다. Spring은 트랜잭션 관리를 위한 환경 구성 코드를 구축할 수 있게 해준다. 세션을 막아 놓으면서 자원을 관리하지 않는다. 당신만을 위한 환경 설정을 할 필요도 없다. 트랜잭션 레벨에서는 예외가 unchecked이기 때문에, 예외 관리도 할 필요가 없다. 대부분의 상황에서 트랜잭션에 대한 관리에서 자유로워진다. Spring을 사용하지 않고 어떻게 구현했는지 다른 하이버네이트 메소드를 보면 알 수 있다.
public List getBikesOldWay( ) throws Exception { List bikes = null; Session s = null; try { s = mySessionFactory.openSession( ); bikes = s.find("from Bike"); }catch (Exception ex) { //handle exception gracefully }finally { s.close( ); } return bikes; }Spring은 나에게 수단을 제공한다. 나는 더 빨리 코드를 작성할 수 있으며, 유지를 위한 수고도 적다.
대상(the target) :세 개의 다른 빈-프록시, 대상 객체(the target), 인터셉터-이 있다는 것을 알아두자. 프록시는 POJO를 호출 할 것이고, POJO에 의해 필요한 서비스들이 있을 것이다. 인터셉터는 서비스를 호출하는데 반드시 필요한 서비스 코드를 포함한다. 또한 프록시와 인터셉터에는 대상 객체(the target)에 있는 각 메소드를 어떻게 처리할지에 대해 정의한다. 프록시를 호출해서 RentaBike에 접근을 필요로 하는 어느 누구든지 트랜잭션을 처리하는 인터셉터를 호출하고, 트랜잭션을 시작한 다음 대상 객체(the target : 여기서는 POJO가 됨)를 호출할 수 있다. 대상 객체는 자신의 임무를 수행하고, (트랜잭션을 커밋하는) 인터셉터에게 리턴 한 다음, 다시 프록시에게 리턴하고, 마지막으로 프록시를 호출한 대상에 결과를 리턴 한다.인터셉터(the interceptor) : Bruce"s Bikes 프록시(the proxy) : com.springbook.RentABike.transferReservation= PROPAGATION_REQUIRED,-ReservationTransferException com.springbook.RentABike.save*=PROPAGATION_REQUIRED com.springbook.RentABike.*=PROPAGATION_REQUIRED,readOnly com.springbook.RentABike transactionInterceptor,rentaBikeTarget
public class CommandLineView { private RentABike rentaBike; public CommandLineView( ) { rentaBike = new ArrayListRentABike("Bruce"s Bikes"); } public void setRentABike(RentABike rentABike){ this.rentABike = rentABike; } public void printAllBikes( ) { System.out.println(rentaBike.toString( )); Iterator iter = rentaBike.getBikes().iterator( ); while(iter.hasNext( )) { Bike bike = (Bike)iter.next( ); System.out.println(bike.toString( )); } } public static final void main(String[] args) { CommandLineView clv = new CommandLineView( ); clv.printAllBikes( ); } }다음으로 모델 역할을 하는 서비스를 보자. 배열 리스트를 사용한 간단한 구현이다. 이 구현 클래스는 모델(RentaBike)에 대한 의존성을 가지고 있다.
interface RentABike { List getBikes( ); Bike getBike(String serialNo); } public class ArrayListRentABike implements RentABike { private String storeName; final List bikes = new ArrayList(); public ArrayListRentABike(String storeName) { this.storeName = storeName; bikes.add(new Bike("Shimano", "Roadmaster", 20, "11111", 15, "Fair")); bikes.add(new Bike("Cannondale", "F2000 XTR", 18, "22222",12,"Excellent")); bikes.add(new Bike("Trek","6000", 19, "33333", 12.4, "Fair")); } public String toString() { return "RentABike: " + storeName; } public List getBikes() { return bikes; } public Bike getBike(String serialNo) { Iterator iter = bikes.iterator(); while(iter.hasNext()) { Bike bike = (Bike)iter.next(); if(serialNo.equals(bike.getSerialNo())) return bike; } return null; } }이제 중개자(assembler)에 대해 보자. 이 중개자는 서비스와 사용자를 초기화하고, rentaBike속성에 값을 할당함으로서 의존성을 결정한다.
public class RentABikeAssembler { public static final void main(String[] args) { CommandLineView clv = new CommandLineView( ); RentABike rentaBike = new ArrayListRentABike("Bruce"s Bikes"); clv.setRentaBike(rentaBike); clv.printAllBikes( ); } }물론 Spring은 결과적으로 중개자 역할에 매우 적합할 것이다. 만약 인터페이스로 서비스를 감싼다면, 이 인터페이스를 구현한 컨테이너에 있는 어떤 클래스도 주입(inject)이 가능할 것이다.
JdbcTemplate template = new JdbcTemplate(dataSource); final List names = new LinkedList(); template.query("SELECT USER.NAME FROM USER", new RowCallbackHandler() { public void processRow(ResultSet rs) throws SQLException { names.add(rs.getString(1)); } } );기본 JDBC 메소드로서 사용되는 쿼리 메소드인 템플릿에 대해 생각해보자. Spring은 ResultSet에 있는 각 라인을 위해 익명 내부 클래스에 있는 processRow 메소드를 실행할 것이다. 당신은 컨텍스트에 데이터 소스(data source)를 구성해야 한다. statement를 열거나 닫기, connection, 데이터 소스의 구성, 혹은 트랜잭션 관리에 대한 걱정을 할 필요가 없다. Spring은 SQLException을 일반적인 unchecked 예외 셋으로 감싸주기 때문에 외부 결과 값 셋을 정의하거나 최 하단 수준의 예외를 직접 관리하면 안 된다. 루비나 스몰토크 같은 다른 언어들도 드물게 코드 블록으로 제어의 역전을 사용하지만, 자바에서는 이것이 일반적이지 않다. 제어의 역전은 정말로 나를 동요시킨다.
이전 글 : XML 2.0은 개발중인가?
다음 글 : 하이버네이트 3 어노테이션 소개
최신 콘텐츠