GenericMyBatisDaoSupport.java
package com.openerp.common.dao;

import java.io.Serializable;
import java.util.ArrayList;

import org.apache.ibatis.exceptions.PersistenceException;

public interface GenericMyBatisDaoSupport{
	public T get(PK id) throws PersistenceException;//get obj of type T by the primary key 'id' 
	public ArrayList getAll() throws PersistenceException;//get all objects of type T
	public int insert(T objInstance) throws PersistenceException;//insert an object of type T into the database
	int update(T transientObject) throws PersistenceException; //update an object of type T    
	int delete(PK id)  throws PersistenceException;//delete an object of type T
}




AbstractGenericMyBatisDao.java
package com.openerp.common.dao;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.apache.ibatis.exceptions.PersistenceException;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

public class AbstractGenericMyBatisDao implements GenericMyBatisDaoSupport {
	
	private static Logger log = LoggerFactory.getLogger(AbstractGenericMyBatisDao.class);
	private static final String NAMESPACE = "Mapper"; 

	@Autowired
	private SqlSessionFactory sqlSessionFactory; //reference to mybatis session factory 
	private Class type;

	/** 
	 * Define prefixes for easier naming convetions between XML mapper files and the DAO class 
	 **/
	public static final String PREFIX_SELECT_QUERY = "get";     //prefix of select queries in mapper files (eg. getAddressType) 
	public static final String PREFIX_INSERT_QUERY = "insert"; //prefix of insert queries in mapper files (eg. insertAddressType)
	public static final String PREFIX_UPDATE_QUERY = "update";  //prefix of update queries in mapper files (eg. updateAddressType)
	public static final String PREFIX_DELETE_QUERY = "delete";  //prefix of delete queries in mapper files (eg. deleteAddressType)
	public static final String PREFIX_LIST_QUERY = "list";  //prefix of delete queries in mapper files (eg. deleteAddressType)

	/** Default Constructor */
	public AbstractGenericMyBatisDao(Class type) {
		this.type = type;
	}
	
	/** Default Constructor */
	public AbstractGenericMyBatisDao(Class type, SqlSessionFactory sf) {
		this.type = type;
		this.sqlSessionFactory = sf;
		if(sf==null)
			log.error("Error: Could not instantiate MyBatisDAO. Loading myBatis sessionFactory failed.");  
	}

	/** Use this method to get a session factory for using in any methods impelmented in child dao classes */
	protected SqlSessionFactory getSessionFactory() {
		return sqlSessionFactory;
	}

