^^; 예전에

글을 열심히 썼었는데...

ㅠㅠ 다날라갔다 다시 정리하는겸

써야지~

jpa공부해보니 꼭 실제 업무할때 써보고싶었다

그래야 더 잘 느낄 수 있을거 같다.

 

 


1. JPA 란 ? ( 그외 개념들)

JPA (Java Persistence API) : 자바 어플리케이션에서 관계형 데이터 베이스를 사용하는 방식을 정의한 인터페이스

 

JPA가 인터페이스면 이를 구현한 것도 있지 않을까?

그게바로 Hibernate이다.

 

Hibernate : JPA라는 명세의 구현체이다.

 

쉽게 설명하자면, JPA와 Hibernate는 자바의 interface와 interface를 구현한 class와 같은 관계이다.

즉, 반드시 Hibernate를 쓸 필요는 없다. 그런데 대부분 사용하고 있긴하다.

 

 

Spring Data JPA : JPA를 더 쉽고 편하게 사용할 수 있도록 도와주는 모듈이다. 

JPA를 한단계 추상화시킨 Repository라는 인터페이스를 제공한다.

 

대부분 개발할때 Repository를 이용한다,,

 

 

2. JPA를 왜 쓸까?

jpa는 DB와 객체사이를 mapping해주는 중간자 역할을 해준다.

그래서 기존에 jdbc를 쓸때 쿼리를 이용해서 data에 접근하였었는데 

쿼리를 이용하지 않고, 개발할 때 객체지향적인 관점에서만 접근하게 해준다. 그래서 더 효용이 좋다.

 

 

그런데 여기서  쿼리만 써본 사람들은 의문이 들 것이다.

현재 운영되고 있는 복잡한 쿼리들을 어떻게 JPA로 대체할 수 있을까?

나도 이거에 대한 의문점이 있었는데

 

우선, 간단한 조인 같은건 Querydsl로 적용이 가능하다.

 

그리고 애초에 DB설계자체를 객체지향적으로 하면 

애초에 그렇게 복잡한 쿼리가 나오지 않을 거란 설명이 설득력 있었다.

 

아래 참고 블로그에서 특히 JPA를 왜 쓰는지에 대해서 자세히 나와 있었는데

그중 와닿는 말은 다음과 같다.

 

 

JPA로 실무를 하다 보면, 테이블 중심에서 객체 중심으로 개발 패러다임이 변화된다.

테스트, 통합 테스트시에 CRUD를 믿고 간다.(내가 짠 쿼리는 그것 마저 테스트를 거쳐 가야 한다.)
- 이런거 테스트 할 시간에 CRUD 믿고, 핵심 비즈니스 테스트 코드를 열심히 짜자.


빠르게 에러를 발견할 수 있다.
- 컴파일 시점에 대부분 오류를 발견할 수 있다
-최소한 뭐리 문법 실수나 오류는 거의 발생하지 않는다.



 

https://ict-nroo.tistory.com/117

 

다음 블로그에 자세히 나와있으니 읽어보는 것을 추천한다.

 

 

그리고 실제로도 나도 간단한 개발을 해보았는데 혼자서..

쿼리를 짤때 자잘한 문법오류나 매핑해주는 데에서 오타가 나서 

오류가 나거나 하는 사소한 실수를 전혀 신경쓰지 않아도 되어서 좋았다.

 

 

 


https://suhwan.dev/2019/02/24/jpa-vs-hibernate-vs-spring-data-jpa/

 

JPA, Hibernate, 그리고 Spring Data JPA의 차이점

개요 Spring 프레임워크는 어플리케이션을 개발할 때 필요한 수많은 강력하고 편리한 기능을 제공해준다. 하지만 많은 기술이 존재하는 만큼 Spring 프레임워크를 처음 사용하는 사람이 Spring 프레�

suhwan.dev

https://ict-nroo.tistory.com/117

REST API를 만들면 Swagger를 상당히 많이 사용한다.

그래서 Django 에서도 Swagger를 적용해보고자 한다.

 

그런데.. 하다보니 안되는 부분들을 발견해서 (버전이슈..)

포스팅해본다 ^^;

 

결론부터 말하자면,

