기준: springboot 2.1.9
JPA를 사용하는 이유가
객체지향적인 설계와 개발 생산성을 위함인데,
왜 String을 여러라인으로 붙여 쓰고 있지? + + + + + +
왜 SQL 결과를 Object[]로 받는 방법을 사용하는지 이해가 안된다.
(다시 10년전 과거로 돌아간 기분이다...)
ResultMapping을 어노테이션으로 잡다하게 설정하는게 과연 Mybatis에서 JPA로 탈출한 취지에 맞는가?
String 여러 라인을 붙여쓰거나
리턴으로 Object[]로 받을거면
그냥 Mybatis 쓰는게 낫겠다.
* multiLine String은 XML로...
* Object[]은 Dto로 해결...
native query + XML + DTO
org.example.api.dto.NativeDto1.java
package org.example.api.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Data
public class NativeDto1 {
private Long id;
private String name;
private Long aaa;
private String bbb;
}
repository.java
package org.example.repositories;
import java.util.List;
import org.example.api.dto.NativeDto1;
import org.example.models.Team;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface TeamRepository extends JpaRepository<Team, Long>{
@Query(nativeQuery = true)
public List<NativeDto1> findByName4(@Param("name") String aaa);
}
META-INF/orm.xml
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm" version="2.2">
<named-native-query name="Team.findByName4" result-set-mapping="aaaaa5">
<query>
<![CDATA[
select
t.id as id,
t.name as name,
m.id as aaa,
m.name as bbb
from team t
inner join Member m
on t.id = m.team_id
where t.name = :name
]]></query>
</named-native-query>
<sql-result-set-mapping name="aaaaa5">
<constructor-result target-class="org.example.api.dto.NativeDto1">
<column name="id" class="java.lang.Long" />
<column name="name" />
<column name="aaa" class="java.lang.Long" />
<column name="bbb" />
</constructor-result>
</sql-result-set-mapping>
</entity-mappings>
주의!!!!
repository에서 @Query(nativeQuery = true) 를 하지 않으면 다음 에러가 발생한다.
Got different size of tuples and aliases; nested exception is org.hibernate.HibernateException: Got different size of tuples and aliases
xml에 <named-native-query>를 사용했는데, 왜 또 설정을 해야 하나?
org.hibernate.jpa.spi.NativeQueryTupleTransformer
public NativeTupleImpl(Object[] tuple, String[] aliases) {
// ...
if ( tuple.length != aliases.length ) {
throw new HibernateException( "Got different size of tuples and aliases" );
}
// ...
}
디버깅해보면... (size가 안맞긴 안맞네...)
tuple쪽은 이미 Dto생성자로 잘 만들었는데, 왜 aliases는 여전히 sql column으로 비교를 하는 걸까?
@Query(nativeQuery = true)를 사용하면, NativeTupleImpl 함수 자체를 실행하지 않는다.
아.. NativeQueryTupleTransformer 클래스 자체에 들어오지 않네!!
참고:
springboot 2.4.4 에서도 아직 해결이 되지 않았다.-_-;
==============================================================
DTO를 사용하지 않으면, Object[]로 받아야 한다.
public List<Object[]> findByName4(@Param("name") String aaa);
<named-native-query name="Team.findByName4" result-set-mapping="aaaaa5">
<query>
<![CDATA[
select
t.id as id,
t.name as name,
m.id as aaa,
m.name as bbb
from team t
inner join Member m
on t.id = m.team_id
where t.name = :name
]]></query>
</named-native-query>
<sql-result-set-mapping name="aaaaa5">
<entity-result entity-class="org.example.models.Team" />
<column-result name="aaa" />
<column-result name="bbb" />
</sql-result-set-mapping>
Object[0] 에는 Team
Object[1] 에는 aaa
Object[2] 에는 bbb
==============================================================
// TODO
<constructor-result>를 사용하면서
entity는 entity대로 받고, 나머지 컬럼만 따로 받으면 가장 좋을듯
'Java > Spring' 카테고리의 다른 글
[security] getPassword() is null (0) | 2021.05.06 |
---|---|
[Spring data JPA] 조회: Entity + 연관 Entity(LAZY) + Pageable (0) | 2021.04.24 |
JPA 씹어먹기 (0) | 2021.04.19 |
springBoot2 jpa Test Errors (1) | 2021.04.05 |
[spring을 spring 답게] net.sf.log4jdbc.sql.jdbcapi.DriverSpy (0) | 2020.03.28 |