11월, 2017의 게시물 표시

(스프링) JoinPoint의 사용

AOP관련해서 JoinPoint를 파라미터로 전달받을 경우 반드시 첫번째 파라미터로 지정해야 함 (그 외는 예외 발생) JoinPoint 인터페이스는 호출되는 대상 객체, 메소드 그리고 전달되는 파라미터 목록에 접근할 수 있는 메소드를 제공 Signature getSignature() - 호출되는 메소드에 대한 정보를 구함 Object getTarget() - 대상 객체를 구함 Object[] getArgs() - 파라미터 목록을 구함 org.aspectj.lang.Signature 인터페이스는 호출되는 메소드와 관련된 정보를 제공하기 위해 다음과 같은 메소드를 정의 1. String getName() - 메소드의 이름을 구함 2. String toLongname() - 메소드를 완전하게 표현한 문장을 구함(메소드의 리턴타입, 파라미터 타입 모두 표시) 3. String toShortname() - 메소드를 축약해서 표현한 문장을 구함(메소드의 이름만 구함)

(스칼라) 함수

* 왜 함수형 언어인가? 함수형 프로그래밍인 스칼라에서는 함수 자체를 전달하고 반환받을 수 있습니다. 자바에서의 함수는 함수 객체가 아니라 클래스에 속한 메소드입니다. 스칼라에서 함수는 필요하다면 언제든지 => 로 표현되는 식을 통해 객체처럼 행동할 수 있습니다. 스칼라의 정의는 scalable에서 왓으며 확장이 쉽다는 이야기이다 즉, 잘 사용한다면 아주 동시성이 강한 언어이다. 1. 함수 정의 def 함수명 ([매개변수]): [반환자료형] {   //구현할 로직 } 스칼라에서는 반환값이 없을 때 생략이 가능하다. object class Ex_5_1 {   def main(args:Array[String]) = {     println("반환받은 값 : " + name());   }   def name() = {     var a = 10    a   } } 위의 def함수는 반환형을 명시적으로 쓰지 않아도 반환합니다. 명시적으로 반환형을 명시 할 수 있습니다. def name() : Int = {   val a = 10   return a; } 이렇게하면 Int형이 아닌 다른 자료형을 반환하려 한다면 컴파일 에러가 납니다. <Call-By-Name 함수> 보통 함수는 두 가지 형태로 호출할 수 있습니다. CALL-BY_VALUE (값으로 호출), CALL-BY-NAME(이름으로 호출) CALL-BY-VALUE는 그동안 많이 봐왔던 형식입니다. 예를들어, a(b(x))처럼 중첩된 형태로 함수를 호출하면 안쪽의 함수 b가 반환하는 값이 다시 a에 들어가는 식으로 집어넣어지는 식으로 코드가 동작합니다. CALL-BY-NAME은 b자체가 a의 인수로 들어간다고 생각하면 됩니다. b를 거쳐 나온 값이 아닌, b라는 함수 자체를 매개변수로 인정하는 것입니다. 예) dropship(people(5)) 인 것이 존재할 때, people

(스칼라) 클래스/객체/트레이트

1. 클래스와 객체

(스칼라) 조건문과 반복문

* for 문 for ( x <- 1 to 10) { println(x) } 또는 for ( x <- 1 until 10) { println(x) } to는 10을 포함하고 until은 포함하지 않는다. * 이중포문 for ( x <- 1 until 10; y <- 1 until 10) { println(x) } * 인덱스가 있는 for 문 for( (num, index) <- List.zipWithIndex) { println(num) println(index) } List의 zipWithIndex메소드를 이용해 인덱스를 표현 할 수 있따.

(스칼라) 변수선언

* 변수사용은 아주 간단하다. var a = "변수입니다." val b = " final 변수입니다." 이 두가지가 전부이다. var 은 일반적인 변수이며 변수의 내용이 언제든 바뀔 수 있따. val 은 final 변수이다. 그럼 왜 잘 사용하지 않는 final 을 val을 만들어 가면서까지 만들었을 까요? -> 스칼라는 함수형 언어프로그래밍언어로써 변수 뿐만 아니라 함수까지 집어넣을 수 있다. 그래서 그 안에 담길수 있는 범위가 굉장히 넓다. 범위가 넓다보니 확정지어줘야 하기 때문이다. 또한 스칼라언어는 변수를 초기화 해주어야 한다. 그이유는 컴파일시 어떤 자료형인지 알아야 하기 때문이다. 만약 초기화가 필요없다면 var a = null; 또는 var a = None; 로 설정 해준다. 또한 자료형을 명시적으로 적어 해당 자료형만 넣도록 하는 것이 가능하다. var b : Int = 10 <기본 자료형과 참조자료형> AnyVal -> Byte , Short , Int, Long, Char, Unit, Boolean, AnyRef -> 사용자가 만든 객체, AnyVal이 아닌 객체 * 기본 자료형은 생략 <type 예약어를 이용해 자료형을 별칭화 하기> type 예약어는 자료형이 길고 복잡할 경우 별칭을 주어 쉽게 쓸 수 있습니다. type Name = String type Person = (String, Int) type FType = String => Int// 함수표현식. 첫번째 자료형은 String 두번째 자료형은 (String, Int) 세번쨰는 String 을 받고 Int 를 반환하는 형식입니다. val name: Name = "김말자"; val person: Person = ("김동욱", 24); val f: fType = text =

(스칼라) 모든것은 객체이다.

* 자바는 클래스로 선언되지만, 스칼라는 객체선언으로 시작됩니다. 스칼라에서 객체는 자바로치면 static class 형식으로서 , new 를 통해 인스턴스를 생성하는 것이 아니라 처음부터 단 하나의 인스턴스만 생성가능하느 싱글턴 객체입니다. 싱글턴객체는 여러 인스턴스를 생성하지 못하고, 단 하나의 인스턴스만 생성해야 합니다. * 함수가 다르다. 함수는 def로 정의할 수 있습니다. Unit은 자바의 void 라고 보면된다. 명시적으로 아무것도 반환하지 않음을 나타낸다. 예) object Ex1_1 {   def main(args: Array[String] ): Unit = {   println("핼로 스칼라~"); } }