django_rest_swagger를 쓰지말고 , drf-yasg를 쓰는 것을 추천한다

 

 

 

처음에 djnago-rest_swagger를 설치 후 , settings.py에 추가하고 

기동하면 

  • AttributeError at /api/docs/ -> 'AutoSchema' object has no attribute 'get_link'

다음과 같은 오류가 난다..

https://github.com/encode/django-rest-framework/issues/6809 

 

해당 글을 참조해서.. settings.py에 다음을 추가하면.. (저글에선 이걸 추가하면 된다는글이 대부분이다 ㅠ)

	REST_FRAMEWORK = {
	...
	'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema'
	}

 

But,,,

  • django_rest_swagger - 'staticfiles' is not a registered tag library. Must be one of:

다음 오류가 발생,,,, 다시 구글링..

https://stackoverflow.com/questions/59230539/django-rest-swagger-staticfiles-is-not-a-registered-tag-library-must-be-one

The problem is that staticfiles template tag was deprecated in Django 2.2 and is finally removed in Django 3.0

The djagno-rest-swagger package itself is deprecated and is no longer maintained.

Their GitHub repo recommends something like drf-yasg

 

해당글을 보면, staticfiles 템플릿을 Django3.0버전에서 삭제했고, 

django-rest-swagger 패키지는 더이상 관리안한다고한다,,,

그래서 django-rest-swagger GitHub에서도 drf-yasg를 쓰도록 추천한다고 ^^;

 

여러분들~~ 그냥 속편하게 drf-wasg 쓰세염 ^_^

 

 

https://github.com/axnsan12/drf-yasg

을 참조해서 쓰면된닷

 

 

 

1. drf-yasg 설치

pip install -U drf-yasg

 

 

 

2. settings.py 설정

INSTALLED_APPS = [
   ...
   'drf_yasg',
   ...
]

 

 

 

 

3.urls.py 적용

from django.contrib import admin
from django.urls import path, include
from django.conf.urls import url
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi

schema_url_patterns = [
  path('api/', include('test.urls')),
]
schema_view = get_schema_view(
  openapi.Info(
    title="Django API",
    default_version='v1',
    terms_of_service="https://www.google.com/policies/terms/",
  ),
  public=True,
  permission_classes=(permissions.AllowAny,),
  patterns=schema_url_patterns,
)