	/** 
	 *  Default get by id method. 
	 *  

* Almost all objects in the db will * need this (except mapping tables for multiple joins, which you * probably shouldn't even have as objects in your model, since proper * MyBatis mappings can take care of that). *

* Example: *
* If your DAO object is called CarInfo.java, * the corresponding mapper query id should be: <select id="getCarInfo" ... */ @SuppressWarnings("unchecked") public T get(PK id) throws PersistenceException { SqlSession session = sqlSessionFactory.openSession(); T obj = null; try { String query = this.type.getSimpleName()+NAMESPACE+"."+PREFIX_SELECT_QUERY+this.type.getSimpleName(); //If the object's calls name is AddressType.java, this matches the mapper query id: "namespace.getAddressType" obj = (T)session.selectOne(query,id); } finally { session.close(); } return obj; } /** * Method returns all rows for this object. *

* Example: *
* If your DAO object is called CarInfo.java, * the corresponding mapper query id should be: <select id="getAllCarInfo" ... *

* SQL Executed: select * from [tablename] *

* Notes: *
* Consider overdiding this method in order to handle large numbers of objects * with multiple references. * LAZY LOADING should be enabled in this case, otherwise you might run out of memory (eg. get all UserAccounts if the table has 1,000,000 rows) * look into the aggresiveLazyLoading property * */ @SuppressWarnings("unchecked") public ArrayList getAll() throws PersistenceException { SqlSession session = sqlSessionFactory.openSession(); ArrayList list = null; try { String query = this.type.getSimpleName()+NAMESPACE+"."+PREFIX_SELECT_QUERY+"All"+this.type.getSimpleName(); list = (ArrayList)session.selectList(query); } finally { session.close(); } return list; } /** * Method returns first object which matches the given name (exact match). *

* It's up to you to decide what constitutes an object's name. Typically you would have a * NAME column in the table, but not all objects have this. Generally this method should be overriden (if you need it at all) * in the child dao class. *

* Example: *
* If your DAO object is called CarInfo.java, * the corresponding mapper query id should be: <select id="getCarInfoByName" ... *

* SQL Executed (example): select * from [tablename] where NAME = ? * */ @SuppressWarnings("unchecked") public T getByName(String name) throws PersistenceException { SqlSession session = sqlSessionFactory.openSession(); T obj = null; try { String query = this.type.getSimpleName()+NAMESPACE+"."+PREFIX_SELECT_QUERY+this.type.getSimpleName()+"ByName"; obj = (T)session.selectOne(query, name); } finally { session.close(); } return obj; } /** * Method inserts the object into the table. *

* You will usually override this method, especially if you're inserting associated objects. *
* Example: *
* If your DAO object is called CarInfo.java, * the corresponding mapper query id should be: <insert id="createCarInfo" ... *

* SQL Executed (example): insert into [tablename] (fieldname1,fieldname2,...) values(value1,value2...) ... * */ public int insert(T o) throws PersistenceException{ SqlSession session = sqlSessionFactory.openSession(); Integer status = null; try { String query = this.type.getSimpleName()+NAMESPACE+"."+PREFIX_INSERT_QUERY+o.getClass().getSimpleName(); status = (Integer)session.insert(query, o); session.commit(); } finally { session.close(); } return status; } /** * Method updates the object by id. *

* You will usually override this method. But it can be used for simple objects. *
* Example: *
* If your DAO object is called CarInfo.java, * the corresponding mapper query id should be: <update id="updateCarInfo" ... *

* SQL Executed (example): update [tablename] set fieldname1 = value1 where id = #{id} * */ public int update(T o)throws PersistenceException { SqlSession session = sqlSessionFactory.openSession(); Integer status = null; try { String query = this.type.getSimpleName()+NAMESPACE+"."+PREFIX_UPDATE_QUERY+o.getClass().getSimpleName(); status = session.update(query, o); session.commit(); } finally { session.close(); } return status; } /** * Method deletes the object by id. *

* Example: *
* If your DAO object is called CarInfo.java, * the corresponding mapper query id should be: <delete id="deleteCarInfo" ... *

* SQL Executed (example): update [tablename] set fieldname1 = value1 where id = #{id} * */ public int delete(PK id) throws PersistenceException{ SqlSession session = sqlSessionFactory.openSession(); Integer status = null; try { String query = this.type.getSimpleName()+NAMESPACE+"."+PREFIX_DELETE_QUERY+this.type.getSimpleName(); status = session.delete(query, id); session.commit(); } finally { session.close(); } return status; } }


RoleService.java
package com.openerp.service;

import com.openerp.domain.Role;

public interface RoleService {
	Role getRole(int key);
}


RoleServiceImpl.java
package com.openerp.service.impl;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.openerp.dao.RoleDao;
import com.openerp.domain.Role;
import com.openerp.service.RoleService;

@Service("roleMgr")
public class RoleServiceImpl implements RoleService{
	
	Log logger = LogFactory.getLog(this.getClass());
	
	@Autowired
	private RoleDao dao;

	@Override
	public Role getRole(int key) {
		return dao.get(key);
	}
	
}


Controller
package com.openerp.controller;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.arnx.jsonic.JSONException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.openerp.common.utils.JSONUtil;
import com.openerp.service.RoleService;

@Controller
public class JsonController {

	@Autowired private RoleService roleMgr;
	
	@RequestMapping("/json/sampleData.do")
	public void sendJsonData(HttpServletRequest req, HttpServletResponse rep){
		int key = Integer.parseInt(req.getParameter("key"));
		try {
			rep.setCharacterEncoding("UTF-8");
			rep.getWriter().write(JSONUtil.toJSON(roleMgr.getRole(key), null));
			
		} catch (JSONException e) {
			e.printStackTrace();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}


SqlMapConfig.xml



	
		 
	

	
		
	

	



mapUnderscoreToCamelCase 이 속성을 안적어주면 아래 필드가 매핑되지 않는다.
ROLE_NAME_KOR 이런 필드는 카멜 표기법으로 표기하지 않기 때문에 꼭 위의 속성이 필요하다...


SQL File :

Full Source :
설명 적는게 너무 귀찮으다...


Mapper 방식은 아래 처럼 사용한다.
	
	    
	    
	


pacakge com.openerp.dao

public interface RoleDao{
	List listRole(Parameters params);
	List listRole(Parameters params, int pg, int ps);
}

이 경우 Mapper에 등록을 했기때문에 roleMapper 라는 이름으로  bean에 등록이 된다.

"예전부터 사용해오던 DAO 패턴을 같이 쓸 수 없을까?" 라는 궁금증이 생겨 반나절동안 해 보았는데... 안된다.

DAO 패턴도 어쨋든 Spring DI에 등록이 되어야 하는데 같은 클래스가 두개의 이름으로 등록이 되는 현상이 발생된다. 

No qualifying bean of type [com.openerp.dao.RoleDao] is defined: expected single matching bean but found 2: roleDao,roleMapper


이 같은 결론을 얻고 생각을 해보니.. 

DAO Pattern을 그냥 간소화 시켜서 사용하는게 Mapper 방식이네? 


reference)
myBatis DAO Pattern example : http://blog.idleworx.com/2011/09/mybatis-dao-example-code-tutorial.html 

기존에 사용하던 Spring 3.1에서 3.2.3으로 변경했다. 하는김에 myBatis도 최신으로 변경.. 
이러다가 그냥 back-end를 다 최신으로 변경하기로 작정하고 작업 진행..

applicationContext.xml 에서 myBatis 설정이 조금 변경되었다. 

org.springframework.orm.ibatis.support.SqlMapClientDaoSupport
as of Spring 3.2, in favor of the native Spring support in the Mybatis follow-up project (http://code.google.com/p/mybatis/)
org.springframework.orm.ibatis.SqlMapClientFactoryBean
as of Spring 3.2, in favor of the native Spring support in the Mybatis follow-up project (http://code.google.com/p/mybatis/)
org.springframework.orm.ibatis.SqlMapClientTemplate
as of Spring 3.2, in favor of the native Spring support in the Mybatis follow-up project (http://code.google.com/p/mybatis/)

3.2 버전 이전은 위 클래스를 이용하여 myBatis 설정을 했지만 3.2 이후부터는 불가능하다.

> myBatis configuration codes in applicationContext
	
	
		
		
		
		
		
			
		
	

심플하다... SqlMapConfig에 mapper를 일일이 적어주어도 되지만
mapperLocations를 이용하여 패키지 검색으로 자동 매핑되게도 할 수 있고 이게 더 편하다.

또 하나, 기본 설정 그대로 사용하고자 한다면 configLocation을 적지 않아도 된다.

아래는 maven에서의 myBatis 설정에 관련된 코드.
	
		
		3.2.2
		1.2.0
		
	

	
		
		
			org.mybatis
			mybatis
			${org.mybatis.version}
		
		
			org.mybatis
			mybatis-spring
			${org.mybatis.spring.version}
		
	




 

 


Spring은 자체 maven Repository가 존재한다. 
이곳에서 라이브러리를 통으로 내려 받을 수 있다. 

site : https://ebr.springsource.com/repository/app/ 
	
		
		    com.springsource.repository.bundles.release
		    SpringSource Enterprise Bundle Repository - SpringSource Bundle Releases
		    http://repository.springsource.com/maven/bundles/release
		
		
		
		    com.springsource.repository.bundles.external
		    SpringSource Enterprise Bundle Repository - External Bundle Releases
		    http://repository.springsource.com/maven/bundles/external
		
		
		
		    com.springsource.repository.libraries.release
		    SpringSource Enterprise Bundle Repository - SpringSource Library Releases
		    http://repository.springsource.com/maven/libraries/release
		
		
		
		    com.springsource.repository.libraries.external
		    SpringSource Enterprise Bundle Repository - External Library Releases
		    http://repository.springsource.com/maven/libraries/external
		
	

	
		
			org.springframework
			org.springframework.spring-library
	    	libd
			3.2.3.RELEASE
			
		        
					javax.servlet
		            com.springsource.javax.servlet
				
			
		
	


junit으로 테스트를 진행하고자 할 경우 아래 의존성도 추가해 주어야 한다.
		
			org.springframework
			org.springframework.test
			3.2.3.RELEASE
		

'백엔드 > Spring' 카테고리의 다른 글

myBatis DAO Pattern example  (0) 2013.07.19
Spring 3.2.3 + myBatis 3.2.2  (0) 2013.07.19
Spring Framework 3.2.3 Maven으로 한번에 추가하기..  (0) 2013.07.18
Spring 3.2.2 + Tiles 3.0  (0) 2013.05.22
Spring Security 설정.  (2) 2011.08.30
[2011-05-26] Spring Security 설정 오류.  (0) 2011.05.26

Tiles 3.0을 사용하기 위해선 Spring Framework 3.2 이상의 버전이 필요하다.

기존 버전과 비교했을때 설정이 간소화 되었다.

http://dhruvgairola.blogspot.kr/2013/03/spring-mvc-with-apache-tiles-3.html 

'백엔드 > Spring' 카테고리의 다른 글

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


이 에러 발생시 Oracle JDBC Driver를 업데이트 해준다.

가령.. 11g 기준의 jar 파일이러단가..

JDK6을 지원하는 ojdbc6.jar로 교체하면 정상 작동한다. 
http://wiki.eclipse.org/EclipseLink/Examples/JPA/Pagination

 위 내용 중 쉽게 쓸만 한 것은 아래 코드이다.
Query query = em.createQuery("SELECT e FROM Employee e ORDER BY e.lastName ASC, e.firstName ASC");
query.setFirstResult(5);
query.setMaxResults(5);
List emps = query.getResultList();

예제에는 오라클이라 되어 있는데 MySQL도 사용 가능하다.






 
설치된 Java 환경이 SE 인가 EE인가 살펴보자..

 



one-to-one 및 many-to-one일 경우
SE 환경에서는 JPA가 fetch 무시하고 EAGER로 적용해버린다. 

고로.. SE에서는 쓸모가 없다.. ;; 


http://www.java2s.com/Code/Java/JPA/CatalogJPA.htm

잘 되어 있고 코드도 어렵지 않다. 


http://www.objectdb.com/java/jpa/persistence

JPA 각 클래스 및 짤막한 예제 코드가 있는 곳. 

import org.apache.commons.io.IOUtils;

private void copy(File source, File target){
		try {
			in = new FileInputStream(source);
			out = new FileOutputStream(target, true);
		
        	IOUtils.copy(in, out);
        	
        } catch (IOException ex) {
        	ex.printStackTrace();
        	
        } finally {
        	IOUtils.closeQuietly(in);
            IOUtils.closeQuietly(out);
        }
}

FileOutputStream의 생성자 중 두번째 인자는 append 여부.





+ Recent posts