728x90
반응형
728x90
반응형
728x90
반응형

페이징을 처음 하나하나 만들었을때는 정말... 어렵다기보단 귀찮고 손이 많이 갔다.

다행히 최근에 알게된 pagehelper를 사용하면 페이징에 필요한 정보를 한번에 간단하게 얻을 수 있게 된다.

 

아래는 pagehelper를 적용하기 위한 셈플 소스

 

1. gradle에 추가

1
implementation group: 'com.github.pagehelper', name: 'pagehelper-spring-boot-starter', version: '1.2.10'
cs

2. properties 추가

1
2
3
# Pagehelper Setting (사용하는 DB, 페이지 번호의 가능 범위 자동 제한)
pagehelper.helperDialect=mysql
pagehelper.reasonable=true
cs

3. controller

1
2
3
4
    @GetMapping(value = "/getPageList")
    public PageInfo<GroupCode> getPageList(SearchGrpCodeReqDTO serachDTO) throws Exception {
        return new PageInfo<GroupCode>(service.getPageList(serachDTO));
    }
cs

4. service

PageHelper.startPage(현재 페이지 번호, 한 페이지에 노출할 row 수);

1
2
3
4
    public Page<GroupCode> getPageList(SearchGrpCodeReqDTO reqDTO) throws Exception {
        PageHelper.startPage(reqDTO.getPage(), reqDTO.getPageSize());
        return (Page<GroupCode>) groupCoceMapper.getPageList(reqDTO);
    }
cs

5. mapper

1
 public Page<GroupCode> getPageList(SearchGrpCodeReqDTO serachReqDTO) throws Exception ;
cs

6. mapper.xml

1
2
3
4
5
6
    <select id="getPageList" 
        parameterType="com.deonggi.bookkeeping.admin.system.grpcd.service.dto.SearchGrpCodeReqDTO" 
        resultType="com.deonggi.bookkeeping.core.model.entity.GroupCode">
        SELECT * FROM GROUP_CODE
        ORDER BY CRT_DT ASC
    </select>
cs

7. 리턴된 결과

(참고로 GROUP_CODE 테이블의 전체 row 수는 16개다.)

mapper.xml에서는 모든 row를 조회하지만,

pagehelper를 적용하면 실제 list에는 아래 쿼리 조회 결과만 들어 있다.

 

SELECT * FROM GROUP_CODE
ORDER BY CRT_DT ASC LIMIT 5

 

쿼리문에 limit 가 추가되어 있는데 이 정보는 위 4번에서 PageHelper.startPage()에 의해 적용되는 정보다.

 

결과적으로 pagehelper를 적용하면 개발자는 한번의 조회를 위한 코드를 통해 페이징을 위한 모든 정보를 얻을 수 있게 된다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

## pagehelper github의 정보 : github.com/pagehelper/Mybatis-PageHelper

 

pagehelper/Mybatis-PageHelper

Mybatis通用分页插件. Contribute to pagehelper/Mybatis-PageHelper development by creating an account on GitHub.

github.com

중국어라 왠지 신뢰가 안 갈 수 있지만 상당히 쓸만하다....

728x90
반응형

'코딩 삽질' 카테고리의 다른 글

[jQuery DataTable] table paging 적용  (0) 2021.03.31
[java, spring] spring.jackson.date-format 적용하기  (0) 2021.03.31
[java] StringTrimConverter  (0) 2021.03.24
[java, spring] modelmapper 사용하기  (0) 2021.03.24
[sts] war 생성  (0) 2020.09.16
728x90
반응형

객체에 사용되는 string에 대해 한번에 trim해 주는 메소드입니다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
 
public class StringTrimConverter {
 