urlpatterns = [
  path('admin/', admin.site.urls),
  path('api/', include('test.urls')),
  url(r'^swagger(?P<format>\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'),
  url(r'^swagger/$', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
  url(r'^redoc/$', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
]



 

 

그러고 기동한뒤 

http://localhost:8000/swagger로 접속하면 잘뜬다

그리고 http://localhost:8000/redoc으로도 접속하면 뜬다.

 

그럼 이만

 

 

'DEVELOP > Backend' 카테고리의 다른 글

Spring Security 에서 OAuth 2.0이란?  (0) 2020.05.18
JPA이란? (전체적인 개념, 느낀점)  (0) 2020.05.18
Django CORS 설정하기  (0) 2020.03.26
python pip Proxy 설정하기  (0) 2020.03.24
Django 시작하기 [3] Django MVC 패턴  (0) 2020.03.18

Django 로 REST Api 를 만들었는데

Front 단이랑 연결을 해야할때 

CORS 오류가 난다.

 

CORS란? (Crosss-Origin Resource Sharing)

웹 페이지 상의 제한된 리소스를 최초 자원이 서비스된 도메인 밖의 다른 도메인으로부터 요청할 수 있게 허용하는 구조이다.

 

 

그럼 Django 에서 CORS 처리를 해보자.

 

 

1. django-cors-headers 설치

 

pip install django-cors-headers

 

 

2. settings.py 에 설정 추가

 

INSTALLED_APPS =[
...

'corsheaders', # CORS 관련 추가

]
...

MIDDLEWARE = [

	'corsheaders.middleware.CorsMiddleware',     # CORS 관련 추가
...  
]
...

# CORS 관련 추가
CORS_ORIGIN_WHITELIST = ['http://127.0.0.1:3000'
                         ,'http://localhost:3000']
CORS_ALLOW_CREDENTIALS = True

 

MIDDLEWARE에 CorsMiddleware를 최상단에 기입해준다.

 

CORS_ORIGIN_WHITELIST에 연동할 ip와 포트를 적어준다.

ip와 포트를 적을때 안될때가 있었는데 다음 포스팅을보고 안전하게 두개를 적어 주었다..

 

https://github.com/adamchainz/django-cors-headers/issues/403

 

 

간단쓰하당 ㅎㅎ

역시 모든건 알면 간단하다..

proxy가 있는 환경에서 python pip 를 사용할때 

어떻게 해야할까 ㅎㅎ

 

아주 간단쓰 하당

 

 

 

 

1. 명령어에서 설정 추가 

>> pip config set global.proxy [proxy ip : proxy port]

 

 

 

2. 설정 파일에서 직접 수정 

C:\Users\AppData\Roaming\pip\pip.ini 파일에서 다음추가 

[global]

proxy = [proxy ip : proxy port]

 

 

3. pip 명령어 수행 할 때마다 proxy 옵션 추가

예시

 

>> pip install --proxy [proxy ip : proxy port] django

 

>> pip install --proxy [proxy ip : proxy port] djangorestframework

 

 

 

 

사실 3번은 넘나 귀찮은 일이고 

1번이나 2번으로 한번 설정해서

쓰면 아주 편할일~ ㅎㅎ

 

 

 

 

 

 

 

 

 

 

 

Django MVC 패턴


Django 도 MVC (Model View Controller) 의 패턴을 따른다.


Model : models.py
View : template (index.html)

Controller : views.py

 

동작 순서는 다음과 같다.

 

mysite/urls.py로 가서 해당 urlpattern 본다. 

우리는 여기서 http://localhost:8000/polls를 호출 했으니, 

 

mysite/urls.py

from django.contrib import admin
from django.urls import path , include

urlpatterns = [
    path('polls/' , include('polls.urls')),
    path('admin/', admin.site.urls),
]

 

해당 url을 따라서 polls/urls.py를 따라간다.

 

polls/urls.py

from django.urls import path

from . import views
app_name = 'polls'
urlpatterns =[
  path('', views.IndexView.as_view(), name='index'),
  path('/', views.DetailView.as_view(), name='detail'),
  path('/results/', views.ResultsView.as_view(), name='results'),
  path('/vote/', views.vote, name='vote'),
 ]

 

여기에서 http://locahost:8000/polls 를 호출했으니 indexView를 따라간다.

 

polls/views.py

class IndexView(generic.ListView):
  template_name = 'polls/index.html'
  context_object_name = 'latest_question_list'

  def get_queryset(self):
    """Return the last five published questions."""
    return Question.objects.order_by('-pub_date')[:5]


class DetailView(generic.DetailView):
  model = Question
  template_name = 'polls/detail.html'


class ResultsView(generic.DetailView):
  model = Question
  template_name = 'polls/results.html'


def vote(request, question_id):
  question = get_object_or_404(Question, pk=question_id)
  try:
    selected_choice = question.choice_set.get(pk=request.POST['choice'])
  except (KeyError, Choice.DoesNotExist):

    return render(request, 'polls/detail.html', {
      'question': question,
      'error_message': "You didn't select a choice.",
    })
  else:
    selected_choice.votes += 1
    selected_choice.save()
    return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

 

여기서 index.html을 호출 해서 화면을 보여준다.

 

polls/templates/polls/index.html

 

{% if latest_question_list %}
<ul>
          {% for question in latest_question_list %}
<li><a href ={% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
          {% endfor %}

</ul>

{% else %}

No polls are available.


{% endif %}

 

이런식으로 구동되고,

위에 붙인 소스가 주요 코드이다.

 

 

 

ㅎㅎ mvc 패턴은 생각보다 익숙하지만

python 문법이나 django 모두 생소해서

어려운 부분이 많은것 같다..

그리고 python은 주로 backend로 난 이용할것 같은데.. front보다는

그부분에 대해서 어떻게 구현할지를 더 고민해보아야겠다..

 

그리고 깊이를 익히기 위해선 책을 한권 빌려서 보는게 빠를것 같다 

튜토리얼은 그래도 한번 가볍게 따라하기 좋은것 같다 역시

 

 


참고

https://docs.djangoproject.com/ko/3.0/intro/tutorial03/

 

첫 번째 장고 앱 작성하기, part 3 | Django 문서 | Django

Django The web framework for perfectionists with deadlines. Overview Download Documentation News Community Code Issues About ♥ Donate

docs.djangoproject.com

 

ㅎㅎ 저번 포스팅에 Django 프로젝트까지 생성해 보았다.

그다음 만든 프로젝트를 구동해보자

 

 

1. 앱 만들기

 

이제 앱을 만들어보자ㅏ

>>python manage.py startapp polls

 

 

그런데, 여기서 잠깐

프로젝트와 앱이 뭐가다를까?

 

앱은 웹 로그 시스템, 공개 레코드 데이터베이스 또는 소규모 설문 조사 앱과 같은 작업을 수행하는 웹 애플리케이션

 

프로젝트는 특정 웹 사이트에 대한 구성 및 앱 모음.

프로젝트에는 여러 앱이 포함될 수 있고. 앱은 여러 프로젝트에있을 수 있다.

 

 

그러면 polls라는 디렉토리가 생기며 그안에는 다음과 같은 파일이 생성되어져 있다.

 

polls/
    __init__.py
    admin.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py

 

 

 

2. DATABASE 설치

 

python에서 SQLite를 기본 제공해서 설치안해도 된다.

 

mysite/settings.py안에 여러 설정이 있는데 그중,

DATABASE 설정을 바꿔주면 다른 DB도 사용 가능하다.

 

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

 

 

mysite/setting.py안의 INSTALLED_APPS에는 Django와 함께 딸려오는 앱을 포함한다. 필요없는 앱은

주석처리 해주면 된다.

 

django.contrib.admin -- 관리용 사이트. 곧 사용하게 될 겁니다.
django.contrib.auth -- 인증 시스템.
django.contrib.contenttypes -- 컨텐츠 타입을 위한 프레임워크.
django.contrib.sessions -- 세션 프레임워크.
django.contrib.messages -- 메세징 프레임워크.
django.contrib.staticfiles -- 정적 파일을 관리하는 프레임워크.

 

다음 앱들도 DB가 필요한데, 

다음 명령어를 수행시켜 데이터베이스를 만들어주자

 

>>python manage.py migrate

 

 

3. 모델만들기

Django는 ORM (Object Relational Mapping)을 지원해,

DB와 데이터 모델클래스를 연결해준다고 하였다.

 

그래서 모델을 만들어주면, 데이터베이스를 그에 맞게 반영해 줄 수 있다.

 

1. 다음과 같이 polls/models.py를 수정해주고 

from django.db import models


class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')


class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

 

2. 해당 앱도 DB에 반영 시켜주세요~ 라는걸 mysite/settings.py에서 INSTALED_APPS에 포함시켜준다. 

 

INSTALLED_APPS = [
    'polls.apps.PollsConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

 

3. 다음 명령어를 통해 변경된 migrations을 만들어준다.

 

>> python manage.py makemigrations polls

 

그러면 polls/migrations/하위에 001_initial.py 파일이 생성되는데

 

다음 명령어로 해당 migrations을 반영해준다.

>>pythjon manage.py sqlmigrate polls 0001

 

 

 

 

python manage.py makemigrations을 통해 이 변경사항에 대한 마이그레이션을 만드세요.


python manage.py migrate 명령을 통해 변경사항을 데이터베이스에 적용하세요.

 

 

3. 관리자 생성

>> python manage.py createsuperuser

 

 

이후 id/ pw 를 치고

 

서버기동 ( python manage.py runserver) 하고 , 

 

http://localhost:8000/admin으로 들어가면 어드민 페이지에 접속할 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 


참고

https://docs.djangoproject.com/ko/3.0/intro/tutorial01/

 

첫 번째 장고 앱 작성하기, part 1 | Django 문서 | Django

Django The web framework for perfectionists with deadlines. Overview Download Documentation News Community Code Issues About ♥ Donate

docs.djangoproject.com

 

이글은 Django의 튜토리얼을 개인적으로 따라서 해본 글이다

그러고 개인적으로 정리하고자 한다 '-'

 

 


 

1. Django 란?

파이썬 웹 서버 프레임워크이다.

 

가장 특징적인건 ORM (Object Relational Mapping)을 지원한다는 점이다.

ORM은 DB와 데이터 모델 클래스를 연결해준다.

 

그리고 자동으로 관리자화면을 구성해준다..

이부분은 튜토리얼을 따라해보면서 봤는데 신기했다 ㅎㅎ 그리고 꽤 편리해서

잘 이용하면 유용할것 같다란 생각을 했다.

 

 

 

2. Python , Django 설치하기

 

https://www.python.org/downloads/

 

여기서 맞는 os를 선택해서 window일경우 bit도 보고,,

나는 window 64bit라

 

Windows x86-64 executable installer

를 선택해서 설치해 주었다

 

설치할 때 주의 사항은

Path 추가하기를 체크를 꼭 해야한다,, 

 

그이후 cmd 창에서 다음 명령어를 쳐서 설치가 잘 되었는지 확인해준다.

>>python --version

Python 3.7.7

이게 안됐을경우 환경변수를 확인해보자..!

 

 

이제 Django를 설치해주자 proxy가 없는 환경이라면, --proxy 를 빼고 설치해주면된다.

(django만 설치해줘도된다..)

>>pip install --proxy http://proxy_id:proxy_port pylint
>>pip install --proxy http://proxy_id:proxy_port django
>>pipi nstall --proxy http://proxy_id:proxy_port djangorestframework

 

설치가 잘 됐는지, Django 버전도 확인해보자

 

>> python -m django --version

3.0.4

 

 

3. Django 프로젝트 만들기

cmd 창에서 프로젝트를 만들고 싶은 경로에 다음 명령어를 쳐준다.

>>django-admin startproject mysite

 

여기서 mysite는 프로젝트명이다. 그럼 프로젝트가 만들어지고 

 

 

경로에 다음과 같은 파일이 생성 되어있을 것이다.

mysite/
    manage.py
    mysite/
        __init__.py
        settings.py
        urls.py
        asgi.py
        wsgi.py

 

그리고 만든 프로젝트를 구동해보자

>> python manage.py runserver

 

 

ㅎㅎ 이번편은 여기까지하고 다음번에 

Django 프로젝트를 구현해보고자 한다.

 

 

 

 


참고

https://docs.djangoproject.com/ko/3.0/intro/tutorial01/

 

첫 번째 장고 앱 작성하기, part 1 | Django 문서 | Django

Django The web framework for perfectionists with deadlines. Overview Download Documentation News Community Code Issues About ♥ Donate

docs.djangoproject.com

 

Spring에서 Async처리를 해보겠다..!

 

블로그에 정리되어 있는게 많았는데 그중에 어떤 방법을 택할까 고민을 했다.

 

 

 

가장 간단한 방법으로 구현하였다.

 


 

@Async 

annotaion을 붙여주는 방법이다.

 

1. @EnableAsync로 async를 쓰겠다고 스프링에게 알린다.

2. 비동기로 수행되었으면 하는 method위에 @Async annotaion 을 붙인다.

3. method return 값은 void나 CompletableFuture<?>로 해주어야한다.

 

 

 

@EnableAsync은 Application을 run하는 데에다 붙여주거나,@Configuration annotaion 있는데 붙여주면 된다.

 

그리고 thread를 관리해주어야 하기 때문에 bean을 설정해준다.

 

@Bean
  public Executor taskExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(2);
    executor.setMaxPoolSize(2);
    executor.setQueueCapacity(500);
    executor.setThreadNamePrefix("GithubLookup-");
    executor.initialize();
    return executor;
  }

 

spring boot 2.0이상이면, application.yml파일에 작성해도 auto configuration 으로 Excutor를 등록해준다.

 

 

이렇게해서,, 테스트를 해봤었는데 잘안되었다

 

이유는???

 

@Async를 활용하기 위해서는 몇가지 제약 조건이 있기 때문이다.

 

 

1.public method만 @Async가 가능하다. private는 불가능 
2.self-invocation(자가 호출)해서는 안된다. -> 같은 클래스 내부의 메서드를 호출하는 것은 안된다.

 

 

나같은 경우는 2번의 경우였다.

한 service에서 계속 function call을 내부적으로 하는데 

그중에 한, method만 비지니스적으로 async하게 call하고 싶었다.

 

 

그래서 찾은 방법은???

async해야 하는 method를 다른 service로 빼서 , 

기존 service에 AsyncService를 주입하고 (@Autowired)

async 해야하는 method에 @Async를 붙여준다음,

service에서 call 하면 되는 것이다 (간단간단 '-' 역시.. 알면 간단하다)

 

 

기존 service

@Service

public class 기존service{

@Autowired

AsyncService asyncService;

 

public void 해당method(){

      asyncService.asyncMethod();

   }

}

 

 

AsyncService

@Service

public class Asyncservice{

 

@Async

    ComletableFuture<OutVO>asyncMethod(){

      OutVO output = new OutVO();

 

       return ComletableFuture.completedFuture(output);

   }

}

 

 

 

그런데 도대체 왜그럴까?? ( 블로그 글 참조)

 

결론부터 말하면 AOP가 적용되어 Spring context에 등록되어 있는 빈 객체의 메서드가 호출되었을 때 스프링이 끼어들 수 있고 @Async가 적용되어 있다면 스프링이 메서드를 가로채서 다른 스레드(풀)에서 실행시켜주는 메커니즘이라는 것이다.

 

public이어야 가로챈 스프링의 다른 클래스에서 호출이 가능하고,

self-invocation이 불가능 했던 이유도 spring context에 등록된 빈의 메서드 호출 이어야

프록시를 적용 받을 수 있기에 내부 메서드 호출은 프록세 영향을 받지 않기 때문이다.

 

 

 

 

 


참고 사이트 :

https://spring.io/guides/gs/async-method/

 

Spring

Level up your Java code and explore what Spring can do for you.

spring.io

 

https://jeong-pro.tistory.com/m/187

 

How does @Async work? @Async를 지금까지 잘 못 쓰고 있었습니다(@Async 사용할 때 주의해야 할 것, 사용법)

@Async in Spring boot 스프링 부트에서 개발자에게 비동기 처리를 손쉽게 할 수 있도록 다양한 방법을 제공하고 있다. 대세는 Reactive stack, CompletableFuture를 쓰겠으나 역시 가장 쉬운 방법으로는 @Async..

jeong-pro.tistory.com

 

 

테스트에서 @Transactionl어노테이션을 쓰면 테스트 내에서 진행하는 모든 트랜잭션 관련 작업을 하나로 묶어 줄 수 있다.

 

@Transactionl은 애플리케이션의 클래스에 적용할 때와 디폴트 속성은 동일하다.

 

1. @Transactional

중요한 차이점은,

테스트용 트랜잭션은 테스트가 끝나면 자동으로 롤백된다는 것이다.

테스트에 적용된 @Transactional은 기본적으로 트랜잭션을 강제 롤백시키도록 설정~

롤백 테스트 가능 ㅎㅎ 굳


2. @Rollback

그런데,,, 트랜잭션을 커밋시켜서 테스트에서 진행작업을 DB 반영하고 싶다면?!

@Rollback 어노테이션 사용!

 

@Rollback의 기본값은 true라서 

트랜잭션은 적용되지만 롤백을 원치 않는다면 @Rollback(false) 라고 해주면 된닷!

 

 


3. @TransactionConfiguration

테스트 클래스의 모든 메소드에 트랜잭션을 적용하면서 모든 트랜잭션이 롤백되지 않고 커밋되게 하려면?!

일일히 메소드에 @Rollback(false)하지말고,

 

클래스레벨에 부여할 수 있는 @TransactionConfiguration 사용

 

@Transactional

@TransactionaConfiguraion(defaultRollback=false)

public class Test{

    ... ...

}

토비의 스프링을 진짜 오랜만에 펼쳐봤다,,

앞에만 보고 덮었었는데 

뒤에 알아야되는 내용이 그득 했다,, 

앞으로도 사전처럼 두고 봐야지 ㅎ_ㅎ

 


 

이번 포스팅은 @Transactional 속성에 대해서 알아보려고한당 (feat. 토비의 스프링~)

 

트랜잭션이란? 더 이상 쪼갤 수 없는 최소 단위의 작업

 

트랜잭션 매니저에서 트랜잭션을 가져올때 사용한 오브젝트는 DefaultTransactionDefinition이다.

 

Transaction status = this.transactionManager.getTransaction( new DefaultTransactionDefinition());

DefaultTransactionDefinition이 구현하고 있는 TrasactionDefinition  인터페이스는 트랜잭션 동작방식에 영향을 줄 수 있는 네가지 속성을 정의하고있다.

 


1. 트랜잭션 전파 ( Transaction propagation)

: 트랜잭션 경계에서 이미 진행중인 트랜잭션이 있을 떄 또는 없을 떄 어떻게 동작할 것인가를 결정하는 방식

 

 

  • PROPAGATION_REQUIRED

:진행 중인 트랜잭션이 없으면 새로 시작하고, 이미 시작된 트랜잭션이 있으면 이에 참여한다

 

DefaultTransactionDefinition의 트랜잭션 전파 속성

 

  • PROPAGATION_REQUIRES_NEW

: 항상 새로운 트랜잭션을 시작한다

독립적인 트랜잭션이 보장돼야 하는 코드에 적용

 

 

  • PROPAGATION_NOT_SUPPORTED

: 트랜잭션 없이 동작하도록, 진행중인 트랜잭션이 있어도 무시한다.

 

 

=> 트랜잭션 매니저를 통해 트랜잭션을 시작할때, getTransaction()을 사용하는 이유는 바로 이 트랜잭션 전파 속성이 있기 때문이다. 

 

  • PROPAGATION_SUPPORT : 부모 트랜잭션 내에서 실행, 부모 트랜잭션이 없을 경우, notransactionally로 실행
  • PROPAGATION_MANDATORY : 부모 트랜잭션 내에서 실행되며, 부모 트랜잭션이 없을 경우 예외 발생
  • PROPAGATION_NEVER : notransactionally로 실행되며 부모 트랜잭션이 존재한다면 예외 발생

2. 격리 수준

: 모든 DB 트랜잭션은 격리수준 (isolation levlel)을 가지고 있어야 한다. 

 

성능을 위해서 적절하게 격리수준을 조정해서 가능한 한 많으 트랜잭션을 동시에 진행시키면서도 문제가 발생하지 않게 하는 제어가 필요하다. 

 

격리수준은 기본적으로 DB에 설정, JDBC드라이버나 DataSource 등에서 재설정, 필요하다면 트랜잭션 단위로 조정!

 

 

DefaultTransactionDefinition에 설정된 격리수준은 ISOLATION_DEFAULT이다. 이는 DataSource설정되어 있는 디폴트 격리수준을 따른다.

 

블로그에서 더찾아볼때 더있는데,, 모르겠당 @_@

 


3. 제한시간

: 트랜잭션의 수행하는 제한시간을 설정할 수 있다. 

DefaultTransactionDefinition의 기본설정은 제한시간 음슴..

 

 

 


4. 읽기 전용

: 읽기전용(read only)로 설정하면 트랜잭션내 데이터 조작시도를 막을 수 있다. 성능이 향상 될수도 있다. 

 


 

스프링이 제공하는 TransactonInterceptor에는 예외처리 두가지 방법이 있다.

 

1. 런타임 예외 발생 -> 트랜잭션 롤백

2. 체크예외 -> 예외상황으로 해석하지 않는다. 의미가 있는 리턴방식의 한가지로 인식해서 트랜잭션을 커밋한다.

 

 

 


@Transactional 어노테이션은 인터페이스, 클래스, 메소드에 쓸 수 있다. 

 

해당 구현한 클래스에서도 모두 @Transactionl 어노테이션을 쓰고 싶으면 인터페이스에,

클래스에서만 쓰고 싶으면 클래스에

메소드별로 따로 가지고 가고싶으면 메소드에 쓰면된다

 

나같음 클래스나,,, 메소드 정도로만 쓸듯,,하다

 

 

 


 

ㅎㅎ 토비의 스프링을 보니깐 이해가 그래도 잘되는거 같당~

계속 읽어봐야짓 ㅎㅅㅎ 

 

 

 

 

+ Recent posts