๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ–ฅ๏ธ ๋ญ”๊ฐ€๋ญ”๊ฐ€ํ”„๋กœ์ ํŠธ/๐Ÿ› ๏ธ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…

[ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…] QueryDSL .count().fetchOne()์—์„œ ๋ฐœ์ƒํ•˜๋Š” NPE ๊ฒฝ๊ณ  ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

by carrot0911 2025. 5. 26.

๐Ÿ“Œ ๋ฌธ์ œ ์ƒํ™ฉ

QueryDSL๋กœ ์—”ํ‹ฐํ‹ฐ ๊ฐœ์ˆ˜๋ฅผ ์กฐํšŒํ•  ๋•Œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ ์‚ฌ์šฉํ–ˆ๋‹ค.

return queryFactory
    .select(sender.count())
    .from(sender)
    .where(sender.courier.eq(courier), sender.isDeleted.isFalse())
    .fetchOne(); // โš ๏ธ ๊ฒฝ๊ณ  ๋ฐœ์ƒ!

์ด ์ฝ”๋“œ์—์„œ IDE ๋˜๋Š” ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ๊ณ ๊ฐ€ ๋„์›Œ์กŒ๋‹ค.

โ— Unboxing of 'fetchOne()' may produce 'NullPointerException'

 

 

๐Ÿ” ์™œ ์ด๋Ÿฐ ๊ฒฝ๊ณ ๊ฐ€ ๋ฐœ์ƒํ• ๊นŒ?

  • fetchOne()์€ nullableํ•œ Long ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • ํ•˜์ง€๋งŒ ๋ฐ˜ํ™˜ ํƒ€์ž…์„ long(๊ธฐ๋ณธํ˜•)์œผ๋กœ ์„ ์–ธํ•ด๋ฒ„๋ฆฌ๋ฉด → ์–ธ๋ฐ•์‹ฑ ๊ณผ์ •์—์„œ null์ด๋ฉด NPE ๋ฐœ์ƒ!

์ฆ‰, ์ด ์ฝ”๋“œ๋Š” ์‹คํ–‰ ์ค‘ NPE๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์œ„ํ—˜์ด ์žˆ๋‹ค๋Š” ์˜๋ฏธ๋‹ค.

 

 

๐Ÿ” ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

๋ฐฉ๋ฒ• 1. Optional์„ ํ™œ์šฉํ•ด ์•ˆ์ „ํ•˜๊ฒŒ ์–ธ๋ฐ•์‹ฑ

Long count = queryFactory
    .select(sender.count())
    .from(sender)
    .where(sender.courier.eq(courier), sender.isDeleted.isFalse())
    .fetchOne();

return Optional.ofNullable(count).orElse(0L);

๋ฐฉ๋ฒ• 2. ์‚ผํ•ญ ์—ฐ์‚ฐ์ž ์‚ฌ์šฉ

Long count = queryFactory
    .select(sender.count())
    .from(sender)
    .where(sender.courier.eq(courier), sender.isDeleted.isFalse())
    .fetchOne();

return count != null ? count : 0L;

๋ฐฉ๋ฒ• 3. ํ•œ ์ค„๋กœ ์ฒ˜๋ฆฌ (๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ์Œ)

return Optional.ofNullable(
    queryFactory
        .select(sender.count())
        .from(sender)
        .where(sender.courier.eq(courier), sender.isDeleted.isFalse())
        .fetchOne()
).orElse(0L);

 

 

 

๐Ÿ’ก ์–ธ์ œ null์ด ๋ฐ˜ํ™˜๋  ์ˆ˜ ์žˆ์„๊นŒ?

  • .count()๋Š” ๋ณดํ†ต 0์„ ๋ฐ˜ํ™˜ํ•  ๊ฒƒ ๊ฐ™์ง€๋งŒ,
  • QueryDSL์˜ .fetchOne()์€ ์กฐ๊ฑด์ด ์™„์ „ํžˆ ๋ฐฐ์ œ๋˜๋ฉด null์ด ๋  ์ˆ˜ ์žˆ์Œ
  • ๋”ฐ๋ผ์„œ ์•ˆ์ „ํ•˜๊ฒŒ null ์ฒดํฌ๋ฅผ ํ•ด์ฃผ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.