(스칼라) 스칼라란?

* 스칼라 코드는 짧으며 직관적이다. val otherList = list.filter( i => i>=5); * 스칼라에는 다양한 연산자가 존재한다. 이 연산자들은 모두 하나하나 메소드로 되어있다. 예를들어 , 리스트에는 ++라는 메소드가있따 list1 ++ list2 는 리스트1과 리스트2를 합친결과이다. 이렇게 연산자들이 직관적으로 구현되어있고, 띄어쓰기를 통해 깔끔하게 표현가능하기 때문에 스칼라의 유연성과 가독성은 상당히 높은 수준이다. * 동시성에 강한 언어. 동시성이 뛰어난 라이브러리 아카(akka)가 있따. 아카는 동시성이 뛰어난 액터모델로 이루어져있다. 액터모델이란, 각각의 액터가 서로 간의 메시지를 통해서만 의사소통을 하고 액터를 이루는 변수나 속성은 서로 공유하지 않는 것이다. * 객체지향 + 함수형 언어 스칼라에서는 모든 것이 객체이다. 함수의 매개변수에 함수객체를 집어넣을 수도있고, 변수에 함수를 할당할 수도 있따. Member.members.filter(_userId === 'admin').delete * 맥락을 읽는 언어 자바같은 경우는 자료형 하나하나 명시적으로 지정하고 매개변수를 써야하지만, 스칼라는 필요할 때 implicit 예약어 를 사용하면 명시적인 표현을 감춰버릴 수 있습니다. * 자바와 뛰어난 연계성 자바의 라이브러리를 언제든지 import해서 사용할 수 있습니다. 또한 JVM을 사용합니다.

(Hibernate) 영속성 컨텍스트란?

