TransactionTemplate 이용한 트랜잭션 관리

@Transactional 어노테이션을 사용하지 않고, 트랜잭션을 직접 관리하고 싶은 경우가 있었다. 이때 TransactionTemplate를 사용하면 된다. 트랜잭션 외부에 리턴을 해야되는 경우 return transactionTemplate.execute(new TransactionCallback() { // the code in this method runs in a transactional context public Object doInTransaction(TransactionStatus status) { updateOperation1(); return resultOfUpdateOperation2(); } }); 트랜잭션 외부에 리턴이 필요없을 경우 transactionTemplate.execute(new TransactionCallbackWithoutResult() { protected void doInTransactionWithoutResult(TransactionStatus status) { updateOperation1(); updateOperation2(); } }); 참고 자료 https://docs.spring.io/spring-framework/docs/current/reference/html/data-access.html#tx-prog-template

2024-09-15 · 1 min · 64 words

toString() 메서드가 나올 경우

assertThat(obejct.toString()).isEqualTo("\"value\""); 위의 코드는 아래의 방식으로 바꿀 수 있다. assertThat(obejct).hasToString(expectedString)

2024-09-15 · 1 min · 9 words

TLS vs SSL

SSL(Secure Sockets Layer)은 보안 소켓 계층 이라는 뜻으로 인터넷을 통해 전달되는 정보 보안의 안전한 거래를 허용하기 위해 Netscape 사에서 개발한 인터넷 통신 규약 프로토콜이며, TLS(Transport Layer Security)는 SSL 3.0을 기초로 해서 IETF가 만든 프로토콜로 이는 SSL3.0을 보다 안전하게 하고 프로토콜의 스펙을 더 정확하고 안정성을 높이는 목적으로 고안되었다. 추후에 추가적인 학습이 필요하다. 참고 자료 https://waspro.tistory.com/161

2024-09-15 · 1 min · 54 words

TIMESTAMP vs DATETIME

목표 TIMESTAMP와 DATETIME의 차이점을 이해한다. 크기 5.6.4 버전 이후 기준 TIMESTAMP는 기본적으로 4 bytes에 소수점 표현을 위해 0~3 bytes를 추가로 사용한다. DATETIME은 기본적으로 5 bytes에 소수점 표현을 위해 0~3 bytes를 추가로 사용한다. 표현 범위 TIMESTAMP: 1970-01-01 00:00:00 ~ 2038-01-19 03:14:17 DATETIME: 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59 따라서, 2038년이 넘는 날짜가 필요하면 TIMESTAMP를 사용할 수 없다. Timezone DATETIME은 timezone에 대해서 아무것도 처리되지 않는다. TIMESTAMP는 timezone에 대한 처리가 이루어진다. 저장 시 TIMESTAMP 값을 현재 timezone 에서 UTC로 변환 조회 시 UTC에서 현재 timezone으로 변환 예시 CREATE TABLE timezone_test ( `timestamp` TIMESTAMP, `datetime` DATETIME ); SET SESSION time_zone = '+00:00'; INSERT INTO timezone_test VALUES ('2029-02-14 08:47', '2029-02-14 08:47'); SELECT * FROM timezone_test; -- | timestamp | datetime | -- |---------------------|---------------------| -- | 2029-02-14 08:47:00 | 2029-02-14 08:47:00 | SET SESSION time_zone = '-05:00'; SELECT * FROM timezone_test; -- | timestamp | datetime | -- |---------------------|---------------------| -- | 2029-02-14 03:47:00 | 2029-02-14 08:47:00 | 참고 자료 https://planetscale....

2024-09-15 · 1 min · 155 words

TIMESTAMP ms 단위까지 저장하기

TIMESTAMP(3) 이라고 타입을 지정하면 ms단위까지 저장한다. 참고 자료 https://mariadb.com/kb/en/timestamp/ https://stackoverflow.com/questions/26299149/timestamp-with-a-millisecond-precision-how-to-save-them-in-mysql/26299379

2024-09-15 · 1 min · 10 words

ThreadLocal

배경 ThreadLocal 의 용도와 동작 방식을 알아본다. ThreadLocal이란? 하나의 스레드에서 고유하고 독립적인 변수를 갖게 해주는 클래스다. 스레드가 사라진 뒤에 해당 변수는 GC 대상이 된다. get(), set(), remove() 메서드만 존재하는 단순한 구조다. 예를 들어 스레드 마다 고유한 id를 생성하기 위해서 아래와 같이 사용할 수 있다. public class ThreadId { // Atomic integer containing the next thread ID to be assigned private static final AtomicInteger nextId = new AtomicInteger(0); // Thread local variable containing each thread's ID private static final ThreadLocal<Integer> threadId = new ThreadLocal<Integer>() { @Override protected Integer initialValue() { return nextId....

2024-09-15 · 1 min · 116 words

Thread pool 생성

배경 Executors.newFixedThreadPool(10)의 의미를 알아본다. Executors.newFixedThreadPool() 고정된 개수의 스레드를 가지는 스레드풀을 생성한다. 반환 값은 ExecutorService이다. ExecutorService executor = Executors.newFixedThreadPool(10); ExecutorService ExecutorService는 인터페이스이며, execute() 메서드를 통해 파라미터로 Callable이나 Runnable을 넘겨주면 스레드풀에서 해당 작업을 할당해 실행해준다. executorService.execute(runnableTask); ExecutorService는 수동으로 소멸시켜줘야된다. shutdown() 메소드는 즉시 소멸되지 않고, 현재 실행 중인 스레드가 모드 완료되고 소멸된다. shutdownNow(): 현재 실행중인 스레드들을 즉시 멈추고 소멸시킨다. 또한, 실행 중이던 작업들을 반환한다. executorService.shutdown(); List<Runnable> notExecutedTasks = executorService.shutDownNow(); 참고 자료 https://www.baeldung.com/java-executor-service-tutorial

2024-09-15 · 1 min · 69 words

thenAnswer vs thenReturn

목표 thenAnswer와 thenReturn의 차이를 알아본다. 차이점 thenReturn은 정적인 반환 값을 설정할 때 사용한다. thenAnswer은 호출에 대한 추가적은 작업이 필요하거나, 동적인 반환 값이 필요할 때 사용한다. thenAnswer thenAnswer는 Answer 타입의 인자를 갖는다. Answer는 함수형 인터페이스이다. 아래 사진처럼 Answer의 메서드의 인자인 InvocationOnMock은 호출한 메소드의 인자를 반환하거나, 해당 메소드를 반환, mocking한 대상 객체를 반환도 할 수 있어서 유연하게 사용할 수 있다. 참고 자료 https://stacktraceguru.com/unittest/thenreturn-vs-thenanswer https://www.baeldung.com/mockito-additionalanswers https://javadoc.io/static/org.mockito/mockito-core/3.1.0/org/mockito/invocation/InvocationOnMock.html

2024-09-15 · 1 min · 63 words

TestInsatnce

목표 @TestInstance의 용도를 이해한다. Junit의 라이프사이클 Junit에서는 기본적으로 각 테스트 메서드마다 새로 해당 클래스의 인스턴스를 만든다. 따라서, 아래 테스트 코드는 모두 통과한다. class AdditionTest { private int sum = 1; @Test void addingTwoReturnsThree() { sum += 2; assertEquals(3, sum); } @Test void addingThreeReturnsFour() { sum += 3; assertEquals(4, sum); } } 테스트 마다 공유하는 상태가 필요한 경우 아래의 경우 테스트 메서드 사이에 공유가 되어야 하는 상태가 필요할 수 있다. 리소스 초기화 비용이 큰 경우 @Order 어노테이션으로 각 테스트 메서드가 순차적으로 처리되는 경우(단위 테스트에서는 안티 패턴이지만, 통합 테스트에서는 유용할 수 있다....

2024-09-15 · 1 min · 165 words

TestExecutionListener

목표 TestExecutionListner가 무엇인지 이해한다. TestExecutionListner의 사용법을 이해한다. TestExecutionListner Junit의 @BeforeEach, @AfterEach, @BeforeAll, @AfterAll 같이 테스트 라이프사이클에 추가적으로 동작해야 되는 내용이 있을 때 사용할 수 있다. Spring test에서 제공하는 인터페이스로 이를 상속해서 구현할 수 있다. 인터페이스 public interface TestExecutionListener { default void beforeTestClass(TestContext testContext) throws Exception {}; default void prepareTestInstance(TestContext testContext) throws Exception {}; default void beforeTestMethod(TestContext testContext) throws Exception {}; default void afterTestMethod(TestContext testContext) throws Exception {}; default void afterTestClass(TestContext testContext) throws Exception {}; } beforeTestClass: 클래스 내의 모든 테스트를 실행하기 전에 실행한다....

2024-09-15 · 2 min · 244 words

TCP 흐름 제어

목적 TCP를 사용하는 두 호스트가 있을 때, 발신자의 전송 속도가 너무 빨라서 수신자의 버퍼를 오버플로우 시키는 경우를 방지하기 위한 목적이다. 슬라이딩 윈도우 TCP는 흐름 제어를 위해 슬라이딩 윈도우 기법을 사용한다. TCP 윈도우는 데이터의 일부를 받았다는 ACK 패킷을 받기 전에 발신자가 보낼 수 있는 데이터의 크기다. 발신자는 자신의 윈도우 안에 있는 패킷들을 모두 보낼 수 있으며, 각 패킷에 대해서 타임아웃 타이머를 시작해야된다. 수신자로부터 ACK 패킷을 받게되면, ACK 번호만큼 윈도우를 오른쪽으로 밀 수 있다....

2024-09-15 · 1 min · 83 words

TCP 연결 종료는 연결 요청과 다르게 4-way 핸드셰이크인 이유

연결 과정에서는 3-way 핸드셰이크인데, 연결 종료시에는 왜 비효율적으로 4-way로 동작하는지 의문이 들었다. 그 이유는 클라이언트가 서버에게 연결 종료 요청을 해도 서버는 클라이언트에게 보내야될 데이터가 남아 있을 수 있기 때문이다. 4-way 핸드셰이크의 과정을 상세히 적게된다면 아래와 같다. 클라이언트가 서버에거 FIN 패킷을 보낸다. 서버가 클라이언트에게 ACK 패킷을 보낸다. 서버가 클라이언트에게 보내야 될 남은 데이터들을 보낸다. 서버가 클라이언트에게 FIN 패킷을 보낸다. 클라이언트가 서버에게 ACK 패킷을 보낸다. 참고 자료 https://velog.io/@arielgv829/CS-network-TCP-3-way-handshake-4-way-handshake https://stackoverflow.com/questions/46212623/why-tcp-termination-need-4-way-handshake

2024-09-15 · 1 min · 67 words

Tasklet vs Step

목표 Spring batch의 Tasklet과 Step의 차이점을 이해한다. 차이점 Tasklet은 Step 안의 작업의 전략을 나타내는 함수형 인터페이스다. Job에는 여러개의 Step이 있고, Step은 Tasklet을 이용해 표현할 수 있다. 참고 자료 https://docs.spring.io/spring-batch/docs/current/api/org/springframework/batch/core/step/tasklet/Tasklet.html https://stackoverflow.com/questions/40041334/difference-between-step-tasklet-and-chunk-in-spring-batch

2024-09-15 · 1 min · 30 words

System out print() 테스트하기

System.setOut() 메소드를 통해서 시스템의 기본 출력을 설정할 수 있다. private ByteArrayOutputStream byteArrayOutputStream; @BeforeEach void setUp() { byteArrayOutputStream = new ByteArrayOutputStream(); System.setOut(new PrintStream(byteArrayOutputStream)); } @Test public void out() { System.out.print("hello"); assertEquals("hello", byteArrayOutputStream.toString()); } 참고 자료 https://stackoverflow.com/questions/1119385/junit-test-for-system-out-println

2024-09-15 · 1 min · 35 words

String의 hashCode()

Java의 String의 hashCode() 메소드는 같은 문자열이면 같은 값이 나온다. 하지만 반환값이 int기 때문에 오버플로우가 발생해서 음수가 나올 수 있다는 것도 충분히 고려해야된다. 만약 String의 hashCode를 이용해서 추가적인 작업을하는데 0부터 시작하길 원한다면 아래처럼 구현하면 된다. long avatarIndex = ((long) nickname.hashCode() - Integer.MIN_VALUE) % NUMBER_OF_AVATAR;

2024-09-15 · 1 min · 43 words

String을 뒤집는 방법

StringBuilder에 reverse 기능이 존재한다. String reversed = new StringBuilder(original).reverse().toString() 참고 자료 https://stackoverflow.com/questions/7569335/reverse-a-string-in-java

2024-09-15 · 1 min · 12 words

String을 LocalDate로 변환하기

DateTimeFormatter 로 문자열의 날짜 형식을 지정하고 파싱하면된다. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/MM/yyyy"); String date = "16/08/2016"; //convert String to LocalDate LocalDate localDate = LocalDate.parse(date, formatter); 참고 자료 https://mkyong.com/java8/java-8-how-to-convert-string-to-localdate/

2024-09-15 · 1 min · 27 words

String으로 원하는 Enum 찾기

Enum에 valueOf() 메서드를 이용하면 된다. 참고 자료 https://stackoverflow.com/questions/604424/how-to-get-an-enum-value-from-a-string-value-in-java

2024-09-15 · 1 min · 8 words

String안에 특정 문자의 마지막 인덱스 찾기

abc.txt.jpg 같은 파일이름을 파싱할 때, 확장자를 jpg로 구하기 위해서 ‘.‘문자의 마지막 인덱스 위치를 알아야 됐다. fileName.lastIndexOf(FILE_EXTENSION_DELIMITER); Java에 String의 메소드로 lastIndexOf라는 메소드가 있어서 쉽게 구현할 수 있었다.

2024-09-15 · 1 min · 26 words

Stream을 collection으로 만든 후 추가 적인 작업이 필요한 경우

passengers.stream() .map(name -> new Person(name)) .collect(Collectors.collectingAndThen(Collectors.toList(), Bus::new)); collectingAndThen()메소드를 활용하면 된다. 참고 자료 https://stackoverflow.com/questions/52382157/continue-mapping-after-stream-collect

2024-09-15 · 1 min · 13 words