    public static Object trimReflective(Object object) throws Exception {
        if (object == null)
            return null;
 
        Class<extends Object> c = object.getClass();
        
        try {
            // Introspector usage to pick the getters conveniently thereby
            // excluding the Object getters
            for (PropertyDescriptor propertyDescriptor : Introspector
                    .getBeanInfo(c, Object.class).getPropertyDescriptors()) {
                Method method = propertyDescriptor.getReadMethod();
                String name = method.getName();
 
                // If the current level of Property is of type String
                if (method.getReturnType().equals(String.class)) {
                    String property = (String) method.invoke(object);
                    if (property != null) {
                        Method setter = c.getMethod("set" + name.substring(3),
                                new Class<?>[] { String.class });
                        if (setter != null)
                            // Setter to trim and set the trimmed String value
                            setter.invoke(object, property.trim());
                    }
                }
 
                // If an Object Array of Properties - added additional check to
                // avoid getBytes returning a byte[] and process
                if (method.getReturnType().isArray()
                        && !method.getReturnType().isPrimitive()
                        && !method.getReturnType().equals(String[].class)
                        && !method.getReturnType().equals(byte[].class)) {
                    System.out.println(method.getReturnType());
                    // Type check for primitive arrays (would fail typecasting
                    // in case of int[], char[] etc)
                    if (method.invoke(object) instanceof Object[]) {
                        Object[] objectArray = (Object[]) method.invoke(object);
                        if (objectArray != null) {
                            for (Object obj : (Object[]) objectArray) {
                                // Recursively revisit with the current property
                                trimReflective(obj);
                            }
                        }
                    }
                }
                // If a String array
                if (method.getReturnType().equals(String[].class)) {
                    String[] propertyArray = (String[]) method.invoke(object);
                    if (propertyArray != null) {
                        Method setter = c.getMethod("set" + name.substring(3),
                                new Class<?>[] { String[].class });
                        if (setter != null) {
                            String[] modifiedArray = new String[propertyArray.length];
                            for (int i = 0; i < propertyArray.length; i++)
                                if (propertyArray[i] != null)
                                    modifiedArray[i] = propertyArray[i].trim();
 
                            // Explicit wrapping
                            setter.invoke(object,
                                    new Object[] { modifiedArray });
                        }
                    }
                }
                // Collections start
                if (Collection.class.isAssignableFrom(method.getReturnType())) {
                    Collection collectionProperty = (Collection) method
                            .invoke(object);
                    if (collectionProperty != null) {
                        for (int index = 0; index < collectionProperty.size(); index++) {
                            if (collectionProperty.toArray()[index] instanceof String) {
                                String element = (String) collectionProperty
                                        .toArray()[index];
 
                                if (element != null) {
                                    // Check if List was created with
                                    // Arrays.asList (non-resizable Array)
                                    if (collectionProperty instanceof List) {
                                        ((List) collectionProperty).set(index,
                                                element.trim());
                                    } else {
                                        collectionProperty.remove(element);
                                        collectionProperty.add(element.trim());
                                    }
                                }
                            } else {
                                // Recursively revisit with the current property
                                trimReflective(collectionProperty.toArray()[index]);
                            }
                        }
                    }
                }
                // Separate placement for Map with special conditions to process
                // keys and values
                if (method.getReturnType().equals(Map.class)) {
                    Map mapProperty = (Map) method.invoke(object);
                    if (mapProperty != null) {
                        // Keys
                        for (int index = 0; index < mapProperty.keySet().size(); index++) {
                            if (mapProperty.keySet().toArray()[index] instanceof String) {
                                String element = (String) mapProperty.keySet()
                                        .toArray()[index];
                                if (element != null) {
                                    mapProperty.put(element.trim(),
                                            mapProperty.get(element));
                                    mapProperty.remove(element);
                                }
                            } else {
                                // Recursively revisit with the current property
                                trimReflective(mapProperty.get(index));
                            }
 
                        }
                        // Values
                        for (Map.Entry entry : (Set<Map.Entry>) mapProperty
                                .entrySet()) {
 
                            if (entry.getValue() instanceof String) {
                                String element = (String) entry.getValue();
                                if (element != null) {
                                    entry.setValue(element.trim());
                                }
                            } else {
                                // Recursively revisit with the current property
                                trimReflective(entry.getValue());
                            }
                        }
                    }
                } else {// Catch a custom data type as property and send through
                        // recursion
                    Object property = (Object) method.invoke(object);
                    if (property != null) {
                        trimReflective(property);
                    }
                }
            }
 
        } catch (Exception e) {
            throw new Exception("Strings cannot be trimmed because: ", e);
        }
 
        return object;
 
    }
}
cs

 

실제 vo에 사용 시 아래와 같이 사용하면 됩니다.

1
GrpCodeReqDTO req = (GrpCodeReqDTO) StringTrimConverter.trimReflective(reqDTO);
cs

당연하지만 getter, setter가 있어야 합니다.

이걸 빼먹고 1시간 삽질했네요.

 

아쉽게도 해외 원문 작성글이 있었는데 찾을 수가 없어서 링크를 걸어줄 수 없군요.

728x90
반응형
728x90
반응형

간단하게 dto를 entity에 넣어주고 싶을때 modelmapper를 사용하면 한줄로 해결할 수 있다.

 

# modelmapper 사용하는 방법

1. gradle에 추가하기

1
implementation group: 'org.modelmapper', name: 'modelmapper', version: '2.3.2'
cs

 

2. Bean 등록

