MyBatis 3 사용자가이드
|
|
|
- 윤미 삼
- 7 years ago
- Views:
Transcription
1 MyBatis 3 사용자가이드 번역자 : 이동국 ([email protected], 최신버전은
2 Contents MyBatis 는무엇인가?... 5 시작하기... 5 XML 에서 SqlSessionFactory 빌드하기... 5 XML 을사용하지않고 SqlSessionFactory 빌드하기... 6 SqlSessionFactory 에서 SqlSession 만들기... 6 매핑된 SQL 구문살펴보기... 7 명명공간 (Namespaces) 에대한설명... 8 스코프 (Scope) 와생명주기 (Lifecycle)... 8 매퍼설정 XML properties settings typealiases typehandlers objectfactory plugins environments transactionmanager datasource mappers SQL Map XML 파일 select insert, update, delete sql Parameters... 25
3 resultmap Advanced Result Mapping id, result 지원되는 JDBC 타입 constructor association collection discriminator cache 사용자지정캐시사용하기 cache-ref 동적 SQL if choose, when, otherwise trim, where, set foreach 자바 API 디렉터리구조 SqlSessions SqlSessionFactoryBuilder SqlSessionFactory SqlSession SelectBuilder SqlBuilder Logging
4
5 MyBatis 는무엇인가? MyBatis 는개발자가지정한 SQL, 저장프로시저그리고몇가지고급매핑을지원하는퍼시스턴스프레임워크이다. MyBatis 는 JDBC 코드와수동으로셋팅하는파라미터와결과매핑을제거한다. MyBatis 는데이터베이스레코드에원시타입과 Map 인터페이스그리고자바 POJO 를설정하고매핑하기위해 XML 과애노테이션을사용할수있다. 시작하기 모든 MyBatis 애플리케이션은 SqlSessionFactory 인스턴스를사용한다. SqlSessionFactory 인스턴스는 SqlSessionFactoryBuilder 를사용하여만들수있다. SqlSessionFactoryBuilder 는 XML 설정파일에서 SqlSessionFactory 인스턴스를빌드할수있다. XML 에서 SqlSessionFactory 빌드하기 XML 파일에서 SqlSessionFactory 인스턴스를빌드하는것은매우간단한다. 설정을위해클래스패스자원을사용하는것을추천하나, 파일경로나 file:// URL 로부터만들어진 Reader 인스턴스를사용할수도있다. MyBatis 는클래스패스와다른위치에서자원을로드하는것으로좀더쉽게해주는 Resources 라는유틸성클래스를가지고있다. String resource = "org/mybatis/example/configuration.xml"; Reader reader = Resources.getResourceAsReader(resource); sqlmapper = new SqlSessionFactoryBuilder().build(reader); XML 설정파일에서지정하는 MyBatis 의핵심이되는설정은트랜잭션을제어하기위한 TransactionManager 과함께 데이터베이스 Connection 인스턴스를가져오기위한 DataSource 를포함한다. 세부적인설정은조금뒤에보고간단한 예제를먼저보자. <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//dtd Config 3.0//EN" " <configuration> <environments default="development"> <environment id="development"> <transactionmanager type="jdbc"/> <datasource type="pooled"> <property name="driver" value="${driver"/> <property name="url" value="${url"/> <property name="username" value="${username"/> <property name="password" value="${password"/> </datasource> </environment> </environments> <mappers> <mapper resource="org/mybatis/example/blogmapper.xml"/> </mappers> </configuration>
6 좀더많은 XML 설정방법이있지만, 위예제에서는가장핵심적인부분만을보여주고있다. XML 가장위부분에서는 XML 문서의유효성체크를위해필요하다. environment 요소는트랜잭션관리와커넥션풀링을위한환경적인설정을 나타낸다. mappers 요소는 SQL 코드와매핑정의를가지는 XML 파일인 mapper 의목록을지정한다. XML 을사용하지않고 SqlSessionFactory 빌드하기 XML 보다자바를사용해서직접설정하길원한다면, XML 파일과같은모든설정을제공하는 Configuration 클래스를 사용하면된다. DataSource datasource = BlogDataSourceFactory.getBlogDataSource(); TransactionFactory transactionfactory = new JdbcTransactionFactory(); Environment environment = new Environment("development", transactionfactory, datasource); Configuration configuration = new Configuration(environment); configuration.addmapper(blogmapper.class); SqlSessionFactory sqlsessionfactory = new SqlSessionFactoryBuilder().build(configuration); 이설정에서추가로해야할일은 Mapper 클래스를추가하는것이다. Mapper 클래스는 SQL 매핑애노테이션을가진자바 클래스이다. 어쨌든자바애노테이션의몇가지제약과몇가지설정방법의목잡함에도불구하고, XML 매핑은세부적인 매핑을위해언제든필요하다. 좀더세부적인내용은조금뒤다시보도록하자. SqlSessionFactory 에서 SqlSession 만들기 SqlSessionFactory 이름에서보듯이, SqlSession 인스턴스를만들수있다. SqlSession 은데이터베이스에대해 SQL 명령어를실행하기위해필요한모든메서드를가지고있다. 그래서 SqlSession 인스턴스를통해직접 SQL 구문을실행할수있다. 예를들면 : SqlSession session = sqlmapper.opensession(); try { Blog blog = (Blog) session.selectone( "org.mybatis.example.blogmapper.selectblog", 101); finally { session.close(); 이방법이 MyBatis 의이전버전을사용한사람이라면굉장히친숙할것이다. 하지만좀더좋은방법이생겼다. 주어진 SQL 구문의파라미터와리턴값을설명하는인터페이스 ( 예를들면, BlogMapper.class ) 를사용하여, 문자열처리오류나 타입캐스팅오류없이좀더타입에안전하고깔끔하게실행할수있다. 예를들면 : SqlSession session = sqlsessionfactory.opensession(); try {
7 BlogMapper mapper = session.getmapper(blogmapper.class); Blog blog = mapper.selectblog(101); finally { session.close(); 그럼좀더자세히살펴보자. 매핑된 SQL 구문살펴보기 이시점에 SqlSession 이나 Mapper 클래스가정확히어떻게실행되는지궁금할것이다. 매핑된 SQL 구문에대한내용이가장중요하다. 그래서이문서전반에서가장자주다루어진다. 하지만다음의두가지예제를통해정확히어떻게작동하는지에대해서는충분히이해하게될것이다. 위예제처럼, 구문은 XML 이나애노테이션을사용해서정의할수있다. 그럼먼저 XML 을보자. MyBatis 가제공하는 대부분의기능은 XML 을통해매핑기법을사용한다. 이전에 MyBatis 를사용했었다면쉽게이해되겠지만, XML 매핑 문서에이전보다많은기능이추가되었다. SqlSession 을호출하는 XML 기반의매핑구문이다. <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//dtd Mapper 3.0//EN" " <mapper namespace="org.mybatis.example.blogmapper"> <select id="selectblog" parametertype="int" resulttype="blog"> select * from Blog where id = #{id </select> </mapper> 간단한예제치고는조금복잡해보이지만실제로는굉장히간단하다. 한개의매퍼 XML 파일에는많은수의매핑구문을정의할수있다. XML 도입무의헤더와 doctype 을제외하면, 나머지는쉽게이해되는구문의형태이다. 여기선 org.mybatis.example.blogmapper 명명공간에서 selectblog 라는매핑구문을정의했고, 이는결과적으로 org.mybatis.example.blogmapper.selectblog 형태로실제명시되게된다. 그래서다음처럼사용하게되는셈이다. Blog blog = (Blog) session.selectone( "org.mybatis.example.blogmapper.selectblog", 101); 이건마치패키지를포함한전체경로의클래스내메서드를호출하는것과비슷한형태이다. 이이름은매핑된 select 구문의 이름과파라미터그리고리턴타입을가진명명공간과같은이름의 Mapper 클래스와직접매핑될수있다. 이건위에서 본것과같은 Mapper 인터페이스의메서드를간단히호출하도록허용한다. 위예제에대응되는형태는아래와같다. BlogMapper mapper = session.getmapper(blogmapper.class); Blog blog = mapper.selectblog(101);
8 두번째방법은많은장점을가진다. 먼저문자열에의존하지않는다는것이다. 이는애플리케이션을좀더안전하게만든다. 두번째는개발자가 IDE 를사용할때, 매핑된 SQL 구문을사용할때의수고를덜어준다. 세번째는리턴타입에대해타입캐스팅을하지않아도된다. 그래서 BlogMapper 인터페이스는깔끔하고리턴타입에대해타입에안전하며이는파라미터에도그대로적용된다. 명명공간 (Namespaces) 에대한설명 명명공간 (Namespaces) 이이전버전에서는사실선택사항이었다. 하지만이제는패키지경로를포함한전체이름을가진 구문을구분하기위해필수로사용해야한다. 명명공간은인터페이스바인딩을가능하게한다. 명명공간을사용하고자바패키지의명명공간을두면코드가깔끔해지고 MyBatis 의사용성이크게향상될것이다. 이름분석 (Name Resolution): 타이핑을줄이기위해, MyBatis 는구문과결과맵, 캐시등의모든설정요소를위한이름 분석규칙을사용한다. com.mypackage.mymapper.selectallthings 과같은패키지를포함한전체경로명 (Fully qualified names) 은 같은형태의경로가있다면그경로내에서직접찾는다. selectallthings 과같은짧은형태의이름은모호하지않은엔트리를참고하기위해사용될수있다. 그래서짧은 이름은모호해서에러를자주보게되니되도록이면전체경로를사용해야할것이다. BlogMapper 와같은 Mapper 클래스에는몇가지트릭이있다. 매핑된구문은 XML 에전혀매핑될필요가없다. 대신자바 애노테이션을사용할수있다. 예를들어, 위 XML 예제는다음과같은형태로대체될수있다. package org.mybatis.example; public interface BlogMapper * FROM blog WHERE id = #{id") Blog selectblog(int id); 간단한구문에서는애노테이션이좀더깔끔하다. 어쨌든자바애노테이션은좀더복잡한구문에서는제한적이고코드를 엉망으로만들수있다. 그러므로, 복잡하게사용하고자한다면, XML 매핑구문을사용하는것이좀더나을것이다. 스코프 (Scope) 와생명주기 (Lifecycle) 이제부터다룰스코프와생명주기에대해서이해하는것은매우중요하다. 스코프와생명주기를잘못사용하는것은다양한 동시성문제를야기할수있다.. SqlSessionFactoryBuilder 이클래스는인스턴스회되어사용되고던져질수있다. SqlSessionFactory 를생성한후유지할필요는없다. 그러므로 SqlSessionFactoryBuilder 인스턴스의가장좋은스코프는메서드스코프 ( 예를들면, 메서드지역변수 ) 이다. 여러개의
9 SqlSessionFactory 인스턴스를빌드하기위해 SqlSessionFactoryBuilder 를재사용할수도있지만유지하지않는것이가장 좋다.. SqlSessionFactory 한번만든뒤, SqlSessionFactory 는애플리케이션을실행하는동안존재해야만한다. 그래서삭제하거나재생성할필요가없다. 애플리케이션이실행되는동안여러차례 SqlSessionFactory 를다시빌드하지않는것이가장좋은형태이다. 재빌드하는형태는결과적으로 나쁜냄새 가나도록한다. 그러므로 SqlSessionFactory 의가장좋은스코프는애플리케이션스코프이다. 애플리케이션스코프로유지하기위한다양한방법이존재한다. 가장간단한방법은싱글턴패턴이나 static 싱글턴패턴을사용하는것이다. 또는구글 Guice 나 Spring 과같은의존성삽입컨테이너를선호할수도있다. 이러한프레임워크는 SqlSessionFactory 의생명주기를싱글턴으로관리할것이다. SqlSession 각각의쓰레드는자체적으로 SqlSession 인스턴스를가져야한다. SqlSession 인스턴스는공유되지않고쓰레드에안전하지도않다. 그러므로가장좋은스코프는요청또는메서드스코프이다. SqlSession 을 static 필드나클래스의인스턴스필드로지정해서는안된다. 그리고서블릿프레임워크의 HttpSession 과같은관리스코프에둬서도안된다. 어떠한종류의웹프레임워크를사용한다면, HTTP 요청과유사한스코프에두는것으로고려해야한다. 달리말해서, HTTP 요청을받을? 때마다만들고, 응답을리턴할때마다 SqlSession 을닫을수있다. SqlSession 을닫는것은중요하다. 언제나 finally 블록에서닫아야만한다. 다음은 SqlSession 을닫는것을확인하는표준적인형태다. SqlSession session = sqlsessionfactory.opensession(); try { // do work finally { session.close(); Mapper 인스턴스 Mapper 는매핑된구문을바인딩하기위해만들어야할인터페이스이다. mapper 인터페이스의인스턴스는 SqlSession 에서생성한다. 그래서 mapper 인스턴스의가장좋은스코프는 SqlSession 과동일하다. 어쨌든 mapper 인스턴스의가장좋은스코프는메서드스코프이다. 사용할메서드가호출되면생성되고끝난다. 명시적으로닫을필요는없다. SqlSession session = sqlsessionfactory.opensession(); try { BlogMapper mapper = session.getmapper(blogmapper.class); // do work finally { session.close();
10 매퍼설정 XML MyBatis XML 설정파일은다양한셋팅과프로퍼티를가진다. 문서의구조는다음과같다.: configuration o properties o settings o typealiases o typehandlers o objectfactory o plugins o environments environment transactionmanager datasource o mappers properties 이설정은외부에옮길수있다. 자바프로퍼티파일인스턴스에설정할수도있고, properties 요소의하위요소에둘수도 있다. 예를들면 : <properties resource="org/mybatis/example/config.properties"> <property name="username" value="dev_user"/> <property name="password" value="f2fa3!33tyyg"/> </properties> 속성들은파일도처에둘수도있다. 예를들면 : <datasource type="pooled"> <property name="driver" value="${driver"/> <property name="url" value="${url"/> <property name="username" value="${username"/> <property name="password" value="${password"/> </datasource> 이에제에서 username 과 password 는 properties 요소의설정된값으로대체될수있다. driver 와 url 속성은 config.properties 파일에포함된값으로대체될수도있다. 이것은설정에대한다양한옵션을제공하는셈이다. 속성은 SqlSessionBuilder.build() 메서드에전달될수있다. 예를들면 : SqlSessionFactory factory = sqlsessionfactorybuilder.build(reader, props); //... or... SqlSessionFactory factory =
11 sqlsessionfactorybuilder.build(reader, environment, props); 속성이한개이상존재한다면, MyBatis 는일정한순서로로드한다.: properties 요소에명시된속성을가장먼저읽는다. properties 요소의클래스패스자원이나 url 속성으로부터로드된속성을두번재로읽는다. 그래서이미읽은값이 있다면덮어쓴다. 마지막으로메서드파라미터로전달된속성을읽는다. 앞서로드된값을덮어쓴다. 그래서가장우선순위가높은속성은메서드의파라미터로전달된값이고그다음은자원및 url 속성이고마지막은 properties 요소에명시된값이다. settings 런타임시 MyBatis 의행위를조정하기위한중요한값들이다. 다음표는셋팅과그의미그리고디폴트값을설명한다. 셋팅 설명 사용가능한값들 cacheenabled 설정에서각 mapper 에설정된캐시를전역적으로 true false 사용할지말지에대한여부 lazyloadingenabled 늦은로딩을사용할지에대한여부. 사용하지않는다면 true false 모두즉시로딩할것이다. aggressivelazyloading 활성화상태로두게되면늦은 (lazy) 로딩프로퍼티를 true false 가진객체는호출에따라로드될것이다. 반면에개별 프로퍼티는요청할때로드된다. multipleresultsetsenabled 한개의구문에서여러개의 ResultSet 을허용할지의 true false 여부 ( 드라이버가해당기능을지원해야함 ) usecolumnlabel 칼럼명대신에칼럼라벨을사용. 드라이버마다조금 true false 다르게작동한다. 문서와간단한테스트를통해실제 기대하는것처럼작동하는지확인해야한다. usegeneratedkeys 생성키에대한 JDBC 지원을허용. 지원하는 true false 드라이버가필요하다. true 로설정하면생성키를 강제로생성한다. 일부드라이버 ( 예를들면, Derby) 에서는이설정을무시한다. automappingbehavior MyBatis 가칼럼을필드 / 프로퍼티에자동으로 NONE, 매핑할지와방법에대해명시. PARTIAL 은간단한 PARTIAL, 자동매핑만할뿐, 내포된결과에대해서는처리하지 FULL 않는다. FULL 은처리가능한모든자동매핑을 처리한다. defaultexecutortype 디폴트실행자 (executor) 설정. SIMPLE 실행자는 SIMPLE 특별히하는것이없다. REUSE 실행자는 REUSE PreparedStatement 를재사용한다. BATCH 실행자는 BATCH 구문을재사용하고수정을배치처리한다. defaultstatementtimeout 데이터베이스로의응답을얼마나오래기다릴지를 양수 판단하는타임아웃을셋팅 디폴트 true true true true true False PARTIAL SIMPLE 셋팅되지않음 (null)
12 위설정을모두사용한 setting 요소의예제이다 : typealiases <settings> <setting name="cacheenabled" value="true"/> <setting name="lazyloadingenabled" value="true"/> <setting name="multipleresultsetsenabled" value="true"/> <setting name="usecolumnlabel" value="true"/> <setting name="usegeneratedkeys" value="false"/> <setting name="enhancementenabled" value="false"/> <setting name="defaultexecutortype" value="simple"/> <setting name="defaultstatementtimeout" value="25000"/> </settings> 타입별칭은자바타입에대한좀더짧은이름이다. 오직 XML 설정에서만사용되며, 타이핑을줄이기위해존재한다. 예를들면 : <typealiases> <typealias alias="author" type="domain.blog.author"/> <typealias alias="blog" type="domain.blog.blog"/> <typealias alias="comment" type="domain.blog.comment"/> <typealias alias="post" type="domain.blog.post"/> <typealias alias="section" type="domain.blog.section"/> <typealias alias="tag" type="domain.blog.tag"/> </typealiases> 이설정에서, Blog 는도처에서 domain.blog.blog 대신사용될수있다. 공통의자바타입에대해서는내장된타입별칭이있다. 이모두대소문자를가린다.. 별칭 _byte _long _short _int _integer _double _float _boolean string byte long short int integer double 매핑된타입 Byte Long Short Int int double float boolean String Byte Long Short Integer Integer Double
13 별칭 float boolean date decimal bigdecimal object map hashmap list arraylist collection iterator 매핑된타입 Float Boolean Date BigDecimal BigDecimal Object Map HashMap List ArrayList Collection Iterator typehandlers MyBatis 가 PreparedStatement 에파라미터를셋팅하고 ResultSet 에서값을가져올때마다, TypeHandler 는적절한자바 타입의값을가져오기위해사용된다. 다음의표는디폴트 TypeHandlers 를설명한다.. 타입핸들러 자바타입 JDBC 타입 BooleanTypeHandler Boolean, boolean 어떤호환가능한 BOOLEAN ByteTypeHandler Byte, byte 어떤호환가능한 NUMERIC 또는 BYTE ShortTypeHandler Short, short 어떤호환가능한 NUMERIC 또는 SHORT INTEGER IntegerTypeHandler Integer, int 어떤호환가능한 NUMERIC 또는 INTEGER LongTypeHandler Long, long 어떤호환가능한 NUMERIC 또는 LONG INTEGER FloatTypeHandler Float, float 어떤호환가능한 NUMERIC 또는 FLOAT DoubleTypeHandler Double, double 어떤호환가능한 NUMERIC 또는 DOUBLE BigDecimalTypeHandler BigDecimal 어떤호환가능한 NUMERIC 또는 DECIMAL StringTypeHandler String CHAR, VARCHAR ClobTypeHandler String CLOB, LONGVARCHAR NStringTypeHandler String NVARCHAR, NCHAR NClobTypeHandler String NCLOB ByteArrayTypeHandler byte[] 어떤호환가능한 byte 스트림타입 BlobTypeHandler byte[] BLOB, LONGVARBINARY DateTypeHandler Date (java.util) TIMESTAMP DateOnlyTypeHandler Date (java.util) DATE TimeOnlyTypeHandler Date (java.util) TIME SqlTimestampTypeHandler Timestamp (java.sql) TIMESTAMP SqlDateTypeHadler Date (java.sql) DATE SqlTimeTypeHandler Time (java.sql) TIME ObjectTypeHandler Any OTHER, 또는명시하지않는 EnumTypeHandler Enumeration Type VARCHAR 문자열호환타입. 지원하지않거나비표준인타입에대해서는당신스스로만들어서타입핸들러를오버라이드할수있다. 그러기위해서는 TypeHandler 인터페이스를구현하고자바타입에 TypeHandler 를매핑하면된다. 예를들면 :
14 // ExampleTypeHandler.java public class ExampleTypeHandler implements TypeHandler { public void setparameter( PreparedStatement ps, int i, Object parameter,jdbctype jdbctype) throws SQLException { ps.setstring(i, (String) parameter); public Object getresult( ResultSet rs, String columnname) throws SQLException { return rs.getstring(columnname); public Object getresult( CallableStatement cs, int columnindex) throws SQLException { return cs.getstring(columnindex); // MapperConfig.xml <typehandlers> <typehandler javatype="string" jdbctype="varchar" handler="org.mybatis.example.exampletypehandler"/> </typehandlers> 이러한 TypeHandler 를사용하는것은자바 String 프로퍼티와 VARCHAR 파라미터및결과를위해이미존재하는핸들러를오버라이드하게될것이다. MyBatis 는타입을판단하기위해데이터베이스의메타데이터를보지않는다. 그래서파라미터와결과에정확한타입핸들러를매핑해야한다. MyBatis 가구문이실행될때까지는데이터타입에대해모르기때문이다.. objectfactory 매번 MyBatis 는결과객체의인스턴스를만들기위해 ObjectFactory 를사용한다. 디폴트 ObjectFactory 는디폴트생성자를가진대상클래스를인스턴스화하는것보다조금더많은작업을한다. ObjectFactory 의디폴트행위를오버라이드하고자한다면, 만들수있다. 예를들면 : // ExampleObjectFactory.java public class ExampleObjectFactory extends DefaultObjectFactory { public Object create(class type) { return super.create(type); public Object create( Class type, List<Class> constructorargtypes, List<Object> constructorargs) { return super.create(type, constructorargtypes, constructorargs);
15 public void setproperties(properties properties) { super.setproperties(properties); // MapperConfig.xml <objectfactory type="org.mybatis.example.exampleobjectfactory"> <property name="someproperty" value="100"/> </objectfactory> ObjectFactory 인터페이스는매우간단한다. 두개의 create 메서드를가지고있으며, 하나는디폴트생성자를처리하고다른하나는파라미터를가진생성자를처리한다. 마지막으로 setproperties 메서드는 ObjectFactory 를설정하기위해사용될수있다. objectfactory 요소에정의된프로퍼티는 ObjectFactory 인스턴스가초기화된후 setproperties 에전달될것이다. plugins MyBatis 는매핑구문을실행하는어떤시점에호출을가로챈다. 기본적으로 MyBatis 는메서드호출을가로채기위한 플러그인을허용한다. Executor (update, query, flushstatements, commit, rollback, gettransaction, close, isclosed) ParameterHandler (getparameterobject, setparameters) ResultSetHandler (handleresultsets, handleoutputparameters) StatementHandler (prepare, parameterize, batch, update, query) 이클래스들의메서드는각각메서드시그니처를통해찾을수있고소스코드는 MyBatis 릴리즈파일에서찾을수있다. 오버라이드할메서드의행위를이해해야만한다. 주어진메서드의행위를변경하거나오버라이드하고자한다면, MyBatis 의 핵심기능에악영향을줄수도있다. 이러한로우레벨클래스와메서드들은주의를해서사용해야한다. 플러그인을사용하는것을제공하는기능에다소간단하다. Interceptor 인터페이스를간단히구현해서, 가로채고 (intercept) 싶은시그니처를명시해야한다. // type= Executor.class, method = "update", args = {MappedStatement.class,Object.class)) public class ExamplePlugin implements Interceptor {
16 public Object intercept(invocation invocation) throws Throwable { return invocation.proceed(); public Object plugin(object target) { return Plugin.wrap(target, this); public void setproperties(properties properties) { // MapperConfig.xml <plugins> <plugin interceptor="org.mybatis.example.exampleplugin"> <property name="someproperty" value="100"/> </plugin> </plugins> 위플러그인은매핑된구문의로우레벨실행을책임지는내부객체인 Executor 인스턴스의 update 메서드호출을모두 가로챌것이다. 설정파일오버라이드하기 플러그인을사용해서 MyBatis 핵심행위를변경하기위해, Configuration 클래스전체를오버라이드할수있다. 이클래스를확장하고내부메서드를오버라이드하고, sqlsessionfactorybuilder.build(myconfig) 메서드에그객체를넣어주면된다. 다시얘기하지만이작업은 MyBatis 에큰영향을줄수있으니주의해서해야한다. environments MyBatis 는여러개의환경으로설정될수있다. 여러가지이유로여러개의데이터베이스에 SQL Map 을적용하는데도움이된다. 예를들어, 개발, 테스트, 리얼환경을위해별도의설정을가지거나, 같은스키마를여러개의 DBMS 제품을사용할경우들이다. 그외에도많은경우가있을수있다. 중요하게기억해야할것은, 다중환경을설정할수는있지만, SqlSessionFactory 인스턴스마다한개만사용할수있다는 것이다. 두개의데이터베이스에연결하고싶다면, SqlSessionFactory 인스턴스를두개만들필요가있다. 세개의데이터베이스를 사용한다면, 역시 3 개의인스턴스를필요로한다. 기억하기쉽게 데이터베이스별로하나의 SqlSessionFactory 환경을명시하기위해, SqlSessionFactoryBuilder 에옵션으로추가파라미터를주면된다. 환경을선택하는두가지 시그니처는 SqlSessionFactory factory = sqlsessionfactorybuilder.build(reader, environment); SqlSessionFactory factory = sqlsessionfactorybuilder.build(reader, environment,properties); environment 파라미터가없으면, 디폴트환경이로드된다
17 SqlSessionFactory factory = sqlsessionfactorybuilder.build(reader); SqlSessionFactory factory = sqlsessionfactorybuilder.build(reader,properties); environments 요소는환경을설정하는방법을정의한다. <environments default="development"> <environment id="development"> <transactionmanager type="jdbc"> <property name="..." value="..."/> </transactionmanager> <datasource type="pooled"> <property name="driver" value="${driver"/> <property name="url" value="${url"/> <property name="username" value="${username"/> <property name="password" value="${password"/> </datasource> </environment> </environments> 중요한부분을살펴보면 디폴트환경 (Environment) ID ( 예를들면. default= development ). 각각의환경을정의한환경 (Environment) ID ( 예를들면. id= development ). TransactionManager 설정 ( 예를들면. type= JDBC ) DataSource 설정 ( 예를들면. type= POOLED ) 디폴트환경 (environment) 과환경 (environment) ID 는용어자체가역할을설명한다. transactionmanager MyBatis 는두가지타입의 TransactionManager 를제공한다. JDBC 이설정은간단하게 JDBC 커밋과롤백을처리하기위해사용된다. 트랜잭션의스코프를관리하기위해 datasource 로부터커넥션을가져온다. MANAGED 이설정은어떤것도하지않는다. 결코커밋이나롤백을하지않는다. 대신컨테이너가트랜잭션의 모든생명주기를관리한다. 디플트로커넥션을닫긴한다. 하지만몇몇컨테이너는커넥션을닫는것또한기대하지 않기때문에, 커넥션닫는것으로멈추고자한다면, closeconnection 프로퍼티를 false 로설정하라. 예를들면 : <transactionmanager type="managed"> <property name="closeconnection" value="false"/> </transactionmanager>
18 TransactionManager 타입은어떠한프로퍼티도필요하지않다. 어쨌든둘다타입별칭이있다. 즉 TransactionFactory 를 위한클래스명이나타입별칭중하나를사용할수있다. public interface TransactionFactory { void setproperties(properties props); Transaction newtransaction(connection conn, boolean autocommit); XML 에설정된프로퍼티는인스턴스를만든뒤 setproperties() 메서드에전달할것이다. 당신의구현체가 Transaction 구현체를만들필요가있을것이다.: public interface Transaction { Connection getconnection(); void commit() throws SQLException; void rollback() throws SQLException; void close() throws SQLException; 이두개의인터페이스를사용하여, MyBatis 가트랜잭션을처리하는방법을완벽하게정의할수있다.. datasource datasource 요소는표준 JDBC DataSource 인터페이스를사용하여 JDBC Connection 객체의소스를설정한다. 대부분의 MyBatis 애플리케이션은예제처럼 datasource 를설정할것이다. 여기엔 3 가지의내장된 datasource 타입이있다. UNPOOLED 이구현체는매번요청에대해커넥션을열고닫는간단한 DataSource 이다. 조금늦긴하지만성능을크게 필요로하지않는간단한애플리케이션을위해서는괜찮은선택이다. UNPOOLED DataSource 는 5 개의프로퍼티만으로 설정된다. driver JDBC 드라이버의패키지경로를포함한결제자바클래스명 url 데이터베이스인스턴스에대한 JDBC URL. username 데이터베이스에로그인할때사용할사용자명 password - 데이터베이스에로그인할때사용할패스워드 defaulttransactionisolationlevel 커넥션에대한디폴트트랜잭션격리레벨 필수는아니지만선택적으로데이터베이스드라이버에프로퍼티를전달할수도있다. 그러기위해서는다음예제처럼 driver. 로시작하는접두어로프로퍼티를명시하면된다
19 driver.encoding=utf8 이설정은 encoding 프로퍼티를 UTF8 로설정하게된다. 이방법외에도 DriverManager.getConnection(url, driverproperties) 메서드를통해서도프로퍼티를설정할수있다. POOLED DataSource 에풀링이적용된 JDBC 커넥션을위한구현체이다. 이는새로운 Connection 인스턴스를생성하기위해매번초기화하는것을피하게해준다. 그래서빠른응답을요구하는웹애플리케이션에서는가장흔히사용되고있다. UNPOOLED DataSource 에비해, 많은프로퍼티를설정할수있다. poolmaximumactiveconnections 주어진시간에존재할수있는활성화된 ( 사용중인 ) 커넥션의수. 디폴트는 10 이다. poolmaximumidleconnections 주어진시간에존재할수있는유휴커넥션의수 poolmaximumcheckouttime 강제로리턴되기전에풀에서 체크아웃 될수있는커넥션의시간. 디폴트는 20000ms(20 초 ) pooltimetowait 풀이로그상태를출력하고비정상적으로긴경우커넥션을다시얻을려고시도하는로우레벨셋팅. 디폴트는 20000ms(20 초 ) poolpingquery 커넥션이작업하기좋은상태이고요청을받아서처리할준비가되었는지체크하기위해데이터베이스에던지는핑쿼리 (Ping Query). 디폴트는 핑쿼리가없음 이다. 이설정은대부분의데이터베이스로하여금에러메시지를보게할수도있다. poolpingenabled 핑쿼리를사용할지말지를결정. 사용한다면, 오류가없는 ( 그리고빠른 ) SQL 을사용하여 poolpingquery 프로퍼티를셋팅해야한다. 디폴트는 false 이다. poolpingconnectionsnotusedfor poolpingquery 가얼마나자주사용될지설정한다. 필요이상의핑을피하기위해데이터베이스의타임아웃값과같을수있다. 디폴트는 0 이다. 디폴트값은 poolpingenabled 가 true 일경우에만, 모든커넥션이매번핑을던지는값이다. JNDI 이 DataSource 구현체는컨테이너에따라설정이변경되며, JNDI 컨텍스트를참조한다. 이 DataSource 는오직두개의프로퍼티만을요구한다. initial_context 이프로퍼티는 InitialContext 에서컨텍스트를찾기 ( 예를들어, initialcontext.lookup(initial_context)) 위해사용된다. 이프로퍼티는선택적인값이다. 이설정을생략하면, data_source 프로퍼티가 InitialContext 에서직접찾을것이다. data_source DataSource 인스턴스의참조를찾을수있는컨텍스트경로이다. initial_context 룩업을통해 리턴된컨텍스트에서찾을것이다. initial_context 가지원되지않는다면, InitialContext 에서직접찾을것이다. 다른 DataSource 설정과유사하게, 다음처럼 env. 를접두어로프로퍼티를전달할수있다. env.encoding=utf8 이설정은인스턴스화할때 InitialContext 생성자에 encoding 프로퍼티를 UTF8 로전달한다
20 mappers 이제우리는매핑된 SQL 구문을정의할시간이다. 하지만먼저, 설정을어디에둘지결정해야한다. 자바는자동으로리소스를찾기위한좋은방법을제공하지않는다. 그래서가장좋은건어디서찾으라고지정하는것이다. 클래스패스에상대적으로리소스를지정할수도있고, url 을통해서지정할수도있다. 예를들면 // Using classpath relative resources <mappers> <mapper resource="org/mybatis/builder/authormapper.xml"/> <mapper resource="org/mybatis/builder/blogmapper.xml"/> <mapper resource="org/mybatis/builder/postmapper.xml"/> </mappers> // Using url fully qualified paths <mappers> <mapper url="file:///var/sqlmaps/authormapper.xml"/> <mapper url="file:///var/sqlmaps/blogmapper.xml"/> <mapper url="file:///var/sqlmaps/postmapper.xml"/> </mappers> SQL 매핑파일에대해서좀더자세히알아보자. SQL Map XML 파일 MyBatis 의가장큰장점은매핑된구문이다. 이건간혹마법을부리는것처럼보일수있다. SQL Map XML 파일은상대적으로간단하다. 더군다나동일한기능의 JDBC 코드와비교하면아마도 95% 이상코드수가감소하기도한다. MyBatis 는 SQL 을작성하는데집중하도록만들어졌다. SQL Map XML 파일은첫번째 (first class) 요소만을가진다. cache 해당명명공간을위한캐시설정 cache-ref 다른명명공간의캐시설정에대한참조 resultmap 데이터베이스결과데이터를객체에로드하는방법을정의하는요소 parametermap 비권장됨! 예전에파라미터를매핑하기위해사용되었으나현재는사용하지않음 sql 다른구문에서재사용하기위한 SQL 조각 insert 매핑된 INSERT 구문 update 매핑된 UPDATE 구문. delete 매핑된 DELEETE 구문. select 매핑된 SELECT 구문
21 다음섹션에서는각각에대해좀더세부적으로살펴볼것이다. select select 구문은 MyBatis 에서가장흔히사용할요소이다. 데이터베이스에서데이터를가져온다. 아마도대부분의애플리케이션은데이터를수정하기보다는조회하는기능을많이가진다. 그래서 MyBatis 는데이터를조회하고그결과를매핑하는데집중하고있다. Select 는다음예처럼단순한경우에는단순하게설정된다. <select id= selectperson parametertype= int resulttype= hashmap > SELECT * FROM PERSON WHERE ID = #{id </select> 이구문의이름은 selectperson 이고 int 타입의파라미터를가진다. 그리고결과데이터는 HashMap 에저장된다. 파라미터 표기법을보자. #{id 이표기법은 MyBatis 에게 PreparedStatement 파라미터를만들도록지시한다. JDBC 를사용할때 PreparedStatement 에는? 형태로파라미터가전달된다. 즉결과적으로위설정은아래와같이작동하게되는셈이다. // Similar JDBC code, NOT MyBatis String selectperson = SELECT * FROM PERSON WHERE ID=? ; PreparedStatement ps = conn.preparestatement(selectperson); ps.setint(1,id); 물론 JDBC 를사용하면, 결과를가져와서객체의인스턴스에매핑하기위한많은코드가필요하겠지만, MyBatis 는그 코드들을작성하지않아도되게해준다. select 요소는각각의구문이처리하는방식에대해좀더세부적으로설정하도록많은속성을설정할수있다. <select id= selectperson parametertype= int parametermap= deprecated resulttype= hashmap resultmap= personresultmap flushcache= false usecache= true timeout= fetchsize= 256 statementtype= PREPARED resultsettype= FORWARD_ONLY > 속성 id parametertype parametermap 설명구문을찾기위해사용될수있는명명공간내유일한구분자구문에전달될파라미터의패키지경로를포함한전체클래스명이나별칭외부 parametermap 을찾기위한비권장된접근방법. 인라인파라미터매핑과 parametertype 을대신사용하라
22 속성설명 resulttype 이구문에의해리턴되는기대타입의패키지경로를포함한전체클래스명이나별칭. collection 이경우, collection 타입자체가아닌 collection 이포함된타입이될수있다. resulttype 이나 resultmap 을사용하라. resultmap 외부 resultmap 의참조명. 결과맵은 MyBatis 의가장강력한기능이다. resulttype 이나 resultmap 을사용하라. flushcache 이값을 true 로셋팅하면, 구문이호출될때마다캐시가지원질것이다 (flush). 디폴트는 false 이다. usecache 이값을 true 로셋팅하면, 구문의결과가캐시될것이다. 디폴트는 true 이다. timeout 예외가던져지기전에데이터베이스의요청결과를기다리는최대시간을설정한다. 디폴트는셋팅하지않는것이고드라이버에따라다소지원되지않을수있다. fetchsize 지정된수만큼의결과를리턴하도록하는드라이버힌트형태의값이다. 디폴트는셋팅하지않는것이고드라이버에따라다소지원되지않을수있다. statementtype STATEMENT, PREPARED 또는 CALLABLE 중하나를선택할수있다. MyBatis 에게 Statement, PreparedStatement 또는 CallableStatement 를사용하게한다. 디폴트는 PREPARED 이다. resultsettype FORWARD_ONLY SCROLL_SENSITIVE SCROLL_INSENSITIVE 중하나를선택할수있다. 디폴트는셋팅하지않는것이고드라이버에다라다소지원되지않을수있다. insert, update, delete 데이터를변경하는구문인 insert, update, delete 는매우간단하다. <insert id="insertauthor" parametertype="domain.blog.author" flushcache="true" statementtype="prepared" keyproperty="" keycolumn="" usegeneratedkeys="" timeout="20000"> <update id="insertauthor" parametertype="domain.blog.author" flushcache="true" statementtype="prepared" timeout="20000"> <delete id="insertauthor" parametertype="domain.blog.author" flushcache="true" statementtype="prepared" timeout="20000"> 속성 Id parametertype 설명 구문을찾기위해사용될수있는명명공간내유일한구분자 구문에전달될파라미터의패키지경로를포함한전체클래스명이나별칭
23 속성설명 parametermap 외부 parametermap 을찾기위한비권장된접근방법. 인라인파라미터매핑과 parametertype 을대신사용하라. flushcache 이값을 true 로셋팅하면, 구문이호출될때마다캐시가지원질것이다 (flush). 디폴트는 false 이다. Timeout 예외가던져지기전에데이터베이스의요청결과를기다리는최대시간을설정한다. 디폴트는셋팅하지않는것이고드라이버에따라다소지원되지않을수있다. statementtype STATEMENT, PREPARED 또는 CALLABLE 중하나를선택할수있다. MyBatis 에게 Statement, PreparedStatement 또는 CallableStatement 를사용하게한다. 디폴트는 PREPARED 이다. usegeneratedkeys ( 입력 (insert) 에만적용 ) 데이터베이스에서내부적으로생성한키 ( 예를들어, MySQL 또는 SQL Server 와같은 RDBMS 의자동증가필드 ) 를받는 JDBC getgeneratedkeys 메서드를사용하도록설정하다. 디폴트는 false 이다. keyproperty ( 입력 (insert) 에만적용 ) getgeneratedkeys 메서드나 insert 구문의 selectkey 하위요소에의해리턴된키를셋팅할프로퍼티를지정. 디폴트는셋팅하지않는것이다. keycolumn ( 입력 (insert) 에만적용 ) 생성키를가진테이블의칼럼명을셋팅. 키칼럼이테이블이첫번째칼럼이아닌데이터베이스 (PostgreSQL 처럼 ) 에서만필요하다. Insert, update, delete 구문의예제이다. <insert id="insertauthor" parametertype="domain.blog.author"> insert into Author (id,username,password, ,bio) values (#{id,#{username,#{password,#{ ,#{bio) </insert> <update id="updateauthor" parametertype="domain.blog.author"> update Author set username = #{username, password = #{password, = #{ , bio = #{bio where id = #{id </update> <delete id="deleteauthor parametertype="int"> delete from Author where id = #{id </delete> 앞서설명했지만, insert 는 key 생성과같은기능을위해몇가지추가속성과하위요소를가진다. 먼저, 사용하는데이터베이스가자동생성키 ( 예를들면, MySQL 과 SQL 서버 ) 를지원한다면, usegeneratedkeys= true 로설정하고대상프로퍼티에 keyproperty 를셋팅할수있다. 예를들어, Author 테이블이 id 칼럼에자동생성키를적용했다고하면, 구문은아래와같은형태일것이다. <insert id="insertauthor" parametertype="domain.blog.author" usegeneratedkeys= true keyproperty= id > insert into Author (username,password, ,bio) values (#{username,#{password,#{ ,#{bio) </insert>
24 MyBatis 는자동생성키칼럼을지원하지않는다른데이터베이스를위해다른방법또한제공한다. 이예제는랜덤 ID 를생성하고있다. <insert id="insertauthor" parametertype="domain.blog.author"> <selectkey keyproperty="id" resulttype="int" order="before"> select CAST(RANDOM()* as INTEGER) a from SYSIBM.SYSDUMMY1 </selectkey> insert into Author (id, username, password, ,bio, favourite_section) values (#{id, #{username, #{password, #{ , #{bio, #{favouritesection,jdbctype=varchar ) </insert> 위예제에서, selectkey 구문이먼저실행되고, Author id 프로퍼티에셋팅된다. 그리고나서 insert 구문이실행된다. 이건 복잡한자바코드없이도데이터베이스에자동생성키의행위와비슷한효과를가지도록해준다. selectkey 요소는다음처럼설정가능하다. <selectkey keyproperty="id" resulttype="int" order="before" statementtype="prepared"> 속성설명 keyproperty selectkey 구문의결과가셋팅될대상프로퍼티 resulttype 결과의타입. MyBatis 는이기능을제거할수있지만추가하는게문제가되지는않을것이다. MyBatis 는 String 을포함하여키로사용될수있는간단한타입을허용한다. order BEFORE 또는 AFTER 를셋팅할수있다. BEFORE 로셋팅하면, 키를먼저조회하고그값을 keyproperty 에셋팅한뒤 insert 구문을실행한다. AFTER 로셋팅하면, insert 구문을실행한뒤 selectkey 구문을실행한다. Oracle 과같은데이터베이스에서는 insert 구문내부에서일관된호출형태로처리한다. statementtype 위내용과같다. MyBatis 는 Statement, PreparedStatement 그리고 CallableStatement 을매핑하기위해 STATEMENT, PREPARED 그리고 CALLABLE 구문타입을지원한다. sql 이요소는다른구문에서재사용가능한 SQL 구문을정의할때사용된다. <sql id= usercolumns > id,username,password </sql> SQL 조각은다른구문에포함시킬수있다. <select id= selectusers parametertype= int resulttype= hashmap > select <include refid= usercolumns /> from some_table where id = #{id
25 </select> Parameters 앞서본구문들에서, 간단한파라미터들의예를보았을것이다. Parameters 는 MyBatis 에서매우중요한요소이다. 대략 90% 정도의간단한경우, 이러한형태로설정할것이다. <select id= selectusers parametertype= int resulttype= User > select id, username, password from users where id = #{id </select> 위예제는매우간단한명명된파라미터매핑을보여준다. parametertype 은 int 로설정되어있다. Integer 과 String 과같은원시타입이나간단한데이터타입은프로퍼티를가지지않는다. 그래서파라미터전체가값을대체하게된다. 하지만복잡한객체를전달하고자한다면, 다음의예제처럼상황은조금다르게된다. <insert id= insertuser parametertype= User > insert into users (id, username, password) values (#{id, #{username, #{password) </insert> User 타입의파라미터객체가구문으로전달되면, id, username, password 프로퍼티는찾아서 PreparedStatement 파라미터로전달된다. 비록파라미터들을구문에전달하는괜찮은예제이지만, 파라미터매핑을위한다른기능또한더있다. 먼저, 파라미터에데이터타입을명시할수있다. #{property,javatype=int,jdbctype=numeric javatype 은파라미터객체의타입을판단하는기준이된다. javatype 은 TypeHandler 를사용하여정의할수도있다. Note: 만약특정칼럼에 null 이전달되면, JDBC Type 은 null 가능한칼럼을위해필요하다. 처리방법에대해서는 PreparedStatement.setNull() 메서드의 JavaDoc 을보라. 좀더다양하게타입핸들링하기위해서는, TypeHandler 클래스를명시할수있다. #{age,javatype=int,jdbctype=numeric,typehandler=mytypehandler 숫자타입을위해서, 크기를판단하기위한 numericscale 속성도있다. #{height,javatype=double,jdbctype=numeric,numericscale=2 마지막으로, mode 속성은 IN, OUT 또는 INOUT 파라미터를명시하기위해사용한다. 파라미터가 OUT 또는 INOUT 이라면, 파라미터의실제값은변경될것이다. mode=out( 또는 INOUT) 이고 jdbctype=cursor( 예를들어, Oracle REFCURSOR) 라면, 파라미터의타입에 ResultSet 를매핑하기위해 resultmap 을명시해야만한다. #{department,
26 mode=out, jdbctype=cursor, javatype=resultset, resultmap=departmentresultmap MyBatis 는 structs 와같은좀더향상된데이터타입을지원하지만, 파라미터를등록할때, 타입명을구문에전달해야한다. 예를들면, #{middleinitial, mode=out, jdbctype=struct, jdbctypename=my_type, resultmap=departmentresultmap 이런강력한옵션들에도불구하고, 대부분은프로퍼티명만명시하거나 null 가능한칼럼을위해 jdbctype 정도만명시할 것이다. #{firstname #{middleinitial,jdbctype=varchar #{lastname 문자열대체 (String Substitution) #{ 문법은 MyBatis 로하여금 PreparedStatement 프로퍼티를만들어서 PreparedStatement 파라미터 ( 예를들면,?) 에 값을셋팅하도록할것이다. 이방법이안전하기는하지만, 좀더빠른방법이선호되기도한다. 가끔은 SQL 구문에변하지 않는값으로삽입하길원하기도한다. 예를들면, ORDER BY 와같은구문들이다. ORDER BY ${columnname 여기서 MyBatis 는문자열을변경하거나이스케이프처리하지않는다. 중요 : 사용자로부터받은값을이방법으로변경하지않고구문에전달하는건안전하지않다. 이건잠재적으로 SQL 주입공격에노출된다. 그러므로사용자입력값에대해서는이방법을사용하면안된다. 사용자입력값에대해서는언제나자체적으로이스케이프처리하고체크해야한다. resultmap resultmap 요소는 MyBatis 에서가장중요하고강력한요소이다. ResultSet 에서데이터를가져올때작성되는 JDBC 코드를대부분줄여주는역할을담당한다. 사실 join 매핑과같은복잡한코드는굉장히많은코드가필요하다. ResultMap 은간단한구문에서는매핑이필요하지않고, 좀더복잡한구문에서관계를서술하기위해필요하다. 이미앞에서명시적인 resultmap 을가지지않는간단한매핑구문은봤을것이다. <select id= selectusers parametertype= int resulttype= hashmap > select id, username, hashedpassword from some_table where id = #{id
27 </sql> 모든칼럼의값이결과가되는간단한구문에서는 HashMap 에서키형태로자동으로매핑된다. 하지만대부분의경우, HashMap 은매우좋은도메인모델이되지는못한다. 그래서대부분도메인모델로는자바빈이나 POJO 를사용할것이다. MyBatis 는둘다지원한다. 자바빈의경우를보자. package com.someapp.model; public class User { private int id; private String username; private String hashedpassword; public int getid() { return id; public void setid(int id) { this.id = id; public String getusername() { return username; public void setusername(string username) { this.username = username; public String gethashedpassword() { return hashedpassword; public void sethashedpassword(string hashedpassword) { this.hashedpassword = hashedpassword; 자바빈스펙에기반하여, 위클래스는 3 개의프로퍼티 (id, username, hashedpassword) 를가진다. 이프로퍼티는 select 구문에서칼럼명과정확히일치한다. 그래서자바빈은 HashMap 과마찬가지로매우쉽게 ResultSet 에매핑될수있다. <select id= selectusers parametertype= int resulttype= com.someapp.model.user > select id, username, hashedpassword from some_table where id = #{id </sql> 그리고 TypeAliases 가편리한기능임을기억해두는게좋다. TypeAliases 를사용하면타이핑수를줄일수있다. 예를들면, <!-- In Config XML file --> <typealias type= com.someapp.model.user alias= User />
28 <!-- In SQL Mapping XML file --> <select id= selectusers parametertype= int resulttype= User > select id, username, hashedpassword from some_table where id = #{id </sql> 이경우 MyBatis 는칼럼을자바빈에이름기준으로매핑하여 ResultMap 을자동으로생성할것이다. 만약칼럼명이 프로퍼티명과다르다면, SQL 구문에별칭을지정할수있다. 예를들면. <select id= selectusers parametertype= int resulttype= User > select user_id as id, user_name as username, hashed_password as hashedpassword from some_table where id = #{id </sql> ResultMap 에대한중요한내용은다보았다. 하지만다본건아니다. 칼럼명과프로퍼티명이다른경우에대해 데이터베이스별칭을사용하는것과다른방법으로명시적인 resultmap 을선언하는방법이있다. <resultmap id="userresultmap" type="user"> <id property="id" column="user_id" /> <result property="username" column="username"/> <result property="password" column="password"/> </resultmap> 구문에서는 resultmap 속성에이를지정하여참조한다. 예를들면. <select id= selectusers parametertype= int resultmap= userresultmap > select user_id, user_name, hashed_password from some_table where id = #{id </sql> Advanced Result Mapping 이런복잡한구문은어떻게매핑할까.? <!-- Very Complex Statement --> <select id="selectblogdetails" parametertype="int" resultmap="detailedblogresultmap"> select B.id as blog_id, B.title as blog_title,
29 B.author_id as blog_author_id, A.id as author_id, A.username as author_username, A.password as author_password, A. as author_ , A.bio as author_bio, A.favourite_section as author_favourite_section, P.id as post_id, P.blog_id as post_blog_id, P.author_id as post_author_id, P.created_on as post_created_on, P.section as post_section, P.subject as post_subject, P.draft as draft, P.body as post_body, C.id as comment_id, C.post_id as comment_post_id, C.name as comment_name, C.comment as comment_text, T.id as tag_id, T.name as tag_name from Blog B left outer join Author A on B.author_id = A.id left outer join Post P on B.id = P.blog_id left outer join Comment C on P.id = C.post_id left outer join Post_Tag PT on PT.post_id = P.id left outer join Tag T on PT.tag_id = T.id where B.id = #{id </select> 아마 Author 에의해작성되고 Comments 이나태그를가지는많은포스트를가진 Blog 를구성하는괜찮은객체모델에 매핑하고싶을것이다. 이건복잡한 ResultMap 으로충분한예제이다. 복잡해보이지만단계별로살펴보면지극히간단하다. <!-- Very Complex Result Map --> <resultmap id="detailedblogresultmap" type="blog"> <constructor> <idarg column="blog_id" javatype="int"/> </constructor> <result property="title" column="blog_title"/> <association property="author" column="blog_author_id" javatype=" Author"> <id property="id" column="author_id"/> <result property="username" column="author_username"/> <result property="password" column="author_password"/> <result property=" " column="author_ "/> <result property="bio" column="author_bio"/> <result property="favouritesection" column="author_favourite_section"/> </association> <collection property="posts" oftype="post">
30 <id property="id" column="post_id"/> <result property="subject" column="post_subject"/> <association property="author" column="post_author_id" javatype="author"/> <collection property="comments" column="post_id" oftype=" Comment"> <id property="id" column="comment_id"/> </collection> <collection property="tags" column="post_id" oftype=" Tag" > <id property="id" column="tag_id"/> </collection> <discriminator javatype="int" column="draft"> <case value="1" resulttype="draftpost"/> </discriminator> </collection> </resultmap> resultmap 요소는많은하위요소를가진다. 다음은 resultmap 요소의개념적인뷰 (conceptual view) 이다. resultmap constructor 인스턴스화되는클래스의생성자에결과를삽입하기위해사용됨 o idarg ID 인자 ; ID 와같은결과는전반적으로성능을향상시킨다. o arg 생성자에삽입되는일반적인결과 id ID 결과 ; ID 와같은결과는전반적으로성능을향상시킨다. result 필드나자바빈프로퍼티에삽입되는일반적인결과 association 복잡한타입의연관관계 ; 많은결과는타입으로나타난다. o nested result mappings resultmap 스스로의연관관계 collection 복잡한타입의컬렉션 o nested result mappings resultmap 스스로의연관관계 discriminator 사용할 resultmap 을판단하기위한결과값을사용 o case 몇가지값에기초한결과매핑 nested result mappings a case is also a result map itself, and thus can contain many of these same elements, or it can refer to an external resultmap. 가장좋은형태 : 매번 ResultMap 을추가해서빌드한다. 이경우단위테스트가도움이될수있다. 한번에모든 resultmap 을빌드하면, 작업하기어려울것이다. 간단히시작해서단계별로처리하는것이좋다. 프레임워크를사용하는것은종종블랙박스와같다. 가장좋은방법은단위테스트를통해기대하는행위를달성하는것이다. 이건버그가발견되었을때디버깅을위해서도좋은방법이다. 다음섹션은각각의요소에대해좀더상세하게살펴볼것이다. id, result <id property="id" column="post_id"/> <result property="subject" column="post_subject"/> 이건결과매핑의가장기본적인형태이다. id 와 result 모두한개의칼럼을한개의프로퍼티나간단한데이터타입의필드에 매핑한다
31 둘사이의차이점은 id 값은객체인스턴스를비교할때사용되는구분자프로퍼티로처리되는점이다. 이점은일반적으로 성능을향상시키지만특히캐시와내포된 (nested) 결과매핑 ( 조인매핑 ) 의경우에더그렇다. 둘다다수의속성을가진다. 속성 property column javatype jdbctype typehandler 설명결과칼럼에매핑하기위한필드나프로퍼티. 자바빈프로퍼티가해당이름과일치한다면, 그프로퍼티가사용될것이다. 반면에 MyBatis 는해당이름이필드를찾을것이다. 점표기를사용하여복잡한프로퍼티검색을사용할수있다. 예를들어, username 과같이간단하게매핑될수있거나 address.street.number 처럼좀더복잡하게매핑될수도있다. 데이터베이스의칼럼명이나별칭된칼럼라벨. resultset.getstring(columnname) 에전달되는같은문자열이다. 패키지경로를포함한클래스전체명이거나타입별칭. 자바빈을사용한다면 MyBatis 는타입을찾아낼수있다. 반면에 HashMap 으로매핑한다면, 기대하는처리를명확히하기위해 javatype 을명시해야한다. 지원되는타입목록에서설명하는 JDBC 타입. JDBC 타입은 insert, update 또는 delete 하는 null 입력이가능한칼럼에서만필요하다. JDBC 의요구사항이지 MyBatis 의요구사항이아니다. JDBC 로직접코딩을하다보면, null 이가능한값에이타입을지정할필요가있을것이다. 이문서앞에서이미타입핸들러에대해설명했다. 이프로퍼티를사용하면, 디폴트타입핸들러를오버라이드할수있다. 이값은 TypeHandler 구현체의패키지를포함한전체클래스명이나타입별칭이다. 지원되는 JDBC 타입 좀더상세한설명전에, MyBatis 는 jdbctype 열거를통해다음의 JDBC 타입들을지원한다. BIT FLOAT CHAR TIMESTAMP OTHER UNDEFINED TINYINT REAL VARCHAR BINARY BLOB NVARCHAR SMALLINT DOUBLE LONGVARCHAR VARBINARY CLOB NCHAR INTEGER NUMERIC DATE LONGVARBINARY BOOLEAN NCLOB BIGINT DECIMAL TIME NULL CURSOR constructor <constructor> <idarg column="id" javatype="int"/> <arg column= username javatype= String /> </constructor> 프로퍼티가데이터전송객체 (DTO) 타입클래스로작동한다. 변하지않는클래스를사용하고자하는경우가있다. 거의변하지않는데이터를가진테이블은종종이변하지않는클래스에적합하다. 생성자주입은 public 메서드가없어도인스턴스화할때값을셋팅하도록해준다. MyBatis 는 private 프로퍼티와 private 자바빈프로퍼티를지원하지만많은사람들은생성자주입을선호한다. constructor 요소는이러한처리를가능하게한다. 다음의생성자를보자. public class User { //
32 public User(int id, String username) { // // 결과를생성자에주입하기위해, MyBatis 는파라미터타입에일치하는생성자를찾을필요가있다. 자바는파라미터 이름에서타입을체크할방법이없다. 그래서 constructor 요소를생성할때, 인자의순서에주의하고데이터타입을 명시해야한다. <constructor> <idarg column="id" javatype="int"/> <arg column= username javatype= String /> </constructor> 나머지속성과규칙은 id 와 result 요소와동일하다. 속성설명 column 데이터베이스의칼럼명이나별칭된칼럼라벨. resultset.getstring(columnname) 에전달되는같은문자열이다. javatype 패키지경로를포함한클래스전체명이거나타입별칭. 자바빈을사용한다면 MyBatis 는타입을찾아낼수있다. 반면에 HashMap 으로매핑한다면, 기대하는처리를명확히하기위해 javatype 을명시해야한다. jdbctype 지원되는타입목록에서설명하는 JDBC 타입. JDBC 타입은 insert, update 또는 delete 하는 null 입력이가능한칼럼에서만필요하다. JDBC 의요구사항이지 MyBatis 의요구사항이아니다. JDBC 로직접코딩을하다보면, null 이가능한값에이타입을지정할필요가있을것이다. typehandler 이문서앞에서이미타입핸들러에대해설명했다. 이프로퍼티를사용하면, 디폴트타입핸들러를오버라이드할수있다. 이값은 TypeHandler 구현체의패키지를포함한전체클래스명이나타입별칭이다. select 다른매핑된구문의 ID 는이프로퍼티매핑이필요로하는복잡한타입을로드할것이다. column 속성의칼럼으로부터가져온값은대상 select 구문에파라미터로전달될것이다. 좀더세부적인설명은 association 요소를보라. resultmap 이인자의내포된결과를적절한객체로매핑할수있는 ResultMap 의 ID 이다. 다른 select 구문을호출하기위한대체방법이다. 여러개의테이블을조인하는것을하나의 ResultSet 으로매핑하도록해준다. ResultSet 은사본을포함할수있고, 데이터를반복할수도있다. 가능하게하기위해서, 내포된결과를다루도록결과맵을 연결 하자. 좀더자세히알기위해서는 association 요소를보라. association <association property="author" column="blog_author_id" javatype=" Author"> <id property="id" column="author_id"/> <result property="username" column="author_username"/> </association> association 요소는 has-one 타입의관계를다룬다. 예를들어, Blog 는하나의 Author 를가진다. association 매핑은 다른결과와작동한다. 값을가져오기위해대상프로퍼티를명시한다
33 MyBatis 는관계를정의하는두가지방법을제공한다. 내포된 (Nested) Select: 복잡한타입을리턴하는다른매핑된 SQL 구문을실행하는방법. 내포된 (Nested) Results: 조인된결과물을반복적으로사용하여내포된결과매핑을사용하는방법. 먼저요소내프로퍼티들을보자. 보이는것처럼, select 와 resultmap 속성만을사용하는간단한결과매핑과는다르다. 속성 property column javatype jdbctype typehandler 설명결과칼럼에매핑하기위한필드나프로퍼티. 자바빈프로퍼티가해당이름과일치한다면, 그프로퍼티가사용될것이다. 반면에 MyBatis 는해당이름이필드를찾을것이다. 점표기를사용하여복잡한프로퍼티검색을사용할수있다. 예를들어, username 과같이간단하게매핑될수있거나 address.street.number 처럼좀더복잡하게매핑될수도있다. 데이터베이스의칼럼명이나별칭된칼럼라벨. resultset.getstring(columnname) 에전달되는같은문자열이다. Note: 복합키를다루기위해서, column= {prop1=col1,prop2=col2 문법을사용해서여러개의칼럼명을내포된 select 구문에명시할수있다. 이것은대상의내포된 select 구문의파라미터객체에 prop1, prop2 형태로셋팅하게될것이다. 패키지경로를포함한클래스전체명이거나타입별칭. 자바빈을사용한다면 MyBatis 는타입을찾아낼수있다. 반면에 HashMap 으로매핑한다면, 기대하는처리를명확히하기위해 javatype 을명시해야한다. 지원되는타입목록에서설명하는 JDBC 타입. JDBC 타입은 insert, update 또는 delete 하는 null 입력이가능한칼럼에서만필요하다. JDBC 의요구사항이지 MyBatis 의요구사항이아니다. JDBC 로직접코딩을하다보면, null 이가능한값에이타입을지정할필요가있을것이다. 이문서앞에서이미타입핸들러에대해설명했다. 이프로퍼티를사용하면, 디폴트타입핸들러를오버라이드할수있다. 이값은 TypeHandler 구현체의패키지를포함한전체클래스명이나타입별칭이다. 관계를위한내포된 select select 다른매핑된구문의 ID 는이프로퍼티매핑이필요로하는복잡한타입을로드할것이다. column 속성의칼럼으로부터가져온값은대상 select 구문에파라미터로전달될것이다. Note: 복합키를다루기위해서, column= {prop1=col1,prop2=col2 문법을사용해서여러개의칼럼명을내포된 select 구문에명시할수있다. 이것은대상의내포된 select 구문의파라미터객체에 prop1, prop2 형태로셋팅하게될것이다. 예를들면. <resultmap id= blogresult type= Blog > <association property="author" column="blog_author_id" javatype="author" select= selectauthor /> </resultmap> <select id= selectblog parametertype= int resultmap= blogresult > SELECT * FROM BLOG WHERE ID = #{id </select> <select id= selectauthor parametertype= int resulttype="author"> SELECT * FROM AUTHOR WHERE ID = #{id
34 </select> 여기엔두개의 select 구문이있다. 하나는 Blog 를로드하고다른하나는 Author 를로드한다. 그리고 Blog 의 resultmap 은 author 프로퍼티를로드하기위해 selectauthor 구문을사용한다. 다른프로퍼티들은칼럼과프로퍼티명에일치하는것들로자동으로로드될것이다. 이방법은간단한반면에, 큰데이터나목록에는제대로작동하지않을것이다. 이방법은 N+1 Selects 문제 으로알려진 문제점을가진다. N+1 Selects 문제는처리과정의특이성으로인해야기된다. 레코드의목록을가져오기위해하나의 SQL 구문을실행한다. ( +1 에해당 ). 리턴된레코드별로, 각각의상세데이터를로드하기위해 select 구문을실행한다. ( N 에해당 ). 이문제는수백또는수천의 SQL 구문실행이라는결과를야기할수있다. 아마도언제나바라는형태의처리가아닐것이다. 목록을로드하고내포된데이터에접근하기위해즉시반복적으로처리한다면, 늦은로딩으로호출하고게다가성능은많이 나빠질것이다. 그래서다른방법이있다. 관계를위한내포된결과 (Nested Results) resultmap 이인자의내포된결과를적절한객체로매핑할수있는 ResultMap 의 ID 이다. 다른 select 구문을호출하기위한대체방법이다. 여러개의테이블을조인하는것을하나의 ResultSet 으로매핑하도록해준다. ResultSet 은사본을포함할수있고, 데이터를반복할수도있다. 가능하게하기위해서, 내포된결과를다루도록결과맵을 연결 하자. 좀더자세히알기위해서는 association 요소를보라. 위에서내포된관계의매우복잡한예제를보았을것이다. 다음은작동하는것을보기위한좀더간단한예제이다. 개별 구문을실행하는것대신에, Blog 와 Author 테이블을함께조인했다. <select id="selectblog" parametertype="int" resultmap="blogresult"> select B.id as blog_id, B.title as blog_title, B.author_id as blog_author_id, A.id as author_id, A.username as author_username, A.password as author_password, A. as author_ , A.bio as author_bio from Blog B left outer join Author A on B.author_id = A.id where B.id = #{id </select> 조인을사용할때, 결과의값들이유일하거나좀더명확한이름이되도록별칭을사용하는것이좋다. 이제결과를매핑할수 있다. <resultmap id="blogresult" type="blog">
35 <id property= blog_id column="id" /> <result property="title" column="blog_title"/> <association property="author" column="blog_author_id" javatype="author" resultmap= authorresult /> </resultmap> <resultmap id="authorresult" type="author"> <id property="id" column="author_id"/> <result property="username" column="author_username"/> <result property="password" column="author_password"/> <result property=" " column="author_ "/> <result property="bio" column="author_bio"/> </resultmap> 위예제에서, Author 인스턴스를로드하기위한 authorresult resultmap 으로위임된 Blog 의 author 관계를볼수 있을것이다. 매우중요 : id 요소는내포된결과매핑에서매우중요한역할을담당한다. 결과중유일한것을찾아내기위한한개이상의 프로퍼티를명시해야만한다. 가능하면결과중유일한것을찾아낼수있는프로퍼티들을선택하라. 기본키가가장좋은 선택이될수있다. 이제, 위예제는관계를매핑하기위해외부의 resultmap 요소를사용했다. 이외부 resultmap 은 Author resultmap 을 재사용가능하도록해준다. 어쨌든, 재사용할필요가있거나, 한개의 resultmap 에결과매핑을함께위치시키고자한다면, association 결과매핑을내포시킬수있다. 다음은이방법을사용한예제이다. <resultmap id="blogresult" type="blog"> <id property= blog_id column="id" /> <result property="title" column="blog_title"/> <association property="author" column="blog_author_id" javatype="author"> <id property="id" column="author_id"/> <result property="username" column="author_username"/> <result property="password" column="author_password"/> <result property=" " column="author_ "/> <result property="bio" column="author_bio"/> </association> </resultmap> 지금까지 has one 관계를다루는방법을보았다. 하지만 has many 는어떻게처리할까? 그건다음섹션에서다루어보자. collection <collection property="posts" oftype="domain.blog.post"> <id property="id" column="post_id"/> <result property="subject" column="post_subject"/> <result property="body" column="post_body"/> </collection>
36 collection 요소는관계를파악하기위해작동한다. 사실이내용이중복되는내용으로, 차이점에대해서만주로살펴보자. 위예제를계속진행하기위해, Blog 는오직하나의 Author 를가진다. 하지만 Blog 는많은 Post 를가진다. Blog 클래스에 다음처럼처리될것이다. private List<Post> posts; List 에내포된결과를매핑하기위해, collection 요소를사용한다. association 요소와는달리, 조인에서내포된 select 나 내포된결과를사용할수있다. Collection 을위한내포된 (Nested) Select 먼저, Blog 의 Post 를로드하기위한내포된 select 를사용해보자. <resultmap id= blogresult type= Blog > <collection property="posts" javatype= ArrayList column="blog_id" oftype="post" select= selectpostsforblog /> </resultmap> <select id= selectblog parametertype= int resultmap= blogresult > SELECT * FROM BLOG WHERE ID = #{id </select> <select id= selectpostsforblog parametertype= int resulttype="blog"> SELECT * FROM POST WHERE BLOG_ID = #{id </select> 바로눈치챌수있는몇가지가있지만, 대부분앞서배운 association 요소와매우유사하다. 먼저, collection 요소를사용한 것이보일것이다. 그리고나서새로운 oftype 속성을사용한것을알아차렸을것이다. 이속성은자바빈프로퍼티타입과 collection 의타입을구분하기위해필요하다. <collection property="posts" javatype= ArrayList column="blog_id" oftype="post" select= selectpostsforblog /> 독자왈 : Post 의 ArrayList 타입의글목록 javatype 속성은그다지필요하지않다. MyBatis 는대부분의경우이속성을사용하지않을것이다. 그래서좀더간단하게 설정할수있다. <collection property="posts" column="blog_id" oftype="post" select= selectpostsforblog /> Collection 을위한내포된 (Nested) Results
37 이시점에, collection 을위한내포된결과가어떻게작동하는지짐작할수있을것이다. 왜냐하면 association 와정확히 일치하기때문이다. 하지만 oftype 속성이추가로적용되었다. 먼저, SQL 을보자. <select id="selectblog" parametertype="int" resultmap="blogresult"> select B.id as blog_id, B.title as blog_title, B.author_id as blog_author_id, P.id as post_id, P.subject as post_subject, P.body as post_body, from Blog B left outer join Post P on B.id = P.blog_id where B.id = #{id </select> 다시보면, Blog 와 Post 테이블을조인했고간단한매핑을위해칼럼명에적절한별칭을주었다. 이제 Post 의 Collection 을가진 Blog 의매핑은다음처럼간단해졌다. <resultmap id="blogresult" type="blog"> <id property= id column="blog_id" /> <result property="title" column="blog_title"/> <collection property="posts" oftype="post"> <id property="id" column="post_id"/> <result property="subject" column="post_subject"/> <result property="body" column="post_body"/> </collection> </resultmap> 다시, 여기서 id 요소의중요성을기억해두거나기억이나지않으면 association 섹션에서다시읽어둬라. 혹시, 결과매핑의재사용성을위해좀더긴형태를선호한다면, 다음과같은형태로도가능하다. <resultmap id="blogresult" type="blog"> <id property= id column="blog_id" /> <result property="title" column="blog_title"/> <collection property="posts" oftype="post" resultmap= blogpostresult /> </resultmap> <resultmap id="blogpostresult" type="post"> <id property="id" column="post_id"/> <result property="subject" column="post_subject"/> <result property="body" column="post_body"/> </resultmap>
38 Note: associations 과 collections 에서내포의단계혹은조합에는제한이없다. 매핑할때는성능을생각해야한다. 단위 테스트와성능테스트는애플리케이션에서가장좋은방법을찾도록지속해야한다. MyBatis 는이에수정비용을최대한 줄이도록해줄것이다. discriminator <discriminator javatype="int" column="draft"> <case value="1" resulttype="draftpost"/> </discriminator> 종종하나의데이터베이스쿼리는많고다양한데이터타입의결과를리턴한다. discriminator 요소는클래스상속관계를 포함하여이러한상황을위해고안되었다. discriminator 는자바의 switch 와같이작동하기때문에이해하기쉽다. discriminator 정의는 colume 과 javatype 속성을명시한다. colume 은 MyBatis 로하여금비교할값을찾을것이다. javatype 은동일성테스트와같은것을실행하기위해필요하다. 예를들어 <resultmap id="vehicleresult" type="vehicle"> <id property= id column="id" /> <result property="vin" column="vin"/> <result property="year" column="year"/> <result property="make" column="make"/> <result property="model" column="model"/> <result property="color" column="color"/> <discriminator javatype="int" column="vehicle_type"> <case value="1" resultmap="carresult"/> <case value="2" resultmap="truckresult"/> <case value="3" resultmap="vanresult"/> <case value="4" resultmap="suvresult"/> </discriminator> </resultmap> 이예제에서, MyBatis 는결과데이터에서각각의레코드를가져와서 vehicle_type 값과비교한다. 만약 discriminator 비교값과같은경우가생기면, 이경우에명시된 resultmap 을사용할것이다. 해당되는경우가없다면무시된다. 만약일치하는경우가하나도없다면, MyBatis 는 discriminator 블럭밖에정의된 resultmap 을사용한다. carresult 가다음처럼정의된다면, <resultmap id="carresult" type="car"> </resultmap> <result property= doorcount column="door_count" /> doorcount 프로퍼티만이로드될것이다. discriminator 경우들의독립적인결과를만들어준다. 이경우우리는물론 car 와 vehicle 간의관계를알수있다. 그러므로, 나머지프로퍼티들도로드하길원하게된다. 그러기위해서는간단하게하나만 변경하면된다. <resultmap id="carresult" type="car" extends= vehicleresult > </resultmap> <result property= doorcount column="door_count" />
39 vehicleresult 와 carresult 의모든프로퍼티들이로드될것이다. 한가지더, 도처에설정된외부정의를찾게될지도모른다. 그러므로좀더간결한매핑스타일의문법이있다. 예를들면 <resultmap id="vehicleresult" type="vehicle"> <id property= id column="id" /> <result property="vin" column="vin"/> <result property="year" column="year"/> <result property="make" column="make"/> <result property="model" column="model"/> <result property="color" column="color"/> <discriminator javatype="int" column="vehicle_type"> <case value="1" resulttype="carresult"> <result property= doorcount column="door_count" /> </case> <case value="2" resulttype="truckresult"> <result property= boxsize column="box_size" /> <result property= extendedcab column="extended_cab" /> </case> <case value="3" resulttype="vanresult"> <result property= powerslidingdoor column="power_sliding_door" /> </case> <case value="4" resulttype="suvresult"> <result property= allwheeldrive column="all_wheel_drive" /> </case> </discriminator> </resultmap> 모든결과매핑이있고, 모두명시하고싶지않다면, MyBatis 는칼럼과프로퍼티명으로자동으로매핑할것이다. 이예제는실제로필요한내용보다좀더많이서술되어있다. cache MyBatis 는쉽게설정가능하고변경가능한쿼리캐싱기능을가지고있다. MyBatis 3 캐시구현체는좀더강력하고쉽게설정할수있도록많은부분이수정되었다. 성능을개선하고순환하는의존성을해결하기위해필요한로컬세션캐싱을제외하고기본적으로캐시가작동하지않는다. 캐싱을활성화하기위해서, SQL 매핑파일에한줄을추가하면된다. <cache/> 하나의간단한구문에다음과같은순서로영향을준다. 매핑구문파일내 select 구문의모든결과가캐시될것이다. 매핑구문파일내 insert, update 그리고 delete 구문은캐시를지울 (flush) 것이다
40 캐시는 Least Recently Used (LRU) 알고리즘을사용할것이다. 캐시는스케줄링기반으로시간순서대로지워지지는않는다. ( 예를들면. no Flush Interval) 캐시는리스트나객체에대해 1024 개의참조를저장할것이다. ( 쿼리메서드가실행될때마다 ) 캐시는읽기 / 쓰기캐시처럼처리될것이다. 이것은가져올객체는공유되지않고호출자에의해안전하게 변경된다는것을의미한다. 모든프로퍼티는 cache 요소의속성을통해변경가능하다. 예를들면 : <cache eviction="fifo" flushinterval="60000" size="512" readonly="true"/> 좀더많은프로퍼티가셋팅된이설정은 60 초마다캐시를지우는 FIFO 캐시를생성한다. 이캐시는결과객체또는결과 리스트를 512 개까지저장하고각객체는읽기전용이다. 캐시데이터를변경하는것은개별쓰레드에서호출자간의충돌을 야기할수있다. 사용가능한캐시전략은 4 가지이다. LRU Least Recently Used: 가장오랜시간사용하지않는객체를제거 FIFO First In First Out: 캐시에들어온순서대로객체를제거 SOFT Soft Reference: 가비지컬렉터의상태와강하지않은참조 (Soft References ) 의규칙에기초하여객체를 제거 WEAK Weak Reference: 가비지컬렉터의상태와약한참조 (Weak References) 의규칙에기초하여 점진적으로객체제거 디폴트값은 LRU 이다. flushinterval 은양수로셋팅할수있고, 밀리세컨드로명시되어야한다. 디폴트는셋팅되지않으나, 플러시 (flush) 주기를 사용하지않으면, 캐시는오직구문이호출될때마다캐시를지운다. size 는양수로셋팅할수있고캐시에객체의크기를유지하지만메모리자원이충분해야한다. 디폴트값은 1024 이다. readonly 속성은 true 또는 false 로설정할수있다. 읽기전용캐시는모든호출자에게캐시된객체의같은인스턴스를 리턴할것이다. 게다가그객체는변경할수없다. 이건종종성능에잇점을준다. 읽고쓰는캐시는캐시된객체의복사본을 리턴할것이다. 이건조금더늦긴하지만안전하다. 디폴트는 false 이다.. 사용자지정캐시사용하기 앞서본다양한설정방법에더해, 자체적으로개발하거나써드파티캐시솔루션을사용하여캐시처리를할수있다
41 <cache type= com.domain.something.mycustomcache /> 이예제는사용자지정캐시구현체를사용하는방법을보여준다. type 속성에명시된클래스는 org.mybatis.cache.cache 인터페이스를반드시구현해야한다. 이인터페이스는 MyBatis 프레임워크의가장복잡한구성요소중하나이다. 하지만 하는일은간단하다. public interface Cache { String getid(); int getsize(); void putobject(object key, Object value); Object getobject(object key); boolean haskey(object key); Object removeobject(object key); void clear(); ReadWriteLock getreadwritelock(); 캐시를설정하기위해, 캐시구현체에 public 자바빈프로퍼티를추가하고 cache 요소를통해프로퍼티를전달한다. 예를 들어, 다음예제는캐시구현체에서 setcachefile(string file) 를호출하여메서드를호출할것이다. <cache type= com.domain.something.mycustomcache > <property name= cachefile value= /tmp/my-custom-cache.tmp /> </cache> 모든간단한타입의자바빈프로퍼티를사용할수있다. MyBatis 는변환할것이다. 캐시설정과캐시인스턴스가 SQL Map 파일의명명공간에묶여지는 (bound) 것을기억하는게중요하다. 게다가, 같은 명명공간내모든구문은묶여진다. 구문별로캐시와상호작동하는방법을변경할수있거나두개의간단한속성을통해 완전히배제될수도있다. 디폴트로구문은아래와같이설정된다. <select... flushcache= false usecache= true /> <insert... flushcache= true /> <update... flushcache= true /> <delete... flushcache= true /> 이러한방법으로구문을설정하는하는방법은굉장히좋지않다. 대신디폴트행위를변경해야할경우에만 flushcache 와 usecache 속성을변경하는것이좋다. 예를들어, 캐시에서특정 select 구문의결과를제외하고싶거나캐시를지우기위한 select 구문을원할것이다. 유사하게실행할때마다캐시를지울필요가없는 update 구문도있을것이다
42 cache-ref 이전섹션내용을돌이켜보면서, 특정명명공간을위한캐시는오직하나만사용되거나같은명명공간내에서는구문마다캐시를지울수있다. 명명공간간의캐시설정과인스턴스를공유하고자할때가있을것이다. 이경우 cache-ref 요소를사용해서다른캐시를참조할수있다. <cache-ref namespace= com.someone.application.data.somemapper /> 동적 SQL MyBatis 의가장강력한기능중하나는동적 SQL 기능이다. JDBC 나다른유사한프레임워크를사용해본경험이있다면, 동적으로 SQL 을구성하는것이얼마나힘든작업인지이해할것이다. 간혹공백이나콤마를붙이는것을잊어본적도있을것이다. 동적 SQL 은그만큼어려운것이다. 동적 SQL 을사용하는것은결코파티가될수없을것이다. MyBatis 는강력한동적 SQL 언어로이상황은개선한다. 동적 SQL 요소들은 JSTL 이나 XML 기반의텍스트프로세서를사용해본사람에게는친숙할것이다. MyBatis 의이전 버전에서는, 알고이해해야할요소가많았다. MyBatis 3 에서는이를크게개선했고실제사용해야할요소가반이하로 줄었다. MyBatis 다른요소의사용을최대한제거하기위해 OGNL 기반의표현식을가져왔다. if choose (when, otherwise) trim (where, set) foreach if 동적 SQL 에서가장공통적으로사용되는것으로 where 의일부로포함될수있다. 예를들면 : <select id= findactiveblogwithtitlelike parametertype= Blog resulttype= Blog > SELECT * FROM BLOG WHERE state = ACTIVE <if test= title!= null > AND title like #{title </if> </select> 이구문은선택적으로문자열검색기능을제공할것이다. 만약에 title 값이없다면, 모든 active 상태의 Blog 가리턴될것이다. 하지만 title 값이있다면, 그값과비슷한데이터를찾게될것이다. title 과 author 을사용하여검색하고싶다면? 먼저, 의미가좀더잘전달되도록구문의이름을변경할것이다. 그리고다른조건을추가한다. <select id= findactivebloglike parametertype= Blog resulttype= Blog >
43 SELECT * FROM BLOG WHERE state = ACTIVE <if test= title!= null > AND title like #{title </if> <if test= author!= null and author.name!= null > AND author_name like #{author.name </if> </select> choose, when, otherwise 우리는종종적용할모든조건을원하는대신에한가지경우만을원할수있다. 자바에서는 switch 구문과유사하며, MyBatis 에서는 choose 요소를제공한다. 위예제를다시사용해보자. 지금은 title 만으로검색하고 author 가있다면그값으로검색된다. 둘다제공하지않는다면, featured 상태의 blog 가리턴된다. <select id= findactivebloglike parametertype= Blog resulttype= Blog > SELECT * FROM BLOG WHERE state = ACTIVE <choose> <when test= title!= null > AND title like #{title </when> <when test= author!= null and author.name!= null > AND author_name like #{author.name </when> <otherwise> AND featured = 1 </otherwise> </choose> </select> trim, where, set 앞서예제는악명높게다양한요소가사용된동적 SQL 이다. if 예제를사용해보자. <select id= findactivebloglike parametertype= Blog resulttype= Blog > SELECT * FROM BLOG WHERE <if test= state!= null > state = #{state </if> <if test= title!= null > AND title like #{title </if> <if test= author!= null and author.name!= null > AND author_name like #{author.name
44 </if> </select> 어떤조건에도해당되지않는다면어떤일이벌어질까? 아마도다음과같은 SQL 이만들어질것이다. SELECT * FROM BLOG WHERE 아마도이건실패할것이다. 두번째조건에만해당된다면무슨일이벌어질까? 아마도다음과같은 SQL 이만들어질것이다. SELECT * FROM BLOG WHERE AND title like sometitle 이것도아마실패할것이다. 이문제는조건만가지고는해결되지않았다. 이렇게작성했다면, 다시는이렇게작성하지않게될것이다. 실패하지않기위해서조금수정해야한다. 조금수정하면아마도다음과같을것이다 : <select id= findactivebloglike parametertype= Blog resulttype= Blog > SELECT * FROM BLOG <where> <if test= state!= null > state = #{state </if> <if test= title!= null > AND title like #{title </if> <if test= author!= null and author.name!= null > AND author_name like #{author.name </if> </where> </select> where 요소는태그에의해컨텐츠가리턴되면단순히 WHERE 만을추가한다. 게다가, 컨텐츠가 AND 나 OR 로 시작한다면, 그 AND 나 OR 를지워버린다. 만약에 where 요소가기대한것처럼작동하지않는다면, trim 요소를사용자정의할수도있다. 예를들어, 다음은 where 요소에대한 trim 기능과동일하다.: <trim prefix="where" prefixoverrides="and OR "> </trim> override 속성은오버라이드하는텍스트의목록을제한한다. 결과는 override 속성에명시된것들을지우고 with 속성에 명시된것을추가한다. 다음예제는동적인 update 구문의유사한경우이다. set 요소는 update 하고자하는칼럼을동적으로포함시키기위해 사용될수있다. 예를들어 :
45 <update id="updateauthorifnecessary" parametertype="domain.blog.author"> update Author <set> <if test="username!= null">username=#{username,</if> <if test="password!= null">password=#{password,</if> <if test=" != null"> =#{ ,</if> <if test="bio!= null">bio=#{bio</if> </set> where id=#{id </update> 여기서 set 요소는동적으로 SET 키워드를붙히고, 필요없는콤마를제거한다. 아마도 trim 요소로처리한다면아래와같을것이다. <trim prefix="set" suffixoverrides=","> </trim> 이경우, 접두사는추가하고, 접미사를오버라이딩한다. foreach 동적 SQL 에서공통적으로필요한것은 collection 에대해반복처리를하는것이다. 종종 IN 조건을사용하게된다. 예를 들면, <select id="selectpostin" resulttype="domain.blog.post"> SELECT * FROM POST P WHERE ID in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item </foreach> </select> foreach 요소는매우강력하고 collection 을명시하는것을허용한다. 요소내부에서사용할수있는 item, index 두가지 변수를선언한다. 이요소는또한열고닫는문자열로명시할수있고반복간에둘수있는구분자도추가할수있다. Note: 파라미터객체로 MyBatis 에 List 인스턴스나배열을전달할수있다. 그렇게하면 MyBatis 는 Map 으로 자동으로감싸고이름을키로사용한다. List 인스턴스는 list 를키로사용하고, 배열인스턴스는 array 를키로 사용한다. XML 설정파일과 XML 매핑파일에대해서는이정도에서정리하고, 다음섹션에서는 Java API 에대해좀더상세하게 살펴볼것이다
46 자바 API 이제 MyBatis 를설정하는방법과매핑을만드는방법을알게되었다. 이미충분히잘사용할준비가된셈이다. MyBatis 자바 API 는당신의노력에대한보상을얻게할것이다. JDBC 와비교해보면, MyBatis 는코드를굉장히단순하게만들고깔끔하게만든다. 이해하기쉬워서유지보수도편하게해준다. MyBatis 3 은 SQL Map 을사용하는많은수의개선내용을소개했다. 디렉터리구조 자바 API 를살펴보기전에, 디렉터리구조에대해전반적으로이해하는것이중요하다. MyBatis 는매우유연하고파일을사용해서어떤것도할수있다. 하지만프레임워크이기때문에선호하는방법이있다. 전형적인애플리케이션디렉터리구조를살펴보자. /my_application /bin /devlib /lib /src /test /web /org/myapp/ /action /data /model /service /view /properties /org/myapp/ /action /data /model /service /view /properties /WEB-INF /SqlMapConfig.xml /BlogMapper.java /BlogMapper.xml MyBatis *.jar 파일이여기있다. MyBatis 산출물이여기있다. Mapper 클래스, XML 설정, XML 매핑파일들 XML 설정파일에포함된프로퍼티들이여기있다. 기억해달라. 이건선호하는것이지필수요건이아니다. 하지만다른이들은공통적인디렉터리를구조를사용하면좋아할것이다
47 /web.xml 이섹션의나머지예제는디렉터리구조가이렇게되어있다고가정하고설명한다. SqlSessions MyBatis 를사용하기위한기본적인자바인터페이스는 SqlSession 이다. 이인터페이스를통해명령어를실행하고, 매퍼를얻으며트랜잭션을관리할수있다. 우리는 SqlSession 에대해서좀더얘기해볼것이지만먼저 SqlSession 의인스턴스를만드는방법을배워보자. SqlSession 은 SqlSessionFactory 인스턴스를사용해서만든다. SqlSessionFactory 는몇가지방법으로 SqlSession 인스턴스를생성하기위한메서드를포함하고있다. SqlSessionFactory 자체는 XML, 애노테이션또는자바설정에서 SqlSessonFactory 를생성할수있는 SqlSessionFactoryBuilder 를통해만들어진다. SqlSessionFactoryBuilder SqlSessionFactoryBuilder 는 5 개의 build() 메서드를가진다. 각각은서로다른소스에서 SqlSession 을빌드한다. SqlSessionFactory build(reader reader) SqlSessionFactory build(reader reader, String environment) SqlSessionFactory build(reader reader, Properties properties) SqlSessionFactory build(reader reader, String env, Properties props) SqlSessionFactory build(configuration config) 처음 4 개의메서드가가장공통적이다. XML 문서를나타내는 Reader 인스턴스를가진다. SqlMapConfig.xml 파일은 위에서다루었다. 선택적으로사용가능한프로퍼티는 environment 와 properties 이다. environment 는데이터소스와 트랜잭션관리자를포함하여로드할환경을판단한다. 예를들면 : <environments default="development"> <environment id="development"> <transactionmanager type="jdbc"> <datasource type="pooled"> </environment> <environment id="production"> <transactionmanager type="external"> <datasource type="jndi"> </environment> </environments> environment 파라미터를가진메서드를호출한다면, MyBatis 는사용할환경을위한설정을사용할것이다. 물론잘못된 환경설정을사용하면, 에러를보게될것이다. environment 파라미터를가지지않는메서드중하나를호출한다면, 디폴트 환경 ( 위예제에서 default= development ) 이사용될것이다
48 properties 인스턴스를가진메서드를호출하면, MyBatis 는프로퍼티들을로드해서설정에서사용가능한부분을사용할 것이다. 프로퍼티들은 ${propname 와같은문법을사용해서설정의값으로대체될수있다. 프로퍼티들은 SqlMapConfig.xml 파일에서사용되거나직접명시할수있다. 그러므로프로퍼티들의우선순위를이해하는 것이중요하다. 우리는앞서언급하긴했지만, 쉽게이해할수있도록다시보여주도록하겠다. 프로퍼티가한개이상존재한다면, MyBatis 는일정한순서로로드한다.: properties 요소에명시된속성을가장먼저읽는다. properties 요소의클래스패스자원이나 url 속성으로부터로드된속성을두번재로읽는다. 그래서이미 읽은값이있다면덮어쓴다., 마지막으로메서드파라미터로전달된속성을읽는다. 앞서로드된값을덮어쓴다 그래서가장우선순위가높은속성은메서드의파라미터로전달된값이고그다음은자원및 url 속성이고마지막은 properties 요소에명시된값이다. 요약해보면, 처음 4 개의메서드는사실같지만, environment 그리고 / 또는 properties 에명시한값을오버라이드한다. SqlMapConfig.xml 파일에서 SqlSessionFactory 를빌드하는예제이다. String resource = "org/mybatis/builder/mapperconfig.xml"; Reader reader = Resources.getResourceAsReader(resource); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(reader); Resources 유틸리티클래스를사용하고있는것을주의깊게보면된다. 이클래스는 org.mybatis.io 패키지에있다. Resources 클래스는그이름이나타내는것처럼, 클래스패스나파일시스템또는웹 URL 에서자원으로로드하도록해준다. IDE 를통해클래스의소스코드를보는것으로유용한메서드를보게될것이다. 그유용한메서드목록들이다. URL getresourceurl(string resource) URL getresourceurl(classloader loader, String resource) InputStream getresourceasstream(string resource) InputStream getresourceasstream(classloader loader, String resource) Properties getresourceasproperties(string resource) Properties getresourceasproperties(classloader loader, String resource) Reader getresourceasreader(string resource) Reader getresourceasreader(classloader loader, String resource) File getresourceasfile(string resource) File getresourceasfile(classloader loader, String resource) InputStream geturlasstream(string urlstring) Reader geturlasreader(string urlstring) Properties geturlasproperties(string urlstring) Class classforname(string classname)
49 마지막 build 메서드는 Configuration 의인스턴스를가진다. Configuration 클래스는 SqlSessionFactory 인스턴스에대해알필요가있는모든것으로가지고있다. Configuration 클래스는 SQL Map 을찾거나관리하는것을포함하여설정을살펴보기위해유용하다. Configuration 클래스는앞서봤던모든설정을처리할수있으며, 자바 API 로나타낼수있다. SqlSessionFactory 를생성하기위해 Configuration 인스턴스를 build() 메서드에전달하는예제이다. DataSource datasource = BaseDataTest.createBlogDataSource(); TransactionFactory transactionfactory = new JdbcTransactionFactory(); Environment environment = new Environment("development", transactionfactory, datasource); Configuration configuration = new Configuration(environment); configuration.setlazyloadingenabled(true); configuration.setenhancementenabled(true); configuration.gettypealiasregistry().registeralias(blog.class); configuration.gettypealiasregistry().registeralias(post.class); configuration.gettypealiasregistry().registeralias(author.class); configuration.addmapper(boundblogmapper.class); configuration.addmapper(boundauthormapper.class); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(configuration); 이제 SqlSessionFactory 를만들었다. SqlSession 인스턴스를만들기위해사용해보자. SqlSessionFactory SqlSessionFactory 는 SqlSession 인스턴스를생성하기위해사용할수있는 6 개의메서드를가지고있다. 6 개의메서드가 선택해서사용하는것들을보자. Transaction: 세션에서트랜잭션스코프또는자동커밋을사용하고싶은가? Connection: 설정된 DataSource 에서 Connection 을회득하고싶은가? Execution: PreparedStatements 그리고 / 또는배치 (insert, delete 를포함해서 ) 업데이트를재사용하고싶은가? 오버로드된메서드인 pensession() 이 3 가지를적절히혼합해서사용할수있다. SqlSession opensession() SqlSession opensession(boolean autocommit) SqlSession opensession(connection connection) SqlSession opensession(transactionisolationlevel level) SqlSession opensession(executortype exectype,transactionisolationlevel level) SqlSession opensession(executortype exectype) SqlSession opensession(executortype exectype, boolean autocommit) SqlSession opensession(executortype exectype, Connection connection) Configuration getconfiguration();
50 파라미터를가지지않는디폴트 opensession() 메서드는다음과같은성격을가진 SqlSession 을만들것이다. 트랜잭션스코프는시작될것이다. Connection 객체는활성화된환경에의해설정된 DataSource 인스턴스를획득할것이다. 트랜잭션격리레벨은드라이버나데이터소스가디폴트로제공하는옵션을사용할것이다. PreparedStatements 는재사용되지않을것이다. 그리고 update 또한배치처리되지않을것이다. 메서드대부분은그이름과파라미터가그역할을충분히설명한다. 자동커밋을활성화하기위해서, autocommit 파라미터에 true 값을셋팅하라. 자체적인커넥션을제공하기위해서는, connection 파라미터에 Connection 인스턴스를 셋팅하라. Connection 과 autocommit 둘다셋팅하는것을오버라이드하지않는다. 왜냐하면 MyBatis 는제공된 connection 객체를셋팅할때마다현재사용중인것을사용한다. MyBatis 는 TransactionIsolationLevel 라고불리는트랜잭션격리레벨을위한자바 enum 래퍼를사용한다. JDBC 를 5 가지를지원한다 (NONE, READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE). 새롭게보일수있는하나의파라미터는 ExecutorType 이다. enum 으로는 3 개의값을정의한다. ExecutorType.SIMPLE 이타입의실행자는아무것도하지않는다. 구문실행마다새로운 PreparedStatement 를생성한다. ExecutorType.REUSE 이타입의실행자는 PreparedStatements 를재사용할것이다. ExecutorType.BATCH 이실행자는모든 update 구문을배치처리하고중간에 select 가실행될경우필요하다면경계를표시한다. 이러한 과정은행위를좀더이해하기쉽게하기위함이다. Note: SqlSessionFactory 에서언급하지않는한개이상의메서드가있다. getconfiguration() 메서드인데, 이메서드는 런타임시 MyBatis 설정을조사하는 Configuration 인스턴스를리턴할것이다. SqlSession 앞서언급한것처럼, SqlSession 인스턴스는 MyBatis 에서굉장히강력한클래스이다. 구문을실행하고, 트랜잭션을 커밋하거나롤백하는그리고 mapper 인스턴스를습득하기위해필요한모든메서드를찾을수있을것이다. SqlSession 에는 20 개이상의메서드가있다. 좀더적절히모아서보도록하자. 구문을실행하는메서드 이메서드들은 SQL 매핑 XML 파일에정의된 SELECT, INSERT, UPDATE 그리고 DELETE 구문을실행하기위해사용된다. 메서드이름자체가그역할을설명하도록명명되었다. 메서드각각은구문의 ID 와파라미터객체 ( 원시타입, 자바빈, POJO 또는 Map) 을가진다
51 Object selectone(string statement, Object parameter) List selectlist(string statement, Object parameter) Map selectmap(string statement, Object parameter, String mapkey) int insert(string statement, Object parameter) int update(string statement, Object parameter) int delete(string statement, Object parameter) selectone 과 selectlist 의차이점은 selectone 메서드는오직하나의객체만을리턴해야한다는것이다. 한개이상을리턴하거나 null 이리턴된다면, exception 이발생할것이다. 얼마나많은객체가리턴될지모른다면, selectlist 를사용하라. 객체의존재여부를체크하고싶다면, 개수를리턴하는방법이더좋다. selectmap 은결과목록을 Map 을변환하기위해디자인된특별한경우이다. 이경우결과객체의프로퍼티중하나를키로사용하게된다. 모든구문이파라미터를필요로하지는않기때문에, 파라미터객체를요구하지않는형태로오버로드되었다. Object selectone(string statement) List selectlist(string statement) Map selectmap(string statement, String mapkey) int insert(string statement) int update(string statement) int delete(string statement) 마지막으로, 리턴되는데이터의범위를제한하거나결과를핸들링하는로직을부여할수있는 3 개의 select 메서드가있다. List selectlist (String statement, Object parameter, RowBounds rowbounds) Map selectmap(string statement, Object parameter, String mapkey, RowBounds rowbounds) void select (String statement, Object parameter, ResultHandler handler) void select (String statement, Object parameter, RowBounds rowbounds, ResultHandler handler) RowBounds 파라미터는 MyBatis 로하여금특정개수만큼의레코드를건너띄게한다. RowBounds 클래스는 offset 과 limit 둘다가지는생성자가있다. int offset = 100; int limit = 25; RowBounds rowbounds = new RowBounds(offset, limit); 가장좋은성능을위해, 결과셋의타입을 SCROLL_SENSITIVE 나 SCROLL_INSENSITIVE 로사용하라. ResultHandler 파라미터는레코드별로다룰수있도록해준다. List 에추가할수도있고, Map, Set 을만들수도있으며, 각각의결과를그냥던질수도있다. ResultHandler 로많은것을할수있고 MyBatis 는결과셋을다루기위해내부적으로 사용한다
52 인터페이스는매우간단하다. package org.mybatis.executor.result; public interface ResultHandler { void handleresult(resultcontext context); ResultContext 파라미터는결과객체에접근할수있도록해준다. 트랙잭션제어메서드 트랜잭션을제어하기위해 4 개의메서드가있다. 물론자동커밋을선택하였거나외부트랜잭션관리자를사용하면영향이없다. 어쨌든, Connection 인스턴스에의해관리되고 JDBC 트랜잭션관리자를사용하면, 이 4 개의메서드를사용할수있다. void commit() void commit(boolean force) void rollback() void rollback(boolean force) 기본적으로 MyBatis 는 insert, update 또는 delete 를호출하여데이터베이스가변경된것으로감지하지않는한실제로 커밋하지않는다. 이러한메서드호출없이변경되면, 커밋된것으로보장하기위해 commit 와 rollback 메서드에 true 값을 전달한다. 세션레벨의캐시를지우기 void clearcache() SqlSession 인스턴스는 update, commit, rollback 또는 close 할때마다지워지는로컬캐시이다. 명시적으로닫기 위해서는, clearcache() 메서드를호출할수있다. SqlSession 을반드시닫도록한다. void close() 반드시기억해야하는중요한것은당신이열었던세션을닫아주는것이다. 확실히하기위해가장좋은방법은다음과같은 형태로개발하는것이다. SqlSession session = sqlsessionfactory.opensession(); try { // following 3 lines pseudocod for doing some work session.insert( ); session.update( ); session.delete( ); session.commit();
53 finally { session.close(); Note: SqlSessionFactory 처럼, SqlSession 이 getconfiguration() 메서드를호출하여 Configuration 인스턴스를 얻을수있다. Configuration getconfiguration() Mappers 사용하기 <T> T getmapper(class<t> type) 다양한 insert, update, delete 그리고 select 메서드는강력하지만, 다소장황하고타입에안전하지않다. 더군다나 IDE 나 단위테스트에그다지도움이되지않는형태이다. 우리는 Mapper 를사용하는예제는이미시작하기섹션에서봤다. 그러므로, 매핑된구문을실행하기위해좀더공통적인방법은 Mapper 클래스를사용하는것이다. Mapper 클래스는 SqlSession 메서드에일치하는메서드와간단히연동된다. 다음의예제클래스는몇가지메서드시그니처와 SqlSession 에 매핑하는방법을보여준다. public interface AuthorMapper { // (Author) selectone( selectauthor,5); Author selectauthor(int id); // (List<Author>) selectlist( selectauthors ) List<Author> selectauthors(); // (Map<Integer,Author>) selectmap( selectauthors, id id ) List<Author> selectauthorsasmap(); // insert( insertauthor, author) int insertauthor(author author); // updateauthor( updateauthor, author) int updateauthor(author author); // delete( deleteauthor,5) int deleteauthor(int id); 아주간결하게, 각각의 Mapper 메서드시그니처는 SqlSession 의메서드시그니처와일치해야만한다. String 파라미터 ID 가없지만, 대신메서드명은매핑된구문의 ID 와같아야한다. 추가로, 리턴타입은기대하는결과타입과일치해야만한다. 원시타입과 Map, POJO 그리고자바빈등대부분의타입이 지원된다. Mapper 인터페이스는어떠한인터페이스를구현할필요가없고어떠한클래스를확장할필요도없다. 메서드 시그니처는관련된매핑된구문을유일하게확인하기위해사용될수있다
54 Mapper 인터페이스는다른인터페이스를확장할수있다. 적절한명명공간의구문은 Mapper 인터페이스에 XML 바인딩을사용한다. 오직하나의제한점은두개의인터페이스에같은메서드시그니처를사용할수없다는것이다. mapper 메서드에여러개의파라미터를전달할수있다. 여러개의파라미터를전달하면, 파라미터목록의위치에따라 명명될것이다. 예를들면, #{1, #{2 기타등등이런식이다. 만약파라미터의이름을변경하고자한다면, paramname ) 애노테이션을사용할수있다. 쿼리결과를제한하기위해메서드에 RowBounds 인스턴스를전달할수있다. Mapper 애노테이션 이프레임워크가만들어진이후로 MyBatis 는 XML 기반의프레임워크이다. 설정은 XML 기반이고매핑된구문또한 XML 에정의한다. MyBatis 3 에서는새로운추가옵션이생겼다. MyBatis 3 은편리하고강력한자바기반의설정 API 를제공한다. 설정 API 는 XML 기반의 MyBatis 설정의기초가된다. 이는새로운애노테이션기반의설정에도그대로적용된다. 애노테이션은소개하는데많은시간이할애하지않아도될정도로매핑된구문을구현하는간단한방법을제공한다. Note: 자바애노테이션은복잡하고유연해야하는경우에대해서는다소제한적이다. 조사하는데많은시간이소요됨에도불구하고, 가장강력한 MyBatis 매핑은애노테이션으로처리되지는못한다. C# 속성은이러한제한사항이없어서 MyBatis.NET 버전은 XML 대안으로자바보다다소더풍부한기능을제공한다. 하지만자바애노테이션기반의설정이장점이없지는않다. 사용가능한애노테이션은아래에서설명한다. 애노테이션 대상 XML 요소 Class <cache> 명명공간을위한캐시설정사용가능한속성들 : implementation, eviction, flushinterval, size 그리고 Class <cacheref> 다른명명공간의캐시에대한참조사용가능한속성들 : value( 명명공간의이름 Method <constructor> 결과객체생성자에전달되는결과들사용가능한속성들 : value( 인자의배열 Method <arg> <idarg> ConstructorArgs 의일부로한개의생성자인자사용가능한속성들 : id, column, javatype, jdbctype, typehandler, select 그리고 resultmap. id 속성은비교하기위해사용되는값이다. XML 에서는 <idarg> Method <discriminator> 결과매핑을할때사용될수있는경우에대한값들사용가능한속성들 : column, javatype, jdbctype, typehandler, cases. cases 속성은경우 (case) Method <case> case 의값과매핑사용가능한속성들 : value, type, results. results 속성은 Result 의배열이다. 게다가이 Case 애노테이션은 Results 애노테이션에서명시된 ResultMap 와유사하다
55 애노테이션 대상 XML 요소 Method <resultmap> 결과칼럼이프로퍼티나필드에매핑되는방법에대한상세설정을포함하는결과매핑의목록사용가능한속성들 : value(result 애노테이션의배열 Method <result> <id> 칼럼이프로퍼티나필드에매핑되는한개의결과매핑사용가능한속성들 : id, column, property, javatype, jdbctype, typehandler, one, many. id 속성은프로퍼티를비교할때사용할지를표시하는 boolean 값이다. (XML 에서 <id> 와유사하다.) one 속성은한개의관계 (associations) 이고, <association> 과유사하다. many 속성은 collection 이고 <collection> 과유사하다. Method <association> 복잡한타입의한개의프로퍼티를위한매핑이다. 사용가능한속성들 : select( 매핑구문의이름, 예를들어매퍼메서드 ) Note: 조인매핑은애노테이션 API 를통해서는지원되지않는다는것을알아야한다. 순환 (circular) Method <collection> 복잡한타입의 collection 프로퍼티를위한매핑이다. 사용가능한속성들 : select( 매핑구문의이름, 예를들어매퍼메서드 ) Note: 조인매핑은애노테이션 API 를통해서는지원되지않는다는것을알아야한다. 순환 (circular) Method 리턴타입이 Map 인메서드에서사용된다. 결과객체의 List 를객체의프로퍼티에기초한 Map 으로변환하기위해사용된다
56 애노테이션 대상 XML 요소 Method 매핑구문의속성들 이애노테이션은매핑된구문에속성으로존재하는많은분기 (switch) 와설정옵션에접근할수있다. 각구문을복잡하게만들기보다, Options 애노테이션으로일관되고깔끔한방법으로설정할수있게한다. 사용가능한속성들 : usecache=true, flushcache=false, resultsettype=forward_only, statementtype=prepared, fetchsize=-1, timeout=-1, usegeneratedkeys=false, keyproperty= id, keycolumn=. 자바애노테이션을이해하는것이중요하다. 자바애노테이션은 null 을셋팅할수없다. 그래서일단 Options 애노테이션을사용하면각각의속성은디폴트값을사용하게된다. 디폴트값이기대하지않은결과를만들지않도록주의해야한다. keycolumn 은키칼럼이테이블의첫번째칼럼이아닌특정데이터베이스에서만 (PostgreSQL 같은 Method <insert> <update> <delete> <select> 각각의애노테이션은실행하고자하는 SQL 을표현한다. 각각문자열의배열 ( 또는한개의문자열 ) 을가진다. 문자열의배열이전달되면, 각각공백을두고하나로합친다. 자바코드에서 SQL 을만들때발행할수있는 공백누락 문제를해결하도록도와준다. 사용가능한속성들 : value( 한개의 SQL Method <insert> <update> <delete> <select> 동적 SQL 생성을허용 실행시 SQL 을리턴할클래스명과메서드명을명시하도록해주는대체수단의애노테이션이다. 매핑된구문을실행할때 MyBatis 는클래스의인스턴스를만들고, 메서드를실행한다. 메서드는파라미터객체를받을수도있다. 사용가능한속성들 : type, method. type 속성은클래스의패키지경로를포함한전체이름이다. 메서드는클래스의메서드명이다. Note: 이섹션은 SelectBuilder 클래스에대한설명으로, 동적 SQL Parameter N/A 매퍼메서드가여러개의파라미터를가진다면, 이애노테이션은이름에일치하는매퍼메서드파라미터에적용된다. 반면에여러개의파라미터는순서대로명명된다. 예를들어, #{1, #{2 person ) 를사용하면, 파라미터는 #{person 로명명된다
57 애노테이션 대상 XML 요소 Method <selectkey> 애노테이션을사용하는메서드에서 <selectkey> 와똑같다. 애노테이션을명시하면, MyBatis 애노테이션이나설정프로퍼티를통해셋팅된 key 프로퍼티를무시할것이다. 사용가능한속성들 : statement 는실행할 SQL 구문을만드는문자열의배열이다. keyproperty 는새로운값으로수정될파라미터객체의프로퍼티이다. SQL 이 insert 전후에실행되는것을나타내기위해 true 나 false 가되어야한다. resulttype 은 keyproperty 의자바타입이다. Method N/A 애노테이션을위해 XML 매퍼의 <resultmap> 요소의 id 를제공하기위해사용된다. XML 에정의된결과매핑을재사용하도록해준다. 를오버라이드할것이다. Mapper 애노테이션예제 이예제는 insert into table3 (id, name) values(#{nameid, next value for TestSequence", keyproperty="nameid", before=true, resulttype=int.class) int inserttable3(name name); 이예제는 insert into table2 (name) identity()", keyproperty="nameid", before=false, resulttype=int.class) int inserttable2(name name); SelectBuilder 자바개발자에게가장끔찍한일중하나는자바코드에서내장 SQL 을처리하는것이다. SQL 은항상동적으로생성되기때문에그렇다. 반면에파일이나저장프로시저를외부에둘수도있다. 이미그렇게하고있다면, MyBatis 는 XML 매핑에서동적으로 SQL 을생성하기위한강력한대답이될것이다. 어쨌든때때로자바코드에서 SQL 구문을문자열을만들어야할필요가종종있다. 이경우, MyBatis 는좀더쉽게만들도록해준다. 이기능은 + 기호, 따옴표, 개행문자그리고콤마와 AND 등의포맷팅에관련된작업을줄여준다. 자바코드에서 SQL 코드를동적으로생성하는것은정말끔찍하다
58 MyBatis 3 은이문제는다루기위해다른컨셉을소개한다. 단계별로 SQL 구문을만들도록메서드를호출하는클래스의 인스턴스를생성할수있다. 하지만그후 SQL 은 SQL 이라기보다는자바에가까운형태로끝나게된다. 대신조금다른 것을시도할것이다. SelectBuilder 의비밀 SelectBuilder 클래스는마법스럽지는않다. 어떻게작동하는지모른다면좋은선택이라고보기에도어렵다. 그래서바로 살펴보자. SelectBuilder 는깔끔한문법이가능하도록 Static Import 와 ThreadLocal 변수의조합을사용한다. 생성하는 메서드는다음과같다. public String selectblogssql() { BEGIN(); // Clears ThreadLocal variable SELECT("*"); FROM("BLOG"); return SQL(); 정적으로빌드하는매우간단한예제이다. 그래서좀더복잡한예제를보자. private String selectpersonsql() { BEGIN(); // Clears ThreadLocal variable SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FULL_NAME"); SELECT("P.LAST_NAME, P.CREATED_ON, P.UPDATED_ON"); FROM("PERSON P"); FROM("ACCOUNT A"); INNER_JOIN("DEPARTMENT D on D.ID = P.DEPARTMENT_ID"); INNER_JOIN("COMPANY C on D.COMPANY_ID = C.ID"); WHERE("P.ID = A.ID"); WHERE("P.FIRST_NAME like?"); OR(); WHERE("P.LAST_NAME like?"); GROUP_BY("P.ID"); HAVING("P.LAST_NAME like?"); OR(); HAVING("P.FIRST_NAME like?"); ORDER_BY("P.ID"); ORDER_BY("P.FULL_NAME"); return SQL(); 위 SQL 이빌드되면다음의문자열과거의같을것이다. 예를들면 "SELECT P.ID, P.USERNAME, P.PASSWORD, P.FULL_NAME, " "P.LAST_NAME,P.CREATED_ON, P.UPDATED_ON " + "FROM PERSON P, ACCOUNT A " + "INNER JOIN DEPARTMENT D on D.ID = P.DEPARTMENT_ID " + "INNER JOIN COMPANY C on D.COMPANY_ID = C.ID "
59 "WHERE (P.ID = A.ID AND P.FIRST_NAME like?) " + "OR (P.LAST_NAME like?) " + "GROUP BY P.ID " + "HAVING (P.LAST_NAME like?) " + "OR (P.FIRST_NAME like?) " + "ORDER BY P.ID, P.FULL_NAME"; 이러한문법을선호한다면, 이기능을사용해도좋다. 아마도다소에러를야기할수도있다. 각라인마다끝에공백을 추가하는것을잊지말아야한다. 지금부터이문법을선호한다면, 다음예제는자바문자열처리보다좀더간단할것이다. private String selectpersonlike(person p){ BEGIN(); // Clears ThreadLocal variable SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FIRST_NAME, P.LAST_NAME"); FROM("PERSON P"); if (p.id!= null) { WHERE("P.ID like #{id"); if (p.firstname!= null) { WHERE("P.FIRST_NAME like #{firstname"); if (p.lastname!= null) { WHERE("P.LAST_NAME like #{lastname"); ORDER_BY("P.LAST_NAME"); return SQL(); 이예제에서다소특별한건무엇인가? 자좀더자세히보자. AND 키워드가중복되는것에대해서는그다지걱정하지않아도된다. WHERE 와 AND 간의선택하는것도그렇다. 예를들어위구문은 PERSON 의모든레코드를리턴하는쿼리를생성할것이다. 파라미터로 ID 또는 firstname, lastname 등 3 개의조합을가진다. SelectBuilder 는 WHEN 가어디서필요한지 AND 가어디서사용되는지이해하는데주의해야한다. 무엇보다도이러한메서드의호출순서에영향을받지않는다.( 단 OR() 메서드는예외 ) 아마도두개의메서드가먼저보일것이다. 두개의메서드는 BEGIN() 과 SQL() 이다. 먼저 SelectBuilder 의모든메서드는 BEGIN() 을호출해서시작하고 SQL() 을호출해서끝난다. 물론로직중간에생성될 SQL 을추출하는메서드를호출할수도있으나 SQL 을생성하는대부분의상황에서는 BEGIN() 으로시작하고 SQL() 로끝난다. BEGIN() 메서드는 ThreadLocal 변수를초기화하고 SQL() 메서드는 BEGIN() 이후호출에따라 SQL 구문을만든다. BEGIN() 은 RESET() 과동의어이다. 위예제처럼 SelectBuilder 를사용하기위해, static import 할필요가있다. import static org.mybatis.jdbc.selectbuilder.*; 한번 import 하고나면, SelectBuilder 메서드모두사용할수있다. 실제사용가능한모든메서드들이다. Method BEGIN() / RESET() Description 이메서드들은 SelectBuilder 클래스의 ThreadLocal 상태를초기화하고새로운구문을 추가하기위해준비한다. BEGIN() 메서드는새로운구문을추가할때호출하는것이가장
60 Method Description 좋다. RESET() 메서드는어떠한이유로인해실행중간에구문을초기화할때호출하면된다. SELECT(String) SELECT 절을시작하거나추가한다. 한번이상호출될수있고, 파라미터는 SELECT 절에추가될것이다. 파라미터들은칼럼과별칭의목록이고각각의값은콤마로구분된다. SELECT_DISTINCT(String) SELECT 절을시작하거나추가한다. 생성된쿼리에 DISTINCT 키워드만을추가한다. 한번이상호출될수있고, 파라미터들은 SELECT 절에추가될것이다. 파라미터들은칼럼과별칭의목록이고각각의값은콤마로구분된다. FROM(String) FROM 절을시작하거나추가한다. 한번이상호출될수있고, 파라미터는 FROM 절에추가될것이다. 파라미터는테이블명과별칭이다. JOIN(String) 메서드를호출할때적절한타입으로 JOIN 절을추가한다. 파라미터는칼럼과조인하고자 INNER_JOIN(String) 하는조건으로구성된표준조인을포함할수있다. LEFT_OUTER_JOIN(String) RIGHT_OUTER_JOIN(String) WHERE(String) WHERE 절의조건을추가한다. AND 를자동으로추가하고여러번호출될수있다. 여러차례 AND 로새로운조건을만든다. OR 로분기하고자한다면 OR() 메서드를사용하면된다. OR() WHERE 절의조건을 OR 로분리한다. 한번이상호출될수있으나잘못호출하면 SQL 에에러가발생할수있다. AND() WHEER 절의조건을 AND 로분리한다. 한번이상호출될수있으나잘못호출하면 SQL 에에러가발생할수있다. WHERE 과 HAVING 모두조건에 AND 를자동으로붙여준다. 흔히사용되지는않을것이며, 반드시필요한경우에추가로사용하면된다.. GROUP_BY(String) GROUP BY 절을추가한다. 콤마를자동으로추가하고여러차례호출될수있다. 매번콤마를추가해서새로운조건을만든다. HAVING(String) HAVING 절의조건을추가한다. AND 를자동으로추가하고여러차례호출될수있다. 매번 AND 를추가해서새로운조건을추가한다. OR 로분기하고자한다면 OR() 메서드를사용하면된다. ORDER_BY(String) ORDER BY 절을추가한다. 콤마를자동으로추가하고여러차례호출될수있다. 매번콤마를추가해서새로운조건을만든다. SQL() 생성되는 SQL 을리턴하고 SelectBuilder 상태를리셋 (BEGIN() 이나 RESET() 가호출된것처럼 ) 한다. 게다가이메서드는한번만호출될수있다. SqlBuilder SelectBuilder 와유사하게, MyBatis 는일반적인 SqlBuilder 를가지고있다. SelectBuilder 가가진모든메서드를포함할뿐아니라, insert, update 그리고 delete 를만드는메서드도가지고있다. 이클래스는 SelectProvider, DeleteProvider, InsertProvider, 또는 UpdateProvider 에서 SQL 문자열을만들때유용하다. 위예제에서 SqlBuilder 를사용하기위해, 다음처럼 static 으로 import 할필요가있다. import static org.mybatis.jdbc.sqlbuilder.*; SqlBuilder 는 SelectBuilder 의모든메서드를가지고있으며몇가지추가로메서드를더가지고있다
61 메서드설명 DELETE_FROM(String) delete 구문을시작하고실제삭제하고자하는테이블을명시한다. 대개는 WHERE 구문이뒤에붙는다. INSERT_INTO(String) insert 구문을시작하고실제입력하고자하는테이블을명시한다. 대개는하나이상의 VALUES() 호출을뒤따른다. SET(String) update 구문에서 set 에관련된목록을추가한다. UPDATE(String) update 구문을시작하고실제수정하고자하는테이블을명시한다. 하나이상의 SET() 호출이뛰따르고대개는 WHERE() 호출도사용한다. VALUES(String, String) insert 구문에추가된다. 첫번째파라미터는칼럼 (column(s)) 이고두번째파라미터는값 (value(s)) 이다. 이건몇가지예제이다. public String deletepersonsql() { BEGIN(); // Clears ThreadLocal variable DELETE_FROM("PERSON"); WHERE("ID = ${id"); return SQL(); public String insertpersonsql() { BEGIN(); // Clears ThreadLocal variable INSERT_INTO("PERSON"); VALUES("ID, FIRST_NAME", "${id, ${firstname"); VALUES("LAST_NAME", "${lastname"); return SQL(); public String updatepersonsql() { BEGIN(); // Clears ThreadLocal variable UPDATE("PERSON"); SET("FIRST_NAME = ${firstname"); WHERE("ID = ${id"); return SQL(); Logging MyBatis 는내부로그팩토리를사용하여로깅정보를제공한다. 내부로그팩토리는로깅정보를다른로그구현체중 하나에전달한다. 1. SLF4J 2. Jakarta Commons Logging (JCL NOT Job Control Language!)
62 3. Log4J 4. JDK logging 로깅솔루션은내부 MyBatis 로그팩토리의런타임체크를통해선택된다. MyBatis 로그팩토리는가능하면첫번째구현체를사용할것이다 ( 위로깅구현체의나열순서는내부적으로선택하는우선순위이다 ). 만약 MyBatis 가위구현체중하나도찾지못한다면, 로깅을하지않을것이다. 많은환경은애플리케이션서버 ( 좋은예는 Tomcat 과 WebSphere) 의클래스패스의일부로 JCL 을사용한다. 이러한환경을아는것이중요하다. MyBatis 는로깅구현체로 JCL 을사용할것이다. WebSphere 와같은환경에서 Log4J 설정은무시될것이다. 왜냐하면 WebSphere 는자체 JCL 구현체를제공하기때문이다. 이러한사항은불만스러울수있다. 왜냐하면 MyBatis 는당신의 Log4J 설정을무시하는것처럼보일수도있기때문이다. ( 사실 MyBatis 는당신의 Log4J 설정을무시한다. 왜냐하면 MyBatis 는이러한환경에서 JCL 을사용할것이기때문이다.) 만약당신의애플리케이션이클래스패스에 JCL 을포함한환경에서돌아가지만다른로깅구현체중하나를더선호한다면, 다음의메서드중하나를호출하여다른로깅구현체를선택할수있다. org.apache.ibatis.logging.logfactory.useslf4jlogging(); org.apache.ibatis.logging.logfactory.uselog4jlogging(); org.apache.ibatis.logging.logfactory.usejdklogging(); org.apache.ibatis.logging.logfactory.usecommonslogging(); org.apache.ibatis.logging.logfactory.usestdoutlogging(); MyBatis 메서드를호출하기전에위메서드중하나를호출해야한다. 이메서드들은런타임클래스패스에구현체가존재하면그로그구현체를사용하게한다. 예를들어, Log4J 로깅을선택했지만런타임에 Log4J 구현체가클래스패스에없다면, MyBatis 는 Log4J 구현체의사용을무시하고로깅구현체를찾아다시사용할것이다. Jakarta Commons 로깅, Log4J 그리고 JDK 로깅 API 에대한설명은이문서의범위를벗어난다. 이러한로깅관련프레임워크에대해좀더알고싶다면, 개별위치에서좀더많은정보를얻을수있을것이다. Jakarta Commons 로깅 Log4J JDK 로깅 API 로그설정
63 MyBatis 가실제로사용하는로그클래스는 MyBatis 패키지에포함되어있지않다. MyBatis 로깅구문을보기위해서는, java.sql 패키지의클래스에대해로깅을활성화해야할것이다. 해당되는클래스목록들이다. java.sql.connection java.sql.preparedstatement java.sql.resultset java.sql.statement Log4J 를사용하는방법을보여줄것이다. 로깅서비스는하나이상이설정파일 ( 예를들면, log4j.properties) 과새로운 JAR 파일 ( 예를들면, log4j.jar) 을사용한다. 다음의예제는 Log4J 를사용하여로깅서비스를설정할것이다. 두가지단계를거친다. 첫번째단계 : Log4J JAR 파일추가하기 Log4J 를사용하기때문에, 애플리케이션에 JAR 파일이있어야한다. Log4J 를사용하기위해, 애플리케이션의클래스패스에 JAR 파일을추가할필요가있다. 위 URL 에서 Log4J 를다운로드할수있다. 웹이나기업용애플리케이션에서는 WEB-INF/lib 디렉터리에 log4j.jar 파일을추가할수있다. 단독으로실행되는애플리케이션에서는 JVM 의 classpath 시작파라미터에서간단히추가할수있다. 두번째단계 : Log4J 설정하기 Log4J 를설정하는것은간단하다. 먼저 log4j.properties 파일을만들어서다음처럼설정하면된다. log4j.properties # 전역로깅설정 log4j.rootlogger=error, stdout # MyBatis 로깅설정... #log4j.logger.org.apache.ibatis=debug #log4j.logger.java.sql.connection=debug #log4j.logger.java.sql.statement=debug #log4j.logger.java.sql.preparedstatement=debug #log4j.logger.java.sql.resultset=debug # Console 출력... log4j.appender.stdout=org.apache.log4j.consoleappender log4j.appender.stdout.layout=org.apache.log4j.patternlayout log4j.appender.stdout.layout.conversionpattern=%5p [%t] - %m%n 위파일은에러만을리포트하는최소한의설정이다. 파일의두번째라인은 stdout appender 에에러만을출력한다. appender 는출력 ( 예를들면, 콘솔, 파일, 데이터베이스등 ) 을모으는컴포넌트이다. 로그를최대한출력하기위해서는 다음처럼설정을변경해야한다
64 log4j.rootlogger=debug, stdout 두번째라인을위처럼변경하면, Log4J 는 stdout appender 에모든로깅이벤트를출력한다. finer 레벨로레벨을조정하고자한다면, 위파일에서 SqlMap 로깅설정 (4 번째라인에서 8 번째라인까지 ) 에서각클래스별로설정할수있다. PreparedStatement 에대해콘솔에 DEBUG 레벨로로깅 (SQL 구문 ) 을하고싶다면, 다음처럼 7 번째라인을수정하면된다. log4j.logger.java.sql.preparedstatement=debug log4j.properties 파일에서남은설정은 appender 를설정하기위해사용된다. 하지만이내용은이문서의범위를벗어난다. 어쨌든 Log4J 웹사이트에서좀더많은정보를찾을수있다
MyBatis
MyBatis 목차 3 1.1 mybatis 웹애플리케이션개발하기 4 1.1.1 설치하기 4 1.1.2 MYBATIS 설정파일 5 1.1.3 매퍼 XML과매퍼애노테이션 13 1.1.4 트랜잭션관리 16 1.1.5 좀더복잡한매핑규칙정의 17 1.MyBatis 시작하기 1.1 mybatis 웹애플리케이션개발하기 이전장에서는간단한 mybatis 애플리케이션을만들었고,
Spring Boot/JDBC JdbcTemplate/CRUD 예제
Spring Boot/JDBC JdbcTemplate/CRUD 예제 오라클자바커뮤니티 (ojc.asia, ojcedu.com) Spring Boot, Gradle 과오픈소스인 MariaDB 를이용해서 EMP 테이블을만들고 JdbcTemplate, SimpleJdbcTemplate 을이용하여 CRUD 기능을구현해보자. 마리아 DB 설치는다음 URL 에서확인하자.
PowerPoint Presentation
Class - Property Jo, Heeseung 목차 section 1 클래스의일반구조 section 2 클래스선언 section 3 객체의생성 section 4 멤버변수 4-1 객체변수 4-2 클래스변수 4-3 종단 (final) 변수 4-4 멤버변수접근방법 section 5 멤버변수접근한정자 5-1 public 5-2 private 5-3 한정자없음
- JPA를사용하는경우의스프링설정파일에다음을기술한다. <bean id="entitymanagerfactory" class="org.springframework.orm.jpa.localentitymanagerfactorybean" p:persistenceunitname=
JPA 와 Hibernate - 스프링의 JDBC 대신에 JPA를이용한 DB 데이터검색작업 - JPA(Java Persistence API) 는자바의 O/R 매핑에대한표준지침이며, 이지침에따라설계된소프트웨어를 O/R 매핑프레임워크 라고한다. - O/R 매핑 : 객체지향개념인자바와관계개념인 DB 테이블간에상호대응을시켜준다. 즉, 객체지향언어의인스턴스와관계데이터베이스의레코드를상호대응시킨다.
MyBatis
MyBatis 목차 3 1.1 mybatis 시작하기 4 1.1.1 데이터베이스프로그래밍 4 1.1.2 데이터매퍼 MYBATIS 5 1.1.3 이책은구성은 7 1.1.4 정리 7 1.2 mybatis 가장간단히실행하기 8 1.2.1 필수구성요소 8 1.2.2 MYBATIS 설정파일 8 1.2.3 설정파일로드하기 9 1.2.4 데이터조회하기 9 1.2.5 데이터입력하기
쉽게 풀어쓴 C 프로그래밊
Power Java 제 27 장데이터베이스 프로그래밍 이번장에서학습할내용 자바와데이터베이스 데이터베이스의기초 SQL JDBC 를이용한프로그래밍 변경가능한결과집합 자바를통하여데이터베이스를사용하는방법을학습합니다. 자바와데이터베이스 JDBC(Java Database Connectivity) 는자바 API 의하나로서데이터베이스에연결하여서데이터베이스안의데이터에대하여검색하고데이터를변경할수있게한다.
@OneToOne(cascade = = "addr_id") private Addr addr; public Emp(String ename, Addr addr) { this.ename = ename; this.a
1 대 1 단방향, 주테이블에외래키실습 http://ojcedu.com, http://ojc.asia STS -> Spring Stater Project name : onetoone-1 SQL : JPA, MySQL 선택 http://ojc.asia/bbs/board.php?bo_table=lecspring&wr_id=524 ( 마리아 DB 설치는위 URL
JAVA PROGRAMMING 실습 08.다형성
2015 학년도 2 학기 1. 추상메소드 선언은되어있으나코드구현되어있지않은메소드 abstract 키워드사용 메소드타입, 이름, 매개변수리스트만선언 public abstract String getname(); public abstract void setname(string s); 2. 추상클래스 abstract 키워드로선언한클래스 종류 추상메소드를포함하는클래스
Microsoft PowerPoint - CSharp-10-예외처리
10 장. 예외처리 예외처리개념 예외처리구문 사용자정의예외클래스와예외전파 순천향대학교컴퓨터학부이상정 1 예외처리개념 순천향대학교컴퓨터학부이상정 2 예외처리 오류 컴파일타임오류 (Compile-Time Error) 구문오류이기때문에컴파일러의구문오류메시지에의해쉽게교정 런타임오류 (Run-Time Error) 디버깅의절차를거치지않으면잡기어려운심각한오류 시스템에심각한문제를줄수도있다.
Connection 8 22 UniSQLConnection / / 9 3 UniSQL OID SET
135-080 679-4 13 02-3430-1200 1 2 11 2 12 2 2 8 21 Connection 8 22 UniSQLConnection 8 23 8 24 / / 9 3 UniSQL 11 31 OID 11 311 11 312 14 313 16 314 17 32 SET 19 321 20 322 23 323 24 33 GLO 26 331 GLO 26
JUNIT 실습및발표
JUNIT 실습및발표 JUNIT 접속 www.junit.org DownLoad JUnit JavaDoc API Document 를참조 JUNIT 4.8.1 다운로드 설치파일 (jar 파일 ) 을다운로드 CLASSPATH 를설정 환경변수에서설정 실행할클래스에서 import JUnit 설치하기 테스트실행주석 @Test Test 를실행할 method 앞에붙임 expected
10.ppt
: SQL. SQL Plus. JDBC. SQL >> SQL create table : CREATE TABLE ( ( ), ( ),.. ) SQL >> SQL create table : id username dept birth email id username dept birth email CREATE TABLE member ( id NUMBER NOT NULL
JVM 메모리구조
조명이정도면괜찮조! 주제 JVM 메모리구조 설미라자료조사, 자료작성, PPT 작성, 보고서작성. 발표. 조장. 최지성자료조사, 자료작성, PPT 작성, 보고서작성. 발표. 조원 이용열자료조사, 자료작성, PPT 작성, 보고서작성. 이윤경 자료조사, 자료작성, PPT작성, 보고서작성. 이수은 자료조사, 자료작성, PPT작성, 보고서작성. 발표일 2013. 05.
C# Programming Guide - Types
C# Programming Guide - Types 최도경 [email protected] 이문서는 MSDN 의 Types 를요약하고보충한것입니다. http://msdn.microsoft.com/enus/library/ms173104(v=vs.100).aspx Types, Variables, and Values C# 은 type 에민감한언어이다. 모든
PowerPoint Presentation
public class SumTest { public static void main(string a1[]) { int a, b, sum; a = Integer.parseInt(a1[0]); b = Integer.parseInt(a1[1]); sum = a + b ; // 두수를더하는부분입니다 System.out.println(" 두수의합은 " + sum +
PowerPoint Presentation
Package Class 1 Heeseung Jo 목차 section 1 패키지개요와패키지의사용 section 2 java.lang 패키지의개요 section 3 Object 클래스 section 4 포장 (Wrapper) 클래스 section 5 문자열의개요 section 6 String 클래스 section 7 StringBuffer 클래스 section
Spring Data JPA Many To Many 양방향 관계 예제
Spring Data JPA Many To Many 양방향관계예제 오라클자바커뮤니티 (ojc.asia, ojcedu.com) 엔티티매핑 (Entity Mapping) M : N 연관관계 사원 (Sawon), 취미 (Hobby) 는다 : 다관계이다. 사원은여러취미를가질수있고, 하나의취미역시여러사원에할당될수있기때문이다. 보통관계형 DB 에서는다 : 다관계는 1
목차 BUG DEQUEUE 의 WAIT TIME 이 1 초미만인경우, 설정한시간만큼대기하지않는문제가있습니다... 3 BUG [qp-select-pvo] group by 표현식에있는컬럼을참조하는집합연산이존재하지않으면결괏값오류가발생할수있습니다... 4
ALTIBASE HDB 6.5.1.5.10 Patch Notes 목차 BUG-46183 DEQUEUE 의 WAIT TIME 이 1 초미만인경우, 설정한시간만큼대기하지않는문제가있습니다... 3 BUG-46249 [qp-select-pvo] group by 표현식에있는컬럼을참조하는집합연산이존재하지않으면결괏값오류가발생할수있습니다... 4 BUG-46266 [sm]
gnu-lee-oop-kor-lec06-3-chap7
어서와 Java 는처음이지! 제 7 장상속 Super 키워드 상속과생성자 상속과다형성 서브클래스의객체가생성될때, 서브클래스의생성자만호출될까? 아니면수퍼클래스의생성자도호출되는가? class Base{ public Base(String msg) { System.out.println("Base() 생성자 "); ; class Derived extends Base
작성자 : 김성박\(삼성 SDS 멀티캠퍼스 전임강사\)
Session 을이용한현재로그인한사용자의 숫자구하기 작성자 : 김성박 ( 삼성 SDS 멀티캠퍼스전임강사 ) email : [email protected] homepage : http://sunny.sarang.net - 본문서는http://sunny.sarang.net JAVA강좌란 혹은 http://www.javastudy.co.kr 의 칼럼 란에서만배포합니다.
강의 개요
DDL TABLE 을만들자 웹데이터베이스 TABLE 자료가저장되는공간 문자자료의경우 DB 생성시지정한 Character Set 대로저장 Table 생성시 Table 의구조를결정짓는열속성지정 열 (Clumn, Attribute) 은이름과자료형을갖는다. 자료형 : http://dev.mysql.cm/dc/refman/5.1/en/data-types.html TABLE
C++ Programming
C++ Programming 예외처리 Seo, Doo-okok [email protected] http://www.clickseo.com 목 차 예외처리 2 예외처리 예외처리 C++ 의예외처리 예외클래스와객체 3 예외처리 예외를처리하지않는프로그램 int main() int a, b; cout > a >> b; cout
PowerPoint 프레젠테이션
@ Lesson 2... ( ). ( ). @ vs. logic data method variable behavior attribute method field Flow (Type), ( ) member @ () : C program Method A ( ) Method B ( ) Method C () program : Java, C++, C# data @ Program
JDBC 소개및설치 Database Laboratory
JDBC 소개및설치 JDBC } What is the JDBC? } JAVA Database Connectivity 의약어 } 자바프로그램안에서 SQL 을실행하기위해데이터베이스를연결해주는응용프로그램인터페이스 } 연결된데이터베이스의종류와상관없이동일한방법으로자바가데이터베이스내에서발생하는트랜잭션을제어할수있도록하는환경을제공 2 JDBC Driver Manager }
q 이장에서다룰내용 1 객체지향프로그래밍의이해 2 객체지향언어 : 자바 2
객체지향프로그래밍 IT CookBook, 자바로배우는쉬운자료구조 q 이장에서다룰내용 1 객체지향프로그래밍의이해 2 객체지향언어 : 자바 2 q 객체지향프로그래밍의이해 v 프로그래밍기법의발달 A 군의사업발전 1 단계 구조적프로그래밍방식 3 q 객체지향프로그래밍의이해 A 군의사업발전 2 단계 객체지향프로그래밍방식 4 q 객체지향프로그래밍의이해 v 객체란무엇인가
다른 JSP 페이지호출 forward() 메서드 - 하나의 JSP 페이지실행이끝나고다른 JSP 페이지를호출할때사용한다. 예 ) <% RequestDispatcher dispatcher = request.getrequestdispatcher(" 실행할페이지.jsp");
다른 JSP 페이지호출 forward() 메서드 - 하나의 JSP 페이지실행이끝나고다른 JSP 페이지를호출할때사용한다. 예 ) RequestDispatcher dispatcher = request.getrequestdispatcher(" 실행할페이지.jsp"); dispatcher.forward(request, response); - 위의예에서와같이 RequestDispatcher
JAVA 프로그래밍실습 실습 1) 실습목표 - 메소드개념이해하기 - 매개변수이해하기 - 새메소드만들기 - Math 클래스의기존메소드이용하기 ( ) 문제 - 직사각형모양의땅이있다. 이땅의둘레, 면적과대각
JAVA 프로그래밍실습 실습 1) 실습목표 - 메소드개념이해하기 - 매개변수이해하기 - 새메소드만들기 - Math 클래스의기존메소드이용하기 ( http://java.sun.com/javase/6/docs/api ) 문제 - 직사각형모양의땅이있다. 이땅의둘레, 면적과대각선의길이를계산하는메소드들을작성하라. 직사각형의가로와세로의길이는주어진다. 대각선의길이는 Math클래스의적절한메소드를이용하여구하라.
쉽게 풀어쓴 C 프로그래밍
제 5 장생성자와접근제어 1. 객체지향기법을이해한다. 2. 클래스를작성할수있다. 3. 클래스에서객체를생성할수있다. 4. 생성자를이용하여객체를초기화할수 있다. 5. 접근자와설정자를사용할수있다. 이번장에서만들어볼프로그램 생성자 생성자 (constructor) 는초기화를담당하는함수 생성자가필요한이유 #include using namespace
표준프레임워크로 구성된 컨텐츠를 솔루션에 적용하는 것에 문제가 없는지 확인
표준프레임워크로구성된컨텐츠를솔루션에적용하는것에문제가없는지확인 ( S next -> generate example -> finish). 2. 표준프레임워크개발환경에솔루션프로젝트추가. ( File -> Import -> Existring Projects into
13주-14주proc.PDF
12 : Pro*C/C++ 1 2 Embeded SQL 3 PRO *C 31 C/C++ PRO *C NOT! NOT AND && AND OR OR EQUAL == = SQL,,, Embeded SQL SQL 32 Pro*C C SQL Pro*C C, C Pro*C, C C 321, C char : char[n] : n int, short, long : float
chap 5: Trees
5. Threaded Binary Tree 기본개념 n 개의노드를갖는이진트리에는 2n 개의링크가존재 2n 개의링크중에 n + 1 개의링크값은 null Null 링크를다른노드에대한포인터로대체 Threads Thread 의이용 ptr left_child = NULL 일경우, ptr left_child 를 ptr 의 inorder predecessor 를가리키도록변경
어댑터뷰
04 커스텀어댑터뷰 (Custom Adapter View) 커스텀어댑터뷰 (Custom Adapter View) 커스텀어댑터뷰 (Custom Adatper View) 란? u 어댑터뷰의항목하나는단순한문자열이나이미지뿐만아니라, 임의의뷰가될수 있음 이미지뷰 u 커스텀어댑터뷰설정절차 1 2 항목을위한 XML 레이아웃정의 어댑터정의 3 어댑터를생성하고어댑터뷰객체에연결
Microsoft PowerPoint - GUI _DB연동.ppt [호환 모드]
GUI 설계 6 주차 DB 연동김문정 [email protected] 강의순서강의전환경 JDK 설치및환경설정톰캣설치및환경설정이클립스 (JEE) 설치및환경설정 MySQL( 드라이버 ) 설치및커넥터드라이브연결 DB 생성 - 계정생성이클립스에서 DB에연결서버생성 - 프로젝트생성 DB연결테이블생성및등록 2 MySQL 설치확인 mysql - u root -p MySQL 에데이터베이스추가
제11장 프로세스와 쓰레드
제9장자바쓰레드 9.1 Thread 기초 (1/5) 프로그램 명령어들의연속 (a sequence of instruction) 프로세스 / Thread 실행중인프로그램 (program in execution) 프로세스생성과실행을위한함수들 자바 Thread 2 9.1 Thread 기초 (2/5) 프로세스단위작업의문제점 프로세스생성시오버헤드 컨텍스트스위치오버헤드
InsertColumnNonNullableError(#colName) 에해당하는메시지출력 존재하지않는컬럼에값을삽입하려고할경우, InsertColumnExistenceError(#colName) 에해당하는메시지출력 실행결과가 primary key 제약에위배된다면, Ins
Project 1-3: Implementing DML Due: 2015/11/11 (Wed), 11:59 PM 이번프로젝트의목표는프로젝트 1-1 및프로젝트 1-2에서구현한프로그램에기능을추가하여간단한 DML을처리할수있도록하는것이다. 구현한프로그램은 3개의 DML 구문 (insert, delete, select) 을처리할수있어야한다. 테이블데이터는파일에저장되어프로그램이종료되어도사라지지않아야한다.
< 목차 > 1. Data Access Service 개요 (ibatis 활용 ) 3. DBIO 소개
전자정부표준프레임워크 Data Access Service 소개 2011-02-23 오픈커뮤니티김영우커미터 < 목차 > 1. Data Access Service 개요 (ibatis 활용 ) 3. DBIO 소개 Contents 1. Data Access Service 개요 1-1. 데이터처리레이어란? 1-2. 데이터처리레이어구성요소 1-3. Data Access
DBMS & SQL Server Installation Database Laboratory
DBMS & 조교 _ 최윤영 } 데이터베이스연구실 (1314 호 ) } 문의사항은 [email protected] } 과제제출은 [email protected] } 수업공지사항및자료는모두홈페이지에서확인 } dblab.hallym.ac.kr } 홈페이지 ID: 학번 } 홈페이지 PW:s123 2 차례 } } 설치전점검사항 } 설치단계별설명 3 Hallym Univ.
PowerPoint Template
JavaScript 회원정보 입력양식만들기 HTML & JavaScript Contents 1. Form 객체 2. 일반적인입력양식 3. 선택입력양식 4. 회원정보입력양식만들기 2 Form 객체 Form 객체 입력양식의틀이되는 태그에접근할수있도록지원 Document 객체의하위에위치 속성들은모두 태그의속성들의정보에관련된것
목차 BUG 문법에맞지않는질의문수행시, 에러메시지에질의문의일부만보여주는문제를수정합니다... 3 BUG ROUND, TRUNC 함수에서 DATE 포맷 IW 를추가지원합니다... 5 BUG ROLLUP/CUBE 절을포함하는질의는 SUBQUE
ALTIBASE HDB 6.3.1.10.1 Patch Notes 목차 BUG-45710 문법에맞지않는질의문수행시, 에러메시지에질의문의일부만보여주는문제를수정합니다... 3 BUG-45730 ROUND, TRUNC 함수에서 DATE 포맷 IW 를추가지원합니다... 5 BUG-45760 ROLLUP/CUBE 절을포함하는질의는 SUBQUERY REMOVAL 변환을수행하지않도록수정합니다....
Microsoft PowerPoint - 2강
컴퓨터과학과 김희천교수 학습개요 Java 언어문법의기본사항, 자료형, 변수와상수선언및사용법, 각종연산자사용법, if/switch 등과같은제어문사용법등에대해설명한다. 또한 C++ 언어와선언 / 사용방법이다른 Java의배열선언및사용법에대해서설명한다. Java 언어의효과적인활용을위해서는기본문법을이해하는것이중요하다. 객체지향의기본개념에대해알아보고 Java에서어떻게객체지향적요소를적용하고있는지살펴본다.
Bind Peeking 한계에따른 Adaptive Cursor Sharing 등장 엑셈컨설팅본부 /DB 컨설팅팀김철환 Bind Peeking 의한계 SQL 이최초실행되면 3 단계의과정을거치게되는데 Parsing 단계를거쳐 Execute 하고 Fetch 의과정을통해데이터
Bind Peeking 한계에따른 Adaptive Cursor Sharing 등장 엑셈컨설팅본부 /DB 컨설팅팀김철환 Bind Peeking 의한계 SQL 이최초실행되면 3 단계의과정을거치게되는데 Parsing 단계를거쳐 Execute 하고 Fetch 의과정을통해데이터를사용자에게전송하게되며 Parsing 단계에서실행계획이생성된다. Bind 변수를사용하는 SQL
Spring Boot
스프링부트 (Spring Boot) 1. 스프링부트 (Spring Boot)... 2 1-1. Spring Boot 소개... 2 1-2. Spring Boot & Maven... 2 1-3. Spring Boot & Gradle... 3 1-4. Writing the code(spring Boot main)... 4 1-5. Writing the code(commandlinerunner)...
혼자서일을다하는 JSP. 이젠일을 Servlet 과나눠서한다. JSP와서블릿의표현적인차이 - JSP는 <html> 내에서자바를사용할수있는수단을제공한다. - 서블릿은자바내에서 <html> 을작성할수있는수단을제공한다. - JSP나서블릿으로만웹페이지를작성하면자바와다양한코드가
혼자서일을다하는 JSP. 이젠일을 Servlet 과나눠서한다. JSP와서블릿의표현적인차이 - JSP는 내에서자바를사용할수있는수단을제공한다. - 서블릿은자바내에서 을작성할수있는수단을제공한다. - JSP나서블릿으로만웹페이지를작성하면자바와다양한코드가웹페이지내에뒤섞여있어서웹페이지의화면설계가점점어려워진다. - 서블릿이먼저등장하였으나, 자바내에
FileMaker 15 ODBC 및 JDBC 설명서
FileMaker 15 ODBC JDBC 2004-2016 FileMaker, Inc.. FileMaker, Inc. 5201 Patrick Henry Drive Santa Clara, California 95054 FileMaker FileMaker Go FileMaker, Inc.. FileMaker WebDirect FileMaker, Inc... FileMaker.
개발문서 Oracle - Clob
개발문서 ORACLE CLOB 2008.6.9 ( 주 ) 아이캔매니지먼트 개발팀황순규 0. clob개요 1. lob과 long의비교와 clob와 blob 2. 테이블생성쿼리 ( 차이점-추가사항 ) 3. select 쿼리 4. insert 쿼리및 jdbc프로그래밍 5. update 쿼리및 jdbc프로그래밍 (4, 5). putclobdata() 클래스 6. select
파워포인트 템플릿
ibizsoftware 정호열차장 ( 표준프레임워크오픈커뮤니티커미터 ) Agenda 1. ibatis 와 Hibernate 의개념및특징 2. Hibernate 와 JPA 쿼리종류 3. ibatis 와 Hibernate 동시사용을위한 Transaction 처리방안 4. @EntityListeners 활용방법 Agenda 5. Hibernate 사용시 Dynamic
문서 템플릿
HDSI 툴분석 [sql injection 기술명세서 ] Sql injection 기술명세서 Ver. 0.01 이문서는 sql injection 기술명세가범위입니다. Copyrights Copyright 2009 by CanvasTeam@SpeeDroot( 장경칩 ) All Rights Reserved. 장경칩의사전승인없이본내용의전부또는일부에대한복사, 전재,
<4D F736F F F696E74202D20C1A63038C0E520C5ACB7A1BDBABFCD20B0B4C3BC4928B0ADC0C729205BC8A3C8AF20B8F0B5E55D>
Power Java 제 8 장클래스와객체 I 이번장에서학습할내용 클래스와객체 객체의일생직접 메소드클래스를 필드작성해 UML 봅시다. QUIZ 1. 객체는 속성과 동작을가지고있다. 2. 자동차가객체라면클래스는 설계도이다. 먼저앞장에서학습한클래스와객체의개념을복습해봅시다. 클래스의구성 클래스 (class) 는객체의설계도라할수있다. 클래스는필드와메소드로이루어진다.
Microsoft PowerPoint - chap02-C프로그램시작하기.pptx
#include int main(void) { int num; printf( Please enter an integer "); scanf("%d", &num); if ( num < 0 ) printf("is negative.\n"); printf("num = %d\n", num); return 0; } 1 학습목표 을 작성하면서 C 프로그램의
Microsoft PowerPoint - 10Àå.ppt
10 장. DB 서버구축및운영 DBMS 의개념과용어를익힌다. 간단한 SQL 문법을학습한다. MySQL 서버를설치 / 운영한다. 관련용어 데이터 : 자료 테이블 : 데이터를표형식으로표현 레코드 : 테이블의행 필드또는컬럼 : 테이블의열 필드명 : 각필드의이름 데이터타입 : 각필드에입력할값의형식 학번이름주소연락처 관련용어 DB : 테이블의집합 DBMS : DB 들을관리하는소프트웨어
ALTIBASE 사용자가이드 Templete
Real Alternative DBMS ALTIBASE, Since 1999 MyBatis 연동가이드 2014. 10 Copyright c 2000~2014 ALTBASE Corporation. All Rights Reserved. Document Control Change Record Date Author Change Reference 2013-12 sypark
중간고사
중간고사 담당교수 : 단국대학교응용컴퓨터공학박경신 답은반드시답안지에기술할것. 공간이부족할경우반드시답안지몇쪽의뒤에있다고명기한후기술할것. 그외의경우의답안지뒤쪽이나연습지에기술한내용은답안으로인정안함. 답에는반드시네모를쳐서확실히표시할것. 답안지에학과, 학번, 이름외에본인의암호 (4자리숫자 ) 를기입하면성적공고시학번대신암호를사용할것임. 1. JSP 란무엇인가? 간단히설명하라.
FileMaker ODBC 및 JDBC 가이드
FileMaker ODBC JDBC 2004-2019 FileMaker, Inc.. FileMaker, Inc. 5201 Patrick Henry Drive Santa Clara, California 95054 FileMaker, FileMaker Cloud, FileMaker Go FileMaker, Inc.. FileMaker WebDirect FileMaker,
Microsoft PowerPoint - ch07 - 포인터 pm0415
2015-1 프로그래밍언어 7. 포인터 (Pointer), 동적메모리할당 2015 년 4 월 4 일 교수김영탁 영남대학교공과대학정보통신공학과 (Tel : +82-53-810-2497; Fax : +82-53-810-4742 http://antl.yu.ac.kr/; E-mail : [email protected]) Outline 포인터 (pointer) 란? 간접참조연산자
WINDOW FUNCTION 의이해와활용방법 엑셈컨설팅본부 / DB 컨설팅팀정동기 개요 Window Function 이란행과행간의관계를쉽게정의할수있도록만든함수이다. 윈도우함수를활용하면복잡한 SQL 들을하나의 SQL 문장으로변경할수있으며반복적으로 ACCESS 하는비효율역
WINDOW FUNCTION 의이해와활용방법 엑셈컨설팅본부 / DB 컨설팅팀정동기 개요 Window Function 이란행과행간의관계를쉽게정의할수있도록만든함수이다. 윈도우함수를활용하면복잡한 SQL 들을하나의 SQL 문장으로변경할수있으며반복적으로 ACCESS 하는비효율역시쉽게해결할수있다. 이번화이트페이퍼에서는 Window Function 중순위 RANK, ROW_NUMBER,
PowerPoint 프레젠테이션
@ Lesson 3 if, if else, if else if, switch case for, while, do while break, continue : System.in, args, JOptionPane for (,, ) @ vs. logic data method variable Data Data Flow (Type), ( ) @ Member field
Microsoft PowerPoint - 18-DataSource.ppt
18 장 : JDBC DataSource DataSource JDBC 2.0의 javax.sql 패키지에포함되어도입됨 DataSource 인터페이스는데이터베이스커넥션을만들거나사용하는데좀더유연한아키텍처를제공하기위해도입됨 DataSource를이용할경우, 클라이언트코드는한줄도바꾸지않고서도다른데이터베이스에접속할수있도록해줌 즉 DataSource 는커넥션상세사항들을캡슐화
Network Programming
Part 5 확장된 Network Programming 기술 1. Remote Procedure Call 2. Remote Method Invocation 3. Object Request Broker 2. Java RMI
예제 2) Test.java class A intvar= 10; void method() class B extends A intvar= 20; 1"); void method() 2"); void method1() public class Test 3"); args) A
제 10 장상속 예제 1) ConstructorTest.java class Parent public Parent() super - default"); public Parent(int i) this("hello"); super(int) constructor" + i); public Parent(char c) this(); super(char) constructor
JAVA PROGRAMMING 실습 05. 객체의 활용
public class Person{ public String name; public int age; } public Person(){ } public Person(String s, int a){ name = s; age = a; } public String getname(){ return name; } @ 객체의선언 public static void main(string
PowerPoint Presentation
Package Class 3 Heeseung Jo 목차 section 1 패키지개요와패키지의사용 section 2 java.lang 패키지의개요 section 3 Object 클래스 section 4 포장 (Wrapper) 클래스 section 5 문자열의개요 section 6 String 클래스 section 7 StringBuffer 클래스 section
* Factory class for query and DML clause creation * tiwe * */ public class JPAQueryFactory implements JPQLQueryFactory private f
JPA 에서 QueryDSL 사용하기위해 JPAQuery 인스턴스생성방법 http://ojc.asia, http://ojcedu.com 1. JPAQuery 를직접생성하기 JPAQuery 인스턴스생성하기 QueryDSL의 JPAQuery API를사용하려면 JPAQuery 인스턴스를생성하면된다. // entitymanager는 JPA의 EntityManage
Windows 8에서 BioStar 1 설치하기
/ 콘텐츠 테이블... PC에 BioStar 1 설치 방법... Microsoft SQL Server 2012 Express 설치하기... Running SQL 2012 Express Studio... DBSetup.exe 설정하기... BioStar 서버와 클라이언트 시작하기... 1 1 2 2 6 7 1/11 BioStar 1, Windows 8 BioStar
PowerPoint 프레젠테이션
Lecture 02 프로그램구조및문법 Kwang-Man Ko [email protected], compiler.sangji.ac.kr Department of Computer Engineering Sang Ji University 2018 자바프로그램기본구조 Hello 프로그램구조 sec01/hello.java 2/40 자바프로그램기본구조 Hello 프로그램구조
07 자바의 다양한 클래스.key
[ 07 ] . java.lang Object, Math, String, StringBuffer Byte, Short, Integer, Long, Float, Double, Boolean, Character. java.util Random, StringTokenizer Calendar, GregorianCalendar, Date. Collection, List,
ThisJava ..
자바언어에정확한타입을추가한 ThisJava 소개 나현익, 류석영 프로그래밍언어연구실 KAIST 2014 년 1 월 14 일 나현익, 류석영 자바언어에정확한타입을추가한 ThisJava 소개 1/29 APLAS 2013 나현익, 류석영 자바 언어에 정확한 타입을 추가한 ThisJava 소개 2/29 실제로부딪힌문제 자바스크립트프로그램분석을위한요약도메인 나현익,
PowerPoint 프레젠테이션
인터페이스 배효철 [email protected] 1 목차 인터페이스의역할 인터페이스선언 인터페이스구현 인터페이스사용 타입변환과다형성 인터페이스상속 디폴트메소드와인터페이스확장 2 인터페이스의역할 인터페이스란? 개발코드와객체가서로통신하는접점 개발코드는인터페이스의메소드만알고있으면 OK 인터페이스의역할 개발코드가객체에종속되지않게 -> 객체교체할수있도록하는역할 개발코드변경없이리턴값또는실행내용이다양해질수있음
Microsoft PowerPoint - chap06-2pointer.ppt
2010-1 학기프로그래밍입문 (1) chapter 06-2 참고자료 포인터 박종혁 Tel: 970-6702 Email: [email protected] 한빛미디어 출처 : 뇌를자극하는 C프로그래밍, 한빛미디어 -1- 포인터의정의와사용 변수를선언하는것은메모리에기억공간을할당하는것이며할당된이후에는변수명으로그기억공간을사용한다. 할당된기억공간을사용하는방법에는변수명외에메모리의실제주소값을사용하는것이다.
MySQL-.. 1
MySQL- 기초 1 Jinseog Kim Dongguk University [email protected] 2017-08-25 Jinseog Kim Dongguk University [email protected] MySQL-기초 1 2017-08-25 1 / 18 SQL의 기초 SQL은 아래의 용도로 구성됨 데이터정의 언어(Data definition
제8장 자바 GUI 프로그래밍 II
제8장 MVC Model 8.1 MVC 모델 (1/7) MVC (Model, View, Controller) 모델 스윙은 MVC 모델에기초를두고있다. MVC란 Xerox의연구소에서 Smalltalk 언어를바탕으로사용자인터페이스를개발하기위한방법 MVC는 3개의구성요소로구성 Model : 응용프로그램의자료를표현하기위한모델 View : 자료를시각적으로 (GUI 방식으로
PowerPoint Presentation
public class SumTest { public static void main(string a1[]) { int a, b, sum; a = Integer.parseInt(a1[0]); b = Integer.parseInt(a1[1]); sum = a + b ; // 두수를더하는부분입니다 System.out.println(" 두수의합은 " + sum +
8 장데이터베이스 8.1 기본개념 - 데이터베이스 : 데이터를조직적으로구조화한집합 (cf. 엑셀파일 ) - 테이블 : 데이터의기록형식 (cf. 엑셀시트의첫줄 ) - 필드 : 같은종류의데이터 (cf. 엑셀시트의각칸 ) - 레코드 : 데이터내용 (cf. 엑셀시트의한줄 )
8 장데이터베이스 8.1 기본개념 - 데이터베이스 : 데이터를조직적으로구조화한집합 (cf. 엑셀파일 ) - 테이블 : 데이터의기록형식 (cf. 엑셀시트의첫줄 ) - 필드 : 같은종류의데이터 (cf. 엑셀시트의각칸 ) - 레코드 : 데이터내용 (cf. 엑셀시트의한줄 ) - DDL(Data Definition Language) : show, create, drop
Microsoft PowerPoint - 04-UDP Programming.ppt
Chapter 4. UDP Dongwon Jeong [email protected] http://ist.kunsan.ac.kr/ Dept. of Informatics & Statistics 목차 UDP 1 1 UDP 개념 자바 UDP 프로그램작성 클라이언트와서버모두 DatagramSocket 클래스로생성 상호간통신은 DatagramPacket 클래스를이용하여
슬라이드 1
Pairwise Tool & Pairwise Test NuSRS 200511305 김성규 200511306 김성훈 200614164 김효석 200611124 유성배 200518036 곡진화 2 PICT Pairwise Tool - PICT Microsoft 의 Command-line 기반의 Free Software www.pairwise.org 에서다운로드후설치
1. auto_ptr 다음프로그램의문제점은무엇인가? void func(void) int *p = new int; cout << " 양수입력 : "; cin >> *p; if (*p <= 0) cout << " 양수를입력해야합니다 " << endl; return; 동적할
15 장기타주제들 auto_ptr 변환함수 cast 연산자에의한명시적형변환실행시간타입정보알아내기 (RTTI) C++ 프로그래밍입문 1. auto_ptr 다음프로그램의문제점은무엇인가? void func(void) int *p = new int; cout > *p; if (*p
PowerPoint 프레젠테이션
실습 1 배효철 [email protected] 1 목차 조건문 반복문 System.out 구구단 모양만들기 Up & Down 2 조건문 조건문의종류 If, switch If 문 조건식결과따라중괄호 { 블록을실행할지여부결정할때사용 조건식 true 또는 false값을산출할수있는연산식 boolean 변수 조건식이 true이면블록실행하고 false 이면블록실행하지않음 3
Microsoft PowerPoint - chap01-C언어개요.pptx
#include int main(void) { int num; printf( Please enter an integer: "); scanf("%d", &num); if ( num < 0 ) printf("is negative.\n"); printf("num = %d\n", num); return 0; } 1 학습목표 프로그래밍의 기본 개념을
임베디드시스템설계강의자료 6 system call 2/2 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과
임베디드시스템설계강의자료 6 system call 2/2 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과 System call table and linkage v Ref. http://www.ibm.com/developerworks/linux/library/l-system-calls/ - 2 - Young-Jin Kim SYSCALL_DEFINE 함수
금오공대 컴퓨터공학전공 강의자료
C 프로그래밍프로젝트 Chap 14. 포인터와함수에대한이해 2013.10.09. 오병우 컴퓨터공학과 14-1 함수의인자로배열전달 기본적인인자의전달방식 값의복사에의한전달 val 10 a 10 11 Department of Computer Engineering 2 14-1 함수의인자로배열전달 배열의함수인자전달방식 배열이름 ( 배열주소, 포인터 ) 에의한전달 #include
3 S Q L A n t i p a t t e r n s Trees/intro/parent.sql CREATE TABLE Comments ( comment_id SERIAL PRIMARY KEY, parent_id BIGINT UNSIGNED, comment TEXT
3 S Q L A n t i p a t t e r n s Trees/intro/parent.sql CREATE TABLE Comments ( comment_id SERIAL PRIMARY KEY, parent_id BIGINT UNSIGNED, comment TEXT NOT NULL, FOREIGN KEY (parent_id) REFERENCES Comments(comment_id)
Microsoft PowerPoint - ch09 - 연결형리스트, Stack, Queue와 응용 pm0100
2015-1 프로그래밍언어 9. 연결형리스트, Stack, Queue 2015 년 5 월 4 일 교수김영탁 영남대학교공과대학정보통신공학과 (Tel : +82-53-810-2497; Fax : +82-53-810-4742 http://antl.yu.ac.kr/; E-mail : [email protected]) 연결리스트 (Linked List) 연결리스트연산 Stack
TITLE
CSED421 Database Systems Lab MySQL Basic Syntax SQL DML & DDL Data Manipulation Language SELECT UPDATE DELETE INSERT INTO Data Definition Language CREATE DATABASE ALTER DATABASE CREATE TABLE ALTER TABLE
교육자료
THE SYS4U DODUMENT Java Reflection & Introspection 2012.08.21 김진아사원 2012 SYS4U I&C All rights reserved. 목차 I. 개념 1. Reflection 이란? 2. Introspection 이란? 3. Reflection 과 Introspection 의차이점 II. 실제사용예 1. Instance의생성
설계란 무엇인가?
금오공과대학교 C++ 프로그래밍 [email protected] 컴퓨터공학과 황준하 9 강. 클래스의활용목차 멤버함수의외부정의 this 포인터 friend 선언 static 멤버 임시객체 1 /17 9 강. 클래스의활용멤버함수의외부정의 멤버함수정의구현방법 내부정의 : 클래스선언내에함수정의구현 외부정의 클래스선언 : 함수프로토타입 멤버함수정의 : 클래스선언외부에구현
학습목표 함수프로시저, 서브프로시저의의미를안다. 매개변수전달방식을학습한다. 함수를이용한프로그래밍한다. 2
학습목표 함수프로시저, 서브프로시저의의미를안다. 매개변수전달방식을학습한다. 함수를이용한프로그래밍한다. 2 6.1 함수프로시저 6.2 서브프로시저 6.3 매개변수의전달방식 6.4 함수를이용한프로그래밍 3 프로시저 (Procedure) 프로시저 (Procedure) 란무엇인가? 논리적으로묶여있는하나의처리단위 내장프로시저 이벤트프로시저, 속성프로시저, 메서드, 비주얼베이직내장함수등
쉽게 풀어쓴 C 프로그래밍
Power Java 제 7 장클래스와객체 이번장에서학습할내용 객체지향이란? 객체 메시지 클래스 객체지향의장점 String 클래스 객체지향개념을완벽하게이해해야만객체지향설계의이점을활용할수있다. 실제세계는객체로이루어진다. 객체지향이란? 실제세계를모델링하여소프트웨어를개발하는방법 절차지향과객체지향 절차지향프로그래밍 (procedural programming): 문제를해결하는절차를중요하게생각하는방법
PowerPoint Presentation
객체지향프로그래밍 클래스, 객체, 메소드 ( 실습 ) 손시운 [email protected] 예제 1. 필드만있는클래스 텔레비젼 2 예제 1. 필드만있는클래스 3 예제 2. 여러개의객체생성하기 4 5 예제 3. 메소드가추가된클래스 public class Television { int channel; // 채널번호 int volume; // 볼륨 boolean
Microsoft PowerPoint - C++ 5 .pptx
C++ 언어프로그래밍 한밭대학교전자. 제어공학과이승호교수 연산자중복 (operator overloading) 이란? 2 1. 연산자중복이란? 1) 기존에미리정의되어있는연산자 (+, -, /, * 등 ) 들을프로그래머의의도에맞도록새롭게정의하여사용할수있도록지원하는기능 2) 연산자를특정한기능을수행하도록재정의하여사용하면여러가지이점을가질수있음 3) 하나의기능이프로그래머의의도에따라바뀌어동작하는다형성
API 매뉴얼
PCI-DIO12 API Programming (Rev 1.0) Windows, Windows2000, Windows NT and Windows XP are trademarks of Microsoft. We acknowledge that the trademarks or service names of all other organizations mentioned
6장. SQL
학습목표 SQL이 무엇인지 개념을 설명 테이블을 생성, 변경, 제거할 할 수 있다. 수 있다. 데이터를 검색, 갱신, 삽입, 삭 제할 수 있다. 뷰, 시스템 카탈로그, 저장 프 로시저, 트리거에 대한 개념 을 설명할 수 있다. 2 목차 SECTION 01 SQL의 개요 11 SQL의 역사 12 SQL의 유형별 종류 SECTION 0 21 스키마 22 테이블
FileMaker ODBC and JDBC Guide
FileMaker 13 5 5 5 6 6 6 7 7 8 8 8 8 9 9 10 10 11 11 12 12 12 12 12 12 13 13 14 14 16 16 18 4 19 19 20 20 21 21 21 23 23 23 23 25 26 26 26 26 27 28 28 28 28 29 31 31 32 33 33 33 33 34 34 35 35 35 36 1
Microsoft PowerPoint 자바-기본문법(Ch2).pptx
자바기본문법 1. 기본사항 2. 자료형 3. 변수와상수 4. 연산자 1 주석 (Comments) 이해를돕기위한설명문 종류 // /* */ /** */ 활용예 javadoc HelloApplication.java 2 주석 (Comments) /* File name: HelloApplication.java Created by: Jung Created on: March
Cluster management software
자바네트워크프로그래밍 (OCJP 국제공인자격취득중심 ) 충북대학교 최민 기본예제 예외클래스를정의하고사용하는예제 class NewException extends Exception { public class ExceptionTest { static void methoda() throws NewException { System.out.println("NewException
rmi_박준용_final.PDF
(RMI) - JSTORM http://wwwjstormpekr (RMI)- Document title: Document file name: Revision number: Issued by: Document Information (RMI)- rmi finaldoc Issue Date: Status:
Microsoft PowerPoint - Java7.pptx
HPC & OT Lab. 1 HPC & OT Lab. 2 실습 7 주차 Jin-Ho, Jang M.S. Hanyang Univ. HPC&OT Lab. [email protected] HPC & OT Lab. 3 Component Structure 객체 (object) 생성개념을이해한다. 외부클래스에대한접근방법을이해한다. 접근제어자 (public & private)
10.0pt1height.7depth.3width±â10.0pt1height.7depth.3widthÃÊ10.0pt1height.7depth.3widthÅë10.0pt1height.7depth.3width°è10.0pt1height.7depth.3widthÇÁ10.0pt1height.7depth.3width·Î10.0pt1height.7depth.3width±×10.0pt1height.7depth.3width·¡10.0pt1height.7depth.3width¹Ö pt1height.7depth.3widthŬ10.0pt1height.7depth.3width·¡10.0pt1height.7depth.3width½º, 10.0pt1height.7depth.3width°´10.0pt1height.7depth.3widthü, 10.0pt1height.7depth.3widthº¯10.0pt1height.7depth.3width¼ö, 10.0pt1height.7depth.3width¸Þ10.0pt1height.7depth.3width¼Ò10.0pt1height.7depth.3widthµå
기초통계프로그래밍 클래스, 객체, 변수, 메소드 [email protected] 금융정보통계학과 강희모 ( 금융정보통계학과 ) 기초통계프로그래밍 1 / 26 자바구성파일 소스파일 소스파일 : 사용자가직접에디터에입력하는파일로자바프로그램언어가제공하는형식으로제작 소스파일의확장자는.java 임 컴파일 : javac 명령어를이용하여프로그래머가만든소스파일을컴파일하여실행파일.class
ORANGE FOR ORACLE V4.0 INSTALLATION GUIDE (Online Upgrade) ORANGE CONFIGURATION ADMIN O
Orange for ORACLE V4.0 Installation Guide ORANGE FOR ORACLE V4.0 INSTALLATION GUIDE...1 1....2 1.1...2 1.2...2 1.2.1...2 1.2.2 (Online Upgrade)...11 1.3 ORANGE CONFIGURATION ADMIN...12 1.3.1 Orange Configuration
