반응형

https://github.com/antop-dev/example/tree/master/mybatis-rowbounds-example

 

Mybatis에 RowBounds 클래스를 이용해서 페이징 처리를 할 수 있다.

package org.antop.mybatis.mapper;
import org.antop.mybatis.model.Employee;
import org.apache.ibatis.session.RowBounds;
import java.util.List;

public interface EmployeeMapper {
	List<Employee> select(RowBounds rowBounds);
}

 

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.antop.mybatis.mapper.EmployeeMapper">
	<resultMap id="BaseResultMap" type="org.antop.mybatis.model.Employee">
    	<id property="no" column="emp_no" />
        <result property="gender" column="gender" typeHandler="org.antop.mybatis.handler.GenderTypeHandler" />
        <association property="name" javaType="org.antop.mybatis.model.Name">
        	<result property="first" column="first_name" />
            <result property="last" column="last_name" />
		</association>
	</resultMap>
    
    <select id="select" resultMap="BaseResultMap">
    	select
        	*
		from
        	employees
		order by
        	emp_no asc
	</select>
</mapper>

 

위와 같이 맵퍼와 XML 이 있다.

RowBounds rowBounds = new RowBounds(5, 10);
// 15건을 가져와서 앞에 5건 건너띔
List select = mapper.select(rowBounds);

결과는 10건이 나왔지만 어떻게 동작할까?

여기저기 찾아보고 소스도 대충(?) 보면 offset + limit 만큼 가져와서 offset 만큼 건너띤다.

페이징이 뒤로 갈 수록 느려지게 된다.

RowBounds rowBounds = new RowBounds(29990, 10);
// 30000건을 가져와서 앞에 29990건 건너띔
List select = mapper.select(rowBounds);

데이터의 양이 적다면 쿼리에서 페이징을 하지 않고 RowBouns를 이용하면 빠르게 개발할 수 있을 것이다.

하긴 요즘 수천만건의 데이터를 페이징에서 마지막 페이지를 볼 일이 많을까? -_-/

 

XML 쿼리문에 페이징을 넣지 않고 RowBounds 클래스를 사용하면 자동으로 페이징 쿼리가 실행되게 할 수 없을까?

방법이 있다! Mybatis Intercepter를 이용하면 된다. (인터셉터의 자세한 사용법은 다루지 않겠다 ㅠㅠ)

  1. Mybatis에서 쿼리를 날리기 전에 가로챈다.
  2. RowBounds가 있으면 쿼리에 페이징 문장를 적용한다.
  3. RowBounds를 제거하여 Mybatis에서 페이징 처리를 하지 않도록 한다.

아래 소스는 쿼리에 MySQL용으로 limit 문을 붙여준다.

package org.antop.mybatis.intercepter;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.ReflectorFactory;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.Connection;
import java.util.Properties;

@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class MysqlRowBoundsInterceptor implements Interceptor {
	private static final Logger logger = LoggerFactory.getLogger(MysqlRowBoundsInterceptor.class);
    private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();
    private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();
    private static final ReflectorFactory DEFAULT_REFLECTOR_FACTORY = new DefaultReflectorFactory();
    
    public Object intercept(Invocation invocation) throws Throwable {
    	StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        MetaObject metaStatementHandler = MetaObject.forObject(statementHandler, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, DEFAULT_REFLECTOR_FACTORY);
        String originalSql = (String) metaStatementHandler.getValue("delegate.boundSql.sql");
        RowBounds rb = (RowBounds) metaStatementHandler.getValue("delegate.rowBounds");
        logger.debug("originalSql = {}", originalSql);
        logger.debug("RowBounds = {}", rb);
        if (rb == null || rb == RowBounds.DEFAULT) { // RowBounds가 없으면 그냥 실행
        	return invocation.proceed();
		}
        
        // RowBounds가 있다!
        // 원래 쿼리에 limit 문을 붙여준다.
        StringBuffer sb = new StringBuffer();
        sb.append(originalSql);
        sb.append(" limit ");
        sb.append(rb.getOffset());
        sb.append(", ");
        sb.append(rb.getLimit());
        
        logger.debug("sql = {}", sb.toString());
        // RowBounds 정보 제거
        metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET);
        metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT);
        // 변경된 쿼리로 바꿔치기
        metaStatementHandler.setValue("delegate.boundSql.sql", sb.toString());
        
        return invocation.proceed();
	}
    
    public Object plugin(Object target) {
    	return Plugin.wrap(target, this);
	}
    
    public void setProperties(Properties properties) {
    }
    
}

