728x90

6.6. Subtraction Class

We can use subtraction to negate one or more character classes. For example, we can match a set of odd decimal numbers:

@Test
public void givenSetWithSubtraction_whenMatchesAccurately_thenCorrect() {
    int matches = runTest("[0-9&&[^2468]]", "123456789");
 
    assertEquals(matches, 5);
}Copy

Only 1, 3, 5, 7, 9 will be matched.

 

 

Let's dive to Pattern and Matcher

1.

if String qr has contains "substring value" like otpauth%3A%2F%2Ftotp%2F4009acd5fe30716b6201a93f5ed98999%253A35mwlee%2540naver.com%3Fsecret%3DMIHON7TZY7SEIH27RAOROQ7DI7LHCAJEDBLI4R6LSITWZSITS7PQN75S65E2TLEB%26issuer%3D%25EB%258D%2594%25EB%2593%25AC%25EC%259D%25B4%25EC%2599%2595%25ED%2594%25BC%25EC%25BD%259C%25EB%25A1%259C%26id%3Do87a66240433494aa362ad88e69af9c5

 

We can parse ID string like this

    try{
        String decodeStr = URLDecoder.decode(qr, "UTF-8"); // URL Decode
        Pattern pattern = Pattern.compile("id=([^&]+)"); // Standby ID substring
        Matcher matcher = pattern.matcher(decodeStr);	// Matcher Object will find the target data

        if(matcher.find()) {
            jsonUuid = matcher.group(1);
            log.debug("Extracted ID : {}", jsonUuid);
        } else {
            log.debug("ID not found");
        }
    } catch (UnsupportedEncodingException e){
        e.printStackTrace();;
    }

 

 

https://www.baeldung.com/regular-expressions-java

 

728x90

https://kdhyo98.tistory.com/48

 

[Java] Random보단 SecureRandom 를 사용하자.

🙄서론 Random을 사용하다가 소나큐브에서 Critical 버그가 발생했다. 그 후 알아본 내용을 정리해본다. 😉본론 - 에러 메세지 (번역은 구글번역을 통해 되었기 때문에 오역이 있을 수 있습니다..) "

kdhyo98.tistory.com

https://www.baeldung.com/java-generate-random-long-float-integer-double

 

    public static long generatedRandomLongBounded(){
        SecureRandom random = new SecureRandom();
        return Math.abs(random.nextLong());
    }

 

 

728x90

Issue

Cannot change the ExecutorType when there is an existing transaction in _____Processor.

 

 

1. Set a Consistent ExecutorType

Ensure that the ExecutorType is consistently set across all MyBatis operations. Typically, ExecutorType.BATCH is used for batch processing, but you can choose the appropriate one for your use case (SIMPLE, REUSE, BATCH).

 

In runtime, Spring Batch was excuted with ExecuteType.Batch, but annotation-base queries will be excuted with ExecuteType.SIMPLE, which is having differentition point.

 

1.1 Trouble Shooting and Solution

Implement MyBatisConfig with returning SqlSessionTemplate(sqlSessionFactory, ExecutorType.BATCH);

Let's show e.g

import org.apache.ibatis.session.ExecutorType;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;

@Configuration
@MapperScan("your.package.com.model.mapper")
public class MyBatisConfig {

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        // Ensure that the mapper XML files are found
        factoryBean.setMapperLocations(
            new PathMatchingResourcePatternResolver().getResources("classpath*:mappers/*.xml")
        );
        return factoryBean.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory, ExecutorType.SIMPLE);
    }
}

 

@MapperScan Annotation could be matched with interface of mapper location. if non-correct path was assigned, mapper interface do not find real object.

 