이미지
1. 엔티티의 생명주기 비영속 : 영속성 컨텍스트와 전혀 관계가 없는 상태 영속 : 영속성 컨텍스트에 저장된 상태 준영속 : 영속성 컨텍스트에 저장되었다가 분리된 상태 삭제 : 삭제된 상태 * 비영속 엔티티 객체를 생성했다. 순수한 객체 상태이며 아직 저장하지 않았다. 따라서 영속성 컨텍스트나 데이터베이스와는 전혀 관련이 없다. 이것을 비영속 상태라한다. 예) Member member = new Member(); member.setId("member1"); member.setUsername("회원1"); * 영속 엔티티매니저를 통해 엔티티를 영속성 컨텍스트에 저장했다. 이렇게 영속성 컨텍스트가 관리하는 엔티티를 영속 상태라 한다. 이제 회원엔티티는 비영속상태에서 영속상태가 되었다. 결국 영속 상태라는 것은 영속성 컨텍스트에 의해 관리된다는 뜻이다. 그리고 em.find()나 JPQL 을 사용해서 조회한 엔티티도 영속성 컨텍스트가 관리하는 영속상태이다. em.persist(member); * 준영속 영속 컨텍스트가 관리하던 영속 상태의 엔티티를 영속성 컨텍스트가 관리하지 않으면 준영속 상태가 된다. em.detach()나 em.close()나 em.clear()를 호출하면된다. em.detach(member); em.remove(member); <영속성 컨텍스트의 특징> 1. 영속성 컨텍스트와 식별자 값 엔티티를 식별자 값(@Id로 테이블의 기본키와 매핑한 값) 으로 구분한다.  따라서 영속상태는 식별자 값이 반드시 있어야 한다. 없으면 예외가 발생한다. 2. 영속성 컨텍스트와 데이터베이스 저장 영속성 컨텍스트에 엔티티를 저장하면 이 엔티티는 언제 데이터베이스에 저장될까? JPA는 보통 트랜잭션을 커밋하는 순간 영속성 컨텍스트에 새로 저장된 엔티티를 데이터베이스에 반영하는데 이것을 플러시(flush)라

(git) 고급 명령어

* git commit --amend : 같은 브랜치 상에 있는 최종 커밋을 취소하고 새로운내용을 추가하거나 설명을 덧붙인 커밋을 할 수 있다. * git revert  : 이전에 작성한 커밋을 지웁니다. 그런데 특정 커밋의 내용을 지우는 새로운 커밋을 만들어 지운 내역을 모든 사람이 알 수 있게 합니다. * git reset : 어떤 커밋을 버리고 이전의 특정 버전으로 다시 되돌릴 때 사용합니다. git revert와 다른 점은 지운 커밋 내역을 남기지 않는 다는 점이다. 참고 : git add 한 내용을 모두 취소하기 위해서는 git checkout .    하면된다. * git checkout HEAD --filename 아직 커밋하지 않은 변경 내역을 취소한다. * git rebase : git merge처럼 병합할 때 사용한다. 하지만 브랜치가 많을 경우 브랜치 이력을 확인하면서 병합한다. * git rebase -i : 서로 다른 두 개의 커밋내역을 합친다.

(성능개선) MongoDB query (when choosing 11 list in each data for just one query)