SqlSessionFactory 설정하는 부분에 인터셉터를 적용하면 된다.

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">
	
    <mybatis:scan base-package="org.antop.mybatis"/>
    
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    	<property name="dataSource" ref="dataSource"/>
        <property name="mapperLocations" value="classpath*:mybatis/*.xml"/>
        <property name="plugins">
        	<list>
            	<!-- 인터셉터 설정 -->
                <bean class="org.antop.mybatis.intercepter.MysqlRowBoundsInterceptor"/>
			</list>
		</property>
	</bean>
    
    <bean id="dataSource" ... />
</beans>

 

실행시켜 보면 쿼리문에 페이징이 적용되서 쿼리가 날라가는 것을 확인할 수 있다.

 

select * from employees order by emp_no asc limit 29990, 10

 

 

출처

http://www.programering.com/a/MTM5gTNwATQ.html

http://hjw1456.tistory.com/10

반응형
//

Installing Hive(Hadoop 1) + MySQL on CentOS 6.7

Posted at 2016. 1. 5. 22:04 | Posted in Study/Hadoop
반응형

Introduction



Hive 를 공부해보기 MySQL을 메타 스토어로 사용하는 최소한의 설치를 설치해보자..




Requirements


여기서 MySQL 설치에 대해서 다루지 않겠다... 데이터베이스와 유저까지 만들자.


Host: mysqldb

Database: hive

Username: hive


※ MySQL 을 사용 하지 않을 경우를 위해서 생략 가능한 절차를 코맨트 하겠다.


하둡은 이미 설치되어 있어야 한다. 설치된 환경은 아래와 같다.


$ rpm -qa *-release

centos-release-6-7.el6.centos.12.3.x86_64


$ java -version

java version "1.7.0_80"

Java(TM) SE Runtime Environment (build 1.7.0_80-b15)

Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)


$ whoami

hadoop


$ pwd

/opt/hadoop


$ hadoop version

Hadoop 1.2.1

Subversion https://svn.apache.org/repos/asf/hadoop/common/branches/branch-1.2 -r 1503152

Compiled by mattf on Mon Jul 22 15:23:09 PDT 2013

From source with checksum 6923c86528809c4e7e6f493b6b413a9a

This command was run using /opt/hadoop/hadoop-1.2.1/hadoop-core-1.2.1.jar


하이브가 설치될 환경을 미리 잡아주자.


$ cat ~/.bashrc

# .bashrc

# 생략

# User specific aliases and functions

export HADOOP_HOME=/opt/hadoop/hadoop-1.2.1

export HIVE_HOME=/opt/hadoop/hive-1.2.1

export PATH=$PATH:$HADOOP_HOME/bin:$HIVE_HOME/bin




Download Hive


하이브 최신(1.2.1) 파일을 다운로드 받아 설치하자.


# 파일 다운로드

$ wget http://mirror.apache-kr.org/hive/hive-1.2.1/apache-hive-1.2.1-bin.tar.gz


# 압축 해제

$ tar -xzvf apache-hive-1.2.1-bin.tar.gz


# 이름 변경

$ mv apache-hive-1.2.1-bin hive-1.2.1




Install MySQL Connector/J


※ MySQL 을 사용하지 않을 거라면 패스


하이브에서 메타스토어를 다른 데이터베이스로 사용할 시에 해당 JDBC 라이브러리를 넣어줘야한다.


MySQL을 사용할 것이기 때문에 이에 맞는 라이브러리를 찾아 넣어주자. 


# 파일 다운로드

$ wget http://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.38.tar.gz


# 압축 해제

$ tar -xzvf mysql-connector-java-5.1.38.tar.gz


# jar 파일 복사

$ cp mysql-connector-java-5.1.38/mysql-connector-java-5.1.38-bin.jar /opt/hadoop/hadoop-1.2.1/lib


MySQL 스키마 파일은 하이브에 포함되어 있다. 어떤 방법을 쓰든.... 실행하자.


$HIVE_HOME/scripts/metastore/upgrade/mysql/hive-schema-1.2.0.mysql.sql


나는 mysql client 를 이용해서 넣었다..


$ mysql --host=mysqldb --database=hive --user=hive --password=**** < $HIVE_HOME/scripts/metastore/upgrade/mysql/hive-schema-1.2.0.mysql.sql


Setting


하이브에서 사용하게 될 영역을 HDFS 내에 만들자.


$ $HADOOP_HOME/bin/hadoop fs -mkdir /tmp