setMapperLocation  method  will be matched with mybatis.mapper-location in application.yml.
So, We need to match mapper-location path like classpath:*mappers/*.xml

 

Since I use absolute path in application.yml, which is unusuall case, classpath solution could not be fitted.

In theory, we would use classpath with ExecutorType.SIMPLE.

 

 

[Concenturate to understand issue environment]

MyBatisPageReaderBuilder will return ExecutorType.Batch, and this part causes Spring Batch ExecutorType not to be matched issue.

 

    @Bean
    @StepScope
    public MyBatisCursorItemReader<______Dto__or__Entity> ___ItemReader(
            @Value("#{jobParameters[UUID]}") String uuid) throws Exception {
        Map<String, Object> parameterValues = new HashMap<>();
        parameterValues.put("uuid", uuid);

        MyBatisCursorItemReaderBuilder<YourDto> readerBuilder = new MyBatisCursorItemReaderBuilder<>();
        readerBuilder.sqlSessionFactory(sqlSessionFactory);
        readerBuilder.queryId("your.package.com.model.mapper.InterfaceMapper.select");
        readerBuilder.parameterValues(parameterValues);

        return readerBuilder.build();
    }

 

 

 

Quote

https://jessyt.tistory.com/5

 

org.springframework.dao.TransientDataAccessResourceException: Cannot change the ExecutorType when there is an existing transacti

Batch 프로젝트를 진행중에 아래와 같은 에러 발생하였습니다. Batch 삽질 삽질 삽질 에러 원인을 요약하자면 하나의 트랜잭션 안에서 다른 실행자를 사용할 수 없다라는 내용이다. 자세한 내용을

jessyt.tistory.com

https://bkjeon1614.github.io/blog/java-springbatch-7

 

Spring Batch 7편 - ItemReader - 아무거나 (github)

단, 본인 조회 프레임워크가 Querydsl, Jooq 라면 직접 구현해야할 수도 있다. 왜냐하면 왠만해선 JdbcItemReader 로 해결되지만, JPA 영속성 컨텍스트 지원이 안되서 HibernateItemReader 를 사용하여 Reader 구

bkjeon1614.github.io

 

 

'Java' 카테고리의 다른 글

Pattern and Matcher  (0) 2024.07.16
SecureRandom  (0) 2024.07.12
[MyBatis] Page with MyBatis  (0) 2024.07.01
[Spring Security] Public vs Private method to be applied Spring Security  (1) 2024.06.07
[method] java stream mapToObj  (0) 2024.05.07
728x90

Do not confuse Oracle SQL Statement with MySQL Statement

e.g) Oracle SQL statement code

OFFSET ____ ROWS FETCH NEXT _____ ROWS ONLY

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.company.helloBoard.domain.board.mapper.BoardMapper">
	
	<select id="getListBoard" parameterType="RequestList" resultType="Board">
		SELECT BOARD_ID
			 , WRITER
			 , TITLE
			 , CONTENT
			 , REG_DATE
			 , UPDATE_DATE
			 , DELETE_DATE
		  FROM BOARD
		  <where>
		  <if test="data.title != null and data.title != ''">
			 AND TITLE LIKE '%' || #{data.title} || '%'
		  </if>
		  <if test="data.writer != null and data.writer != ''">
			 AND WRITER LIKE '%' || #{data.writer} || '%'
		  </if>
		  </where>
	    OFFSET #{pageable.offset} ROWS FETCH NEXT #{pageable.pageSize} ROWS ONLY
	</select>
	
	<select id="getListBoardCount" parameterType="Board" resultType="int">
		SELECT COUNT(*) AS CNT
		  FROM BOARD
		  <where>
		  <if test="title != null and title != ''">
			 AND TITLE LIKE '%' || #{title} || '%'
		  </if>
		  <if test="writer != null and writer != ''">
			 AND WRITER LIKE '%' || #{writer} || '%'
		  </if>
		  </where>
	</select>

</mapper>

 

 

e.g) 

<select id="pageList" parameterType="RequestList" resultType="OtpDto">
    SELECT
        A.id,
        B.service_name,
        B.group_name,
        A.otp_org_info_id,
        A.create_date,
        A.email,
        A.end_date,
        A.name,
        A.note,
        A.object_id,
        A.otp_app,
        A.user_id
    FROM
        ${data.uuid}_otp A,
        ${data.uuid}_hsm_service B
    <where>
        <if test="data.userId != null">
            AND A.user_id LIKE CONCAT('%', #{data.userId}, '%')
        </if>
        <if test="data.serviceName != null">
            AND B.service_name LIKE CONCAT('%', #{data.serviceName}, '%')
        </if>
        <if test="data.objectId != 0">
            AND A.object_id = #{data.objectId}
        </if>
    </where>
    ORDER BY A.create_date DESC
    LIMIT #{pageable.pageSize} OFFSET #{pageable.offset}
</select>

 

+ Recent posts