* 몽고 디비 쿼리작업 db.getCollection('guestbookReply').aggregate([  {"$sort" : {regDt : 1}},  {"$match": {guestbookId : {"$in" :[ObjectId("58f6c9d49a72b291f14afe04"), ObjectId("58fde40e9a72b5cd0c88ae6e"),ObjectId("593fbb103b8baa7d5b6921c7")      ,ObjectId("593fbb663b8bc590ac3f4799")]}}  },  {"$group" : {   "_id":"$guestbookId",   "GuestBookReply":{"$push" : "$$ROOT"}},  },  {"$project" : {      "GuestBookReply" : {"$slice" : ["$GuestBookReply",10]}      }} ]); ====================================================== db.getCollection('guestbookReply').aggregate([ //{"$sort" : {regDt : 1}},  {"$match": {guestbookId : {"$in" :[ObjectId("58f6c9d49a72b291f14afe04"), ObjectId("58fde40e9a72b5cd0c88ae6e"),ObjectId("593fbb103b8baa7d5b6921c7")

(Scala) tratit

* 자바언어의 Interface에 해당하는 녀석이다. 이를 이용해 코드의 재사용을 극대화 할 수 있다. 클래스의 상속관계와는 다르게 여러 trait를 섞어 사용할 수 있다. 여기서 섞어서 사용한다는 것이 중요하다. Java언어의 interface 는 이 interface를 상속받는 클래스들의 뼈대를 제공해 주지만 정작 메소드 구현은 interface를 상속받는 클라이언트 클래스를 구현하는 개발자가 전부 구현해야 한다. 하지만 Scala언어에서의 trait은 이와 다르게 구체적인 함수가 구현되어 있어서 이를 사용하는 개발자는 특별히 mix(섞어서) 함수를 구현하지 않고 바로 사용할 수 있다는 장점이 있다. trait philosophical {  def philosophize() {    println("블라블라")   } } 다른 클래스에서 이 trait을 mix 해서 사용하는 방법은 아래와 같다. class Frog extends philosophical {  override def toString = "Green"; } 여러개의 trait를 사용하는 방법은 다음과 같다. class Frog extends Animal with philosophical with HashLeg {    override def toString = "Green"; } with를 사용하면 된다.

ddd

db.getCollection('guestbookReply').aggregate([  {"$sort" : {regDt : 1}},  {"$match": {guestbookId : {"$in" :[ObjectId("58f6c9d49a72b291f14afe04"), ObjectId("58fde40e9a72b5cd0c88ae6e"),ObjectId("593fbb103b8baa7d5b6921c7")      ,ObjectId("593fbb663b8bc590ac3f4799")]}}  },  {"$group" : {   "_id":"$guestbookId",   "GuestBookReply":{"$push" : "$$ROOT"}},  },  {"$project" : {      "GuestBookReply" : {"$slice" : ["$GuestBookReply",10]}      }} ]);

(Java8) 리듀싱(Reduce)

1. 요소의 합 int sum = numbers.stream().reduce(0, (a, b) -> a + b); int  product = numbers.stream().reduce(1, (a,b) -> a * b); * 초기값 없음 Optional<Integer> sum = numbers.stream().reduce((a, b) -> a+ b); 2. 최댓값과 최솟값 Optional<Integer> max = numbers.stream().max(Integer::max); Optional<Integer> min = numbers.stream().min(Integer::min); Q) 스트림의 요리갯수를 계산하시오. 스트림의 각 요소를 1로 매핑한 다음 reduce로 이들의 합을 계산하는 방식으로 문제를 해결할 수 있다. int count = menu.stream() .map(d -> 1) .reduce(0, (a, b) -> a +b);

(자바8) findFirst와 findAny

* findFirst와 findAny  는 언제 사용하나? 왜 두 메소드가 존재할까? 바로 병렬성 때문이다. 병렬 실행에서는 첫 번째 요소를 찾기 어렵다. 따라서 요소의 반환 순서가 상관없다면 병렬스트림에서는 제약이 적은 findAny를 사용한다.

(Maven) Maven 컴파일러 버전 설정

Maven 의 기본 라이프사이클에서 complie시기에 실행되는 complier 플러그인은 별도 설정이 없을 경우, 자바 1.3버전 기준으로 컴파일할 소스 코드를 파싱하고 자바 1.1 버전에 호환되도록 클래스 파일을 생성한다. 따라서, 제너릭이나 어노테이션과 같이 자바 5이상 버전에서만 유효한 문법이 코드에 포함되어 있을 경우 컴파일 과정에서 문법 에러가 발생하게 된다. <maven-compiler-plugin 설정하기> 메이븐이 기본적으로 사용하는 소스 및 생성 클래스의 자바 버전을 변경하려면 pom.xml파일에서 maven-compiler-plugin의 <configuration> 영역에서 <source> 와 <target> 을 이용해서 소스 코드 및 생성 대상 자바 버전을 지정할 수 있다. 아래코드는 예를 보여준다. <project> <build>  <plugins>   <plugin>    <groupId>org.apache.maven.plugins</groupId>    <artifactId>maven-compiler-plugin</artifactId>    <configuration>     <source>1.8</source>     <target>1.8</target>     <encoding>UTF-8</encoding>   </configuration> </plugin>  </plugins> </build> </project>

(JPA) 엔티티매핑

@Entity 클래스에 @Entity를 붙여주면 JPA가 엔티티로서 관리한다는 것을 의미한다. 속성 name : 다른 Entity와 충돌이 우려될 경우 이름을 붙여준다. 기본적으로 class명을 따른다. 주의사항 기본생성자 필수 final, enum, interface, inner 클래스에 사용못함. 저장필드에 final 필드 사용못함. @Table Entity와 매핑할 DB테이블을 지정한다. 속성 name : 매핑할 table이름, 기본은 Entity 이름을 사용한다. catalog : catalog 기능이 있는 DB에서 catalog를 매핑 schema : schema 기능이 있는 DB에서 schema 를 매핑 uniqueConstraints : DDL 생성 시에 유니크 제약조건을 만든다. <데이터베이스 스키마 자동생성> 자동으로 스키마를 생성하는 기능은 아래 값을 설정 함으로써 가능하다. <property name="hibernate.hbm2ddl.auto" auto="create"> create : 기존 Table Drop + 생성 create-drop : create후 종료시 drop 까지 실행 update : 변경된 내용만 수정한다. 이건 JPA 스팩에는 없고, 하이버네이트에만 있는 설정이다. validate : 기존 DB Table정보와 비교해서 차이가있다면 경고하고 애플리케이션을실행하지 않는다.(하이버네이트에만 있는 설정) none : 설정이 없거나 유효하지 않은 값을 설정하면 기능을 사용하지 않게 된다.

(MongoDB) MongoDB의 $group 사용법

$group 에서 _Id 필드는 유니크 키로 사용되며 distinct값으로 사용된다. _Id 필드는 의무적이다. * $push 는 각 표현의 값을 배열형식으로 집어넣는다.(각각의 키에 해당하는 document에 따라) 예제) sales라는 collection이 주어졌을 때, { "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-03-01T08:00:00Z") } { "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-03-01T09:00:00Z") } { "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-03-15T09:00:00Z") } { "_id" : 4, "item" : "xyz", "price" : 5, "quantity" : 20, "date" : ISODate("2014-04-04T11:21:39.736Z") } { "_id" : 5, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate

(MongoDB) MongoDB 의 시스템 변수(System Variables)

System Variables MongoDB offers the following system variables: Variable Description ROOT References the root document, i.e. the top-level document, currently being processed in the aggregation pipeline stage. CURRENT References the start of the field path being processed in the aggregation pipeline stage. Unless documented otherwise, all stages start with  CURRENT  the same as  ROOT . CURRENT  is modifiable. However, since  $<field>  is equivalent to  $$CURRENT.<field> , rebinding  CURRENT  changes the meaning of  $  accesses. DESCEND One of the allowed results of a  $redact  expression. PRUNE One of the allowed results of a  $redact  expression. KEEP One of the allowed results of a  $redact  expression.

AtomicInteger

요약 : 원자적 연산이란, 여러 스레드들이 병렬적으로 수행되어도 안전성을 보장받을 수 있는 것을 의미한다. 이러한 원자적 연산은 하드웨어적으로 접근해야지만 안전성을 보장받는다. 이러한 원자적 연산을 도와줄 수 있는 것이 AtomicInteger가 한 예이다. * 원자적 연산을 수행할 수 있는 유용한 클래스이다. Lock이나 synchronized 키워드 없이도 여러 스레드들에 의해 병렬적으로 수행되어도 결과의 안전성을 보장받을 수 있다면 그 연산은 원자적이라고 한다. 내부적으로 원자적 클래스들은 CAS(compare-and-swap)십분 활용한다. 간단히 설명하자면, 값을 변경할 때 자신이 읽었던 변수의 값을 기억하고 있다가 변경 직전에 변경직전에 변수의 메모리 내의 값을 확인하여 이전에 기억해 놓은 값과 같은 경우에만 처리를 진행하고 그렇지 않은 경우는 무산시키는 방식이다. 이러한 명령은 현대적 CPU에 의해 직접적으로 지원된다.(하드웨어적으로) 그래야 원자적 연산이 가능하다. 하드웨어 지원없이 완벽한 원자적 연산을 지원하는 것이 불가능하다. 따라서 요새는 CPU차원에서(하드웨어 차원에서) 이러한 연산을 지원하므로 특정 변수에 여러 스레드들이 동시에 접근하여 작업하는 경우가 있는 경우 이러한 원자적 연산을 이용하는 클래스를 이용하는 것이 권장된다. 예) AtomicInteger atomInt = new AtomicInteger(0); ExecutorService executor = Executors.newFixedThreadPool(2); IntStream.range(0, 1000) .forEach(i -> executor.submit(atomInt::incrementAndGet)); stop(executor) System.out.println(atomInt.get(0);  ----> 1000 =====> Integer대신 AtomicInteger를 사용했을 뿐이다. Integer는