$ $HADOOP_HOME/bin/hadoop fs -mkdir /user/hive/warehouse

$ $HADOOP_HOME/bin/hadoop fs -chmod g+w /tmp

$ $HADOOP_HOME/bin/hadoop fs -chmod g+w /user/hive/warehouse


설정 파일을 만들자. (이 파일이 처음에는 없을 것이다)


$ vi $HIVE_HOME/conf/hive-site.xml


<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
    <property>
        <name>fs.default.name</name>
        <value>hdfs://hadoop-01:9000</value>
    </property>
    <!-- MySQL 사용 안할 거라면 이 아래는 패스 -->
    <property>
        <name>javax.jdo.option.ConnectionURL</name>
        <value>jdbc:mysql://mysqldb:3306/hive</value>
    </property>
    <property>
        <name>javax.jdo.option.ConnectionDriverName</name>
        <value>com.mysql.jdbc.Driver</value>
    </property>
    <property>
        <name>javax.jdo.option.ConnectionUserName</name>
        <value>hive</value>
    </property>
    <property>
        <name>javax.jdo.option.ConnectionPassword</name>
        <value>****</value>
    </property>
</configuration>




이제 하이브를 한번 실행 해보자. 아래와 같이 CLI 커맨드가 나오면 OK!

$ hive

Logging initialized using configuration in jar:file:/opt/hadoop/hive-1.2.1/lib/hive-common-1.2.1.jar!/hive-log4j.properties
hive> _


반응형

'Study > Hadoop' 카테고리의 다른 글

Install Ambari and Deploy HDP in CentOS  (1) 2016.06.05
Installing Hadoop 1 on Ubuntu 14.04  (0) 2015.11.12
//

MySql Password Encoder

Posted at 2013. 9. 21. 19:24 | Posted in Framework/Spring Security
반응형
개인적으로 자주 사용하는 Spring Security Password Encoder 입니다.

MySql 의 password() 펑션 알고리즘 사용합니다.

