μΉμ 4. λ°μ΄ν° μ κ·Ό κΈ°μ - MyBatis μκ° μλ£!!
MyBatisλ JdbcTemplateλ³΄λ€ λ λ§μ κΈ°λ₯μ μ 곡νλ SQL Mapperμ΄λ€.
MyBatisλ SQLμ XMLμ νΈλ¦¬νκ² μμ±ν μ μκ³ , λμ 쿼리λ₯Ό λ§€μ° νΈλ¦¬νκ² μμ±ν μ μλ€λ μ₯μ μ΄ μλ€.
μ€μ μ μ₯λ¨μ
JdbcTemplateμ μ€νλ§μ λ΄μ₯λ κΈ°λ₯μ΄λΌ λ³λμ μ€μ μμ΄ μ¬μ©ν μ μλ€. λ°λ©΄ MyBatisλ μ½κ°μ μ€μ μ΄ νμνλ€.
μ 리
νλ‘μ νΈμμ λμ 쿼리μ 볡μ‘ν μΏΌλ¦¬κ° λ§λ€λ©΄ MyBatisλ₯Ό μ¬μ©νκ³ , λ¨μν 쿼리λ€μ΄ λ§μΌλ©΄ JdbcTemplateμ μ¬μ©νλ©΄ λλ€. λ¬Όλ‘ λμ ν¨κ» μ¬μ©ν΄λ λλ€.
μ€μ
mybatis.type-aliases-package
: MyBatisμμ νμ
μ 보λ₯Ό μ¬μ©ν λλ ν¨ν€μ§ μ΄λ¦μ μ μ΄μΌ νλλ°, μ¬κΈ°μ λͺ
μνλ©΄ ν¨ν€μ§ μ΄λ¦μ μλ΅ν μ μλ€.
mybatis.configuration.map-underscore-to-camel-case
: JdbcTemplateμ BeanPropertyRowMapper
μ²λΌ μΈλλ°λ₯Ό μΉ΄λ© μΌμ΄μ€λ‘ μλ λ³κ²½ν΄μ£Όλ κΈ°λ₯μ νμ±ννλ€.
μ°Έκ³ - κ΄λ‘μ λΆμΌμΉ
μλ° κ°μ²΄μλ μ£Όλ‘ μΉ΄λ© μΌμ΄μ€λ₯Ό μ¬μ©νκ³ , κ΄κ³ν λ°μ΄ν°λ² μ΄μ€μμλ μ£Όλ‘ μ€λ€μ΄ν¬ μΌμ΄μ€λ₯Ό μ¬μ©νλ€.
μ΄λ κ² κ΄λ‘λ‘ λ§μ΄ μ¬μ©νλ€ λ³΄λmap-underscore-to-camel-case
κΈ°λ₯μ νμ±ννλ©΄ μ€λ€μ΄ν¬ μΌμ΄μ€λ₯Ό μΉ΄λ© μΌμ΄μ€λ‘ μλ λ³νν΄μ€λ€. λ°λΌμ DBμμselect item_name
μΌλ‘ μ‘°νν΄λ κ°μ²΄μitemName(setItemName())
μμ±μ κ°μ΄ μ μ μ λ ₯λλ€.
ν΄λΉ μ΅μ μ μΌλ©΄ μ€λ€μ΄ν¬ μΌμ΄μ€λ μλμΌλ‘ ν΄κ²°λκ³ , μ»¬λΌ μ΄λ¦κ³Ό κ°μ²΄ μ΄λ¦μ΄ μμ ν λ€λ₯Έ κ²½μ°μλ μ‘°ν SQLμμ λ³μΉ(as)μ μ¬μ©νλ©΄ λλ€.
<insert id="save" useGeneratedKeys="true" keyProperty="id">
insert into item (item_name, price, quantity)
values (#{itemName}, #{price}, #{quantity})
</insert>
<insert>
λ₯Ό μ¬μ©νλ©΄ λλ€.#{}
λ¬Έλ²μ μ¬μ©νλ©΄ λλ€. κ·Έλ¦¬κ³ λ§€νΌμμ λκΈ΄ κ°μ²΄μ νλ‘νΌν° μ΄λ¦μ μ μ΄μ£Όλ©΄ λλ€.#{}
λ¬Έλ²μ μ¬μ©νλ©΄ PreparedStatement
λ₯Ό μ¬μ©νλ€. JDBCμ ?
λ₯Ό μΉννλ€κ³ μκ°νλ©΄ λλ€.void update(@Param("id") Long id, @Param("updateParam") ItemUpdateDto updateParam);
<update id="update">
update item
set item_name=#{updateParam.itemName},
price=#{updateParam.price},
quantity=#{updateParam.quantity}
where id = #{id}
</update>
<update>
λ₯Ό μ¬μ©νλ©΄ λλ€.@Param
μ μ§μ νμ§ μμλ λμ§λ§, νλΌλ―Έν°κ° 2κ° μ΄μμ΄λ©΄ @Param
μΌλ‘ μ΄λ¦μ μ§μ ν΄μ νλΌλ―Έν°λ₯Ό ꡬλΆν΄μΌ νλ€.<select id="findById" resultType="Item">
select id, item_name, price, quantity
from item
where id = #{id}
</select>
<select>
λ₯Ό μ¬μ©νλ©΄ λλ€.Item
κ°μ²΄μ 맀ννλ€. SELECT SQLμ κ²°κ³Όλ₯Ό νΈλ¦¬νκ² λ°λ‘ κ°μ²΄λ‘ λ³νν΄μ€λ€.Item
, Optional<Item>
κ³Ό κ°μ΄ μ¬μ©νλ©΄ λκ³ , λ°ν κ°μ²΄κ° νλ μ΄μμ΄λ©΄ 컬λ μ
μ μ¬μ©νλ©΄ λλ€. μ£Όλ‘ List
λ₯Ό μ¬μ©νλ€.<select id="findAll" resultType="Item">
select id, item_name, price, quantity
from item
<where>
<if test="itemName != null and itemName != ''">
and item_name like concat('%',#{itemName},'%')
</if>
<if test="maxPrice != null">
and price <= #{maxPrice}
</if>
</where>
</select>
<where>
, <if>
κ°μ λμ 쿼리 λ¬Έλ²μ ν΅ν΄ νΈλ¦¬ν λμ 쿼리λ₯Ό μ§μνλ€.<if>
λ ν΄λΉ μ‘°κ±΄μ΄ λ§μ‘±νλ©΄ ꡬ문μ μΆκ°νλ€.<where>
λ μ μ νκ² where λ¬Έμ₯μ λ§λ€μ΄μ€λ€.<if>
κ° λͺ¨λ μ€ν¨νκ² λλ©΄ SQL whereλ₯Ό λ§λ€μ§ μλλ€.<if>
κ° νλλΌλ μ±κ³΅νλ©΄ μ²μ λνλλ and
λ₯Ό whereλ‘ λ³ννλ€.μ ν리μΌμ΄μ
λ‘λ© μμ μ MyBatis μ€νλ§ μ°λ λͺ¨λμ @Mapper
κ° λΆμ μΈν°νμ΄μ€λ₯Ό μ‘°μ¬νλ€.
ν΄λΉ μΈν°νμ΄μ€κ° λ°κ²¬λλ©΄ λμ νλ‘μ κΈ°μ μ μ¬μ©ν΄μ ItemMapper
μΈν°νμ΄μ€μ ꡬν체λ₯Ό λ§λ λ€.
μμ±λ ꡬν체λ₯Ό μ€νλ§ λΉμΌλ‘ λ±λ‘νλ€.
MyBatis μ€νλ§ μ°λ λͺ¨λμ΄ λ§λ€μ΄μ£Όλ ItemMapper
μ ꡬν체 λλΆμ μΈν°νμ΄μ€λ§μΌλ‘ νΈλ¦¬νκ² XMLμ λ°μ΄ν°λ₯Ό μ°Ύμ νΈμΆν μ μκ² λλ€.
λ§€νΌ κ΅¬ν체λ μμΈ λ³νκΉμ§ μ²λ¦¬ν΄μ€λ€. MyBatisμμ λ°μν μμΈλ₯Ό μ€νλ§ μμΈ μΆμνμΈ DataAccessException
μ λ§κ² λ³νν΄μ λ°ννλ€.
#{}
λ¬Έλ²μ ?
λ₯Ό λ£κ³ νλΌλ―Έν°λ₯Ό λ°μΈλ©νλ PreparedStatement
λ₯Ό μ¬μ©νλ€.
νλΌλ―Έν° λ°μΈλ©μ΄ μλλΌ λ¬Έμ κ·Έλλ‘λ₯Ό μ²λ¦¬νκ³ μΆμ λ ${}
λ₯Ό μ¬μ©νλ©΄ λλ€. λ€λ§ ${}
λ₯Ό μ¬μ©νλ©΄ SQL Injection 곡격μ λΉν μ μκΈ° λλ¬Έμ κ°κΈμ μ¬μ©νμ§ μλ κ²μ΄ μ’λ€.
<sql>
μ μ¬μ©νλ©΄ SQL μ½λλ₯Ό μ¬μ¬μ©ν μ μλ€.
<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>
<select id="selectUsers" resultType="map">
select
<include refid="userColumns"><property name="alias" value="t1"/></include>,
<include refid="userColumns"><property name="alias" value="t2"/></include>
from some_table t1
cross join some_table t2
</select>
<include>
λ₯Ό ν΅ν΄ <sql>
μ‘°κ°μ μ°Ύμμ μ¬μ©ν μ μλ€.
κ²°κ³Όλ₯Ό 맀νν λ ν
μ΄λΈμ user_id
μ΄μ§λ§ κ°μ²΄λ id
μΌ λ, 컬λΌλͺ
κ³Ό κ°μ²΄μ νλ‘νΌν°λͺ
μ΄ λ€λ₯΄λ€. μ΄ λ λ³μΉ(as)μ μ¬μ©νλ©΄ λλ€.
νμ§λ§ λ³μΉμ μ¬μ©νμ§ μκ³ λ λ¬Έμ λ₯Ό ν΄κ²°ν μ μλλ°, λ°λ‘ λ€μκ³Ό κ°μ΄ resultMap
μ μ μΈνλ©΄ λλ€.
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id" />
<result property="username" column="username"/>
<result property="password" column="password"/>
</resultMap>
<select id="selectUsers" resultMap="userResultMap">
select user_id, user_name, hashed_password
from some_table
where id = #{id}
</select>
+) 22. 09. 05. κΈ°λ‘ μΆκ°
λ΄κ° λ°νν λ΄μ©μ μ€νλ§ νΈλμμ !! μλ μ μ DB νΈλμμ λ°ννκ³ κ·Έ λ€μμ λ°λ‘ μ΄μ΄μ μ€νλ§ νΈλμμ μ λν΄ λ°ννλ € νμΌλ λ΄κ° μ€νλ§μ λν΄ μ λ§ λ¬΄μ§ν΄μ... μ΄λ²μ μΈνλ° κ°μλ‘ μ€νλ§ νΈλμμ μ λν΄ μ’ λ°°μ΄ λ€μ λ°ννκ² λλ€.
κ°μ λ€μΌλ©΄μ 곡λΆνμλ λ΄μ©μΌλ‘ μ§ννλ€. pagesλ‘ λ§λ κ°λ¨ λ°ν μλ£ λ³΄μ¬μ£Όλ©΄μ μ μ μ§°λ μ½λλ κ°μ΄ 보μ¬μ£Όκ³ . λλΆμ λ νΌμ λ μκ°μ μ‘μ λ¨Ήμμ§λ§... κ·Έλλ μ΄μ λ°ννλ κ±° νΈλμμ μ λν΄ A to Z λ€ μλ €μ£Όκ³ μΆμ΄μ! λ΄μ©μ μ’ κΈΈκ² μ§°λ€.
κ·Έλμ κ·Έλ°μ§ νΌλλ°±λ μ’κ² λ°μλ€! νμ§λ§ λ΄κ° μκ°ν΄λ μ’... 루μ¦ν΄μ§λ κ°μ΄ μμ§μμ μμμ. λ€μμ μ’ λ λμ λ°νλ₯Ό λͺ©νλ‘... 루μ¦ν΄μ§μ§ μκ² κ΅¬μ±μ μ μ§λ΄μΌκ² λ€.
μΈμ€μ΄κ° λ°νν λ΄μ©μ IPv4μ IPv6. μ΄κ±΄ μ μ λ€νΈμν¬ IPμ λν΄ κ³΅λΆνμ λ μ€μ³μ§λκ°λ― λ°°μ λ 건λ°... μ€λλ§μ λ€μ λ°°μ°λ 볡μ΅νλ λλμ΄λΌ μ’μλ€. κ·Όλ° μ¬μ€ μλΈλ· λ§μ€ν¬μ λν΄μ ... μμ§ μ μ΄ν΄κ° μ κ°. λ°ν λ£λ κ²λ§μΌλ‘λ μ΄ν΄κ° μ μ λλ€. λ΄κ° μ§μ 곡λΆν΄λ΄μΌ μ λ―...
μ§μμ΄κ° λ°νν λ΄μ©μ μλ° μ»΄νμΌ κ³Όμ . μ΄κ±΄ μ μ μΈμ€μ΄κ° λ°ννμλ κ±΄λ° μ΄ μ£Όμ μμ μ€λλ§μ λ€μΌλ μλ‘μ λ€. μμ... μ μλλ΅κ² ν΅μ¬λ§ μμ μλ €μ€μ μ’μμ. κ°κ²°νμ§λ§ λ€μ 건 λ€ λ€μ λλ...!
μ΄μ¨λ μ΄λ² λ°νλ μμ΄ λ§μ μ€λΉνκΈ° νλ€μμ§λ§ κ·Έλλ κ·Έλ§νΌ λΏλ―νλ€. λ€λ€ μ μ΄ν΄ν΄ μ€ κ² κ°μ κΈ°λ»...
ν μ΄ νλ‘μ νΈ κ΄λ ¨ νμλ‘λ μ£Όμ κΈ°λ₯λ€μ΄λ, λͺ μΈμ μ΄λ»κ² 지μ§μ λν΄ μκΈ° λλ΄λ€. κ·Έλ¦¬κ³ μ€ν°λλ£Έ μκ° λ€ λΌμ μ λ λ¨ΉμΌλ¬ κ°...^^
νμ λλκ³ λ¨Ήμ λκ°μ€μΈλ° μ’λ§μ΄μλ€. μΉμ¦κ°... 짱 λΆλλ¬μ! λ§μμλ€! λ λ¨Ήκ³ μΆλ€!