1
2
3
4
5
6
7
    /**
     * ModelMapper 설정
     */
    @Bean
    public ModelMapper modelMapper() {
        return new ModelMapper();
    }
cs

 

3. Service에서 modelmapper 활용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    @Autowired
    private ModelMapper modelMapper;
 
    public GroupCode insertItem(GrpCodeReqDTO reqDTO) {
        GroupCode entity = modelMapper.map(reqDTO, GroupCode.class);
        return groupCodeRepository.save(entity);
    }
 
    public GroupCode updateItem(GrpCodeReqDTO reqDTO) {
        GroupCode entity = groupCodeRepository.findById(reqDTO.getGrpCd());
        modelMapper.map(reqDTO, entity);
        return groupCodeRepository.save(entity);
    }
 
cs

5번 라인의 GroupCode entity = modelMapper.map(reqDTO, GroupCode.class);

11번 라인의 modelMapper.map(reqDTO, entity);

해당 라인을 참고하여 사용하면 된다.

 

 

※ 참고사항: 맵핑에 대한 설정정보

ModelMapper - Configuration

Configuration ModelMapper uses a set of conventions and configuration to determine which source and destination properties match each other. Available configuration, along with default values, is described below: Setting Description Default Value Access le

modelmapper.org

 

728x90
반응형
728x90
반응형

알고는 있었지만 오늘 30분간 삽질하게 한 실수다.

1
2
3
4
5
6
7
for (int i=0; i< list.size(); i++) {
    if(Utils.isNull(list.get(i).getOrginNm())) {
        logger.info("index : "+i+" delete VO : " +list.get(i).toString());
        list.remove(i);
    }
    else logger.info("index : "+i+" not delete VO : " + list.get(i).toString());
}
cs

이걸 실행하면 원하는 결과를 얻을 수 없다.

 

원인은 list.remove(i) 를 하면서 하나가 삭제되면서 index가 달라지기 때문이다.

시작 시 list.size()가 10였는데 하나를 remove 하면 list.size()는 9이 될테니

 

1. 반복문의 실행 횟수가 의도하지 않게 변하게 되고

2. remove(i)에 사용되는 index 값에도 문제가 될 것이다.

 

또 실수할테지만.. 다음엔.. 삽질은 짧게 하자.. 

 

* 관련글

[java] ArrayList.remove(Integer index) 사용시 이상 : https://deonggi.tistory.com/152

 

728x90
반응형
728x90
반응형
1
2
String str = "abcd.1234";
String[] arrStr = str.split(".");
cs

이 경우 나눠지지 않음.

 

 

1
2
String str = "abcd.1234";
String[] arrStr = str.split("\\.");
cs

이렇게 해야지 배열에 2개의 string으로 나눠짐.

728x90
반응형
728x90
반응형

NumberFormatException : 요약하면 숫자형식 에러

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
String str = "123";
if (isStringDouble(str))
    System.out.println("숫자입니다.");
else
    System.out.println("숫자가 아닙니다.");
}
 
public static boolean isStringDouble(String s) {
    try {
        Double.parseDouble(s);
        return true;
    } catch (NumberFormatException e) {
        return false;
    }
}
cs

 

출처 : http://mwultong.blogspot.com/2006/12/java-isnum-isdouble.html

728x90
반응형

'코딩 삽질' 카테고리의 다른 글

[html, asp] 게시글이 한줄로 나오는 것 수정  (0) 2019.11.24
[asp] write error log at text file  (0) 2019.11.24
[oracle] GRANT (권한)  (0) 2019.11.17
[oracle] link db  (0) 2019.11.17
[git] remote 추가  (0) 2019.11.17
728x90
반응형

난 숫자를 입력한 적없는데?

해당 변수는 문자였고 난 분명 문자를 입력했다.

 

java.lang.NumberFormatException: For input string: "N"

 

보라! 어디가 숫자냐! .....

 

요점은 N 한글자를 'N'로 입력한 아래와 같은 케이스다.

1
2
3
<if test="checkingKey != 'N'">
    AND CHECKING_KEY = #{checkingKey}
</if>
cs

 

아무래도 Java에서 char값을 'N' 같이 사용하기 때문인데,

char형은 결론적으로 숫자형이기 때문에 NumberFormatException이 나는것 같다.

 

해결책은 "checkingKey != 'N'"'checkingKey != "N"' 와 같이 따옴표 사용을 바꿔 주거나

"checkingKey != 'N'.toString()"처럼 .toString() 함수를 써주는 것이다.

 

 

 

출처 : https://yeo-eunny.tistory.com/74

 

 

728x90
반응형

+ Recent posts