import java.security.GeneralSecurityException; import java.security.MessageDigest; import org.springframework.security.crypto.password.PasswordEncoder; public class MySqlPasswordEncoder implements PasswordEncoder { @Override public String encode(CharSequence rawPassword) { if (rawPassword == null) { throw new NullPointerException(); } byte[] bpara = new byte[rawPassword.length()]; byte[] rethash; int i; for (i = 0; i < rawPassword.length(); i++) bpara[i] = (byte) (rawPassword.charAt(i) & 0xff); try { MessageDigest sha1er = MessageDigest.getInstance("SHA1"); rethash = sha1er.digest(bpara); // stage1 rethash = sha1er.digest(rethash); // stage2 } catch (GeneralSecurityException e) { throw new RuntimeException(e); } StringBuffer r = new StringBuffer(41); r.append("*"); for (i = 0; i < rethash.length; i++) { String x = Integer.toHexString(rethash[i] & 0xff).toUpperCase(); if (x.length() < 2) r.append("0"); r.append(x); } return r.toString(); } @Override public boolean matches(CharSequence rawPassword, String encodedPassword) { if (encodedPassword == null || rawPassword == null) { return false; } if (!encodedPassword.equals(encode(rawPassword))) { return false; } return true; } }


적용 예시..

	<security:authentication-manager alias="authenticationManager">
		<security:authentication-provider user-service-ref="userService">
			<security:password-encoder ref="passwordEncoder" />
		</security:authentication-provider>
	</security:authentication-manager>

	<bean id="passwordEncoder" class="MySqlPasswordEncoder">


반응형

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

AJAX Login with Spring Security  (7) 2013.12.12
Spring Security Session Destroy  (4) 2013.10.27
//

Using AUTO_INCREMENT keys

Posted at 2011. 3. 1. 16:02 | Posted in Java+/Example
반응형

http://dev.mysql.com/tech-resources/articles/autoincrement-with-connectorj.html

http://static.springsource.org/spring/docs/3.1.0.M1/spring-framework-reference/html/jdbc.html

MySQL 에는 AUTO_INCREMENT(이하 AI)라는 것이 있습니다. 오라클 디비의 시퀀스와 같이 자동으로 값이 증가하게 됩니다.

AI를 적용하려는 칼럼은 기본키K(Primary Key)여야 합니다.



Before JDBC API 3.0

JDBC API 3.0 이전에서는 INSERT 이후에 "select last_insert_id()" 쿼리를 날려서 추가된 AI 값을 가져와야 합니다.

Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; // auto increment value int generatedKey = -1; try { conn = dataSource.getConnection(); // query String sql = "insert into sample_user (name, age) values (?, ?)"; pstmt = conn.prepareStatement(sql); pstmt.setString(1, user.getName()); pstmt.setInt(2, user.getAge()); // execute query pstmt.executeUpdate(); // query sql = "select last_insert_id()"; pstmt = conn.prepareStatement(sql); rs = pstmt.executeQuery(); if(rs.next()) { // auto increment value generatedKey = rs.getInt(1); } return generatedKey; } catch (Exception e) { throw e; } finally { // release rs, pstmt, conn }



After JDBC API 3.0

3.0 부터서는 "getGeneratedKeys()" 메소드를 이용하면 됩니다.

Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; int generatedKey = -1; try { conn = dataSource.getConnection(); // query String sql = "insert into sample_user (name, age) values (?, ?)"; pstmt = conn.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS); pstmt.setString(1, user.getName()); pstmt.setInt(2, user.getAge()); // execute query pstmt.executeUpdate(); rs = pstmt.getGeneratedKeys(); if (rs.next()) { generatedKey = rs.getInt(1); } return generatedKey; } catch (Exception e) { throw e; } finally { // release rs, pstmt, conn; }



Spring + JdbcDaoSupport

스프링과 연동하여 사용할 때에는 KeyHolder 인터페이스를 이용하면 됩니다.

@Override
public int create(User user) throws Exception {
	// query
	String sql = "insert into sample_user (name, age) values (:name, :age)";
	// parameter
	SqlParameterSource paramSource = new BeanPropertySqlParameterSource(user);
	// key holder
	KeyHolder generatedKeyHolder = new GeneratedKeyHolder();
	// execute query
	getNamedParameterJdbcTemplate().update(sql, paramSource, generatedKeyHolder);
	// auto increment
	return generatedKeyHolder.getKey().intValue();
}
※ KeyHolder 기능을 사용하려면 JDBC 드라이버가 JDBC 3.0을 지원해야 합니다.



샘플 소스입니다. (이클립스 Java Project 폴더 통째로 압축했씁니다. Buil Path 설정 해줘야 할지도...)

Spring 3.0 으로 되어있습니다. 간단한 DI만 이용...

kr/nerv/antop/config/spring.xml 파일에서 디비 설정 해줘야합니다.

테스트 클래스는 app.TestUserDao 입니다.

sample_mysql_ai.zip


반응형
//

SELECT 쿼리 연습용 샘플 스키마

Posted at 2009. 12. 22. 18:45 | Posted in Database/MySQL
반응형
Oracle 10g 에 있는 HR, OE, SH, SCOTT 스키마의 데이터들을 MySQL 로 옮겼습니다.

MySQL 5.1.37
InnoDB
utf-8

테이블 이름이 겹쳐서 [스키마]_[테이블] 로 했습니다. ㅠ_ㅠ

주소: nerv-team.co.kr
포트: 3306
아뒤: public
비번: public

SELECT 만 할 수 있구요.. sql 덤프는 [phpMyAdmin SQL Dump] 사용했습니다.

※ 주의! 꼭 OE 보다 HR 을 먼저 IMPORT 시키세요. OE에서 HR_EMPLOYEES 를 참조합니다.



SCOTT(기본 샘플)







HR(Human Resources)







OE(Order Entry)







SH(Sales History)







테이블 정보





반응형

'Database > MySQL' 카테고리의 다른 글

계정 생성  (1) 2009.11.08
//

Apache + PHP + MySQL

Posted at 2009. 11. 11. 08:20 | Posted in Server/Ubuntu
반응형

#  apt-get install mysql-server

utf-8, innodb 설정

# vi /etc/mysql/my.cnf

# utf-8
[client]
default-character-set=utf8  

[mysqld]   
character-set-client-handshake=FALSE  
init_connect="SET collation_connection=utf8_general_ci"  
init_connect="SET NAMES utf8"  
default-character-set=utf8  
character-set-server=utf8  
collation-server=utf8_general_ci  

# InnoDB
default-storage-engine=INNODB

# 테이블명의 대소문자를 가리지 않게 한다.
lower_case_table_names = 1

[mysqldump]    
default-character-set=utf8

[mysql]   
default-character-set=utf8

# 외부에서도 접속 가능하게 한다.
# bind-address          = 127.0.0.1

mysql 재시작

# /etc/init.d/mysql restart

설정 확인

# mysql -uroot -p비밀번호
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 35
Server version: 5.1.37-1ubuntu5 (Ubuntu)
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> status
--------------
mysql  Ver 14.14 Distrib 5.1.37, for debian-linux-gnu (i486) using  EditLine wrapper

Connection id:          35
SSL:                    Not in use
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server version:         5.1.37-1ubuntu5 (Ubuntu)
Protocol version:       10
Connection:             Localhost via UNIX socket
Client characterset:    utf8
Server characterset:    utf8
UNIX socket:            /var/run/mysqld/mysqld.sock
Uptime:                 1 min 59 sec

Threads: 1  Questions: 102  Slow queries: 0  Opens: 99  Flush tables: 1  Open tables: 23  ....
--------------

mysql> show engines;
| InnoDB     | DEFAULT | Supports transactions, row-level locking, and foreign keys ....

mysql> exit
Bye



apache2

# apt-get install apache2
# apt-get install libapache2-mod-auth-mysql

ServerName 등록

# vi /etc/apache2/apache2.conf

# ServerName
ServerName nerv-team.co.kr

가상 호스트 설정

#  vi /etc/apache2/sites-enabled/000-default

# nerv-team.co.kr
<VirtualHost *:80>
        ServerName nerv-team.co.kr
        Redirect / http://www.nerv-team.co.kr/
</VirtualHost>
# www.nerv-team.co.kr
<VirtualHost *:80>
        ServerAdmin antop@nerv-team.co.kr
        ServerName www.nerv-team.co.kr
        ServerAlias nerv-team.co.kr
        DocumentRoot /var/www
        ....
</VirtualHost>

http://nerv-team.co.kr 으로 접속해도 http://www.nerv-team.co.kr 으로 갈 수 있도록 수정


apache2 재시작

# /etc/init.d/apache2 restart

테스트





php5

# apt-get install php5
# apt-get install php5-gd php5-imap
# apt-get install php5-mhash
# apt-get install php5-mysql
# apt-get install php5-pgsql

설정

# vi /etc/php5/apache2/php.ini

; 추가
date.timezone = Asia/Seoul
[PHP]
default_charset = "UTF-8"
output_buffering = 4096

....

; 수정
magic_quotes_gpc = Off

apache2 재시작

# /etc/init.d/apache2 restart

테스트

# echo '<?php phpinfo(); ?>' > /var/www/phpinfo.php





phpmyadmin

# apt-get install phpmyadmin

apache2 선택



기본 http://www.nerv-team.co.kr/phpmyadmin 으로 되어 있지만 http://mysql.nerv-team.co.kr 으로 변경

# rm /etc/apache2/conf.d/phpmyadmin.conf

서브 도메인 설정

# vi /etc/apache2/sites-enabled/000-default

# 추가
# mysql.nerv-team.co.kr
<VirtualHost *:80>
        ServerName mysql.nerv-team.co.kr
        DocumentRoot /usr/share/phpmyadmin
</VirtualHost>

apache2 재시작

# /etc/init.d/apache2 restart

테스트



반응형

'Server > Ubuntu' 카테고리의 다른 글

Openfire  (0) 2010.05.25
Webmin  (0) 2009.11.18
Squirrelmail  (0) 2009.11.12
SparkWeb  (0) 2009.11.12
Cacti  (0) 2009.11.12
Apache + SSL  (0) 2009.11.12
Oracle Express Edition 10g  (0) 2009.11.11
Apache + Tomcat with Tomcat Connector  (0) 2009.11.11
bind9 - domain name service  (0) 2009.11.11
Ubuntu 9.10 Desktop  (0) 2009.11.11
//

계정 생성

Posted at 2009. 11. 8. 23:11 | Posted in Database/MySQL
반응형
- 관리자 로그인
$ mysql -uroot -p비밀번호 mysql

- 계정 생성
mysql> insert into user ( host, user, password ) values ( 'localhost', '사용자명', password('패스워드') );

- 데이터베이스 생성
mysql> create database 디비명;

- 데이터베이스 권한 주기
mysql> insert into db ( host, db, user, select_priv, insert_priv, update_priv, delete_priv, create_priv, alter_priv, drop_priv) values ( 'localhost', '디비명', '사용자명', 'y', 'y', 'y', 'y', 'y', 'y', 'y' );

- 새로 적용
mysql> flush privileges;

반응형

'Database > MySQL' 카테고리의 다른 글

SELECT 쿼리 연습용 샘플 스키마  (1) 2009.12.22
//