오류: 열이 json 유형이지만 최대 절전 모드에서 식이 다양한 유형의 문자입니다.
스프링 데이터 jpa를 사용하여 엔티티 클래스 열 두 개를 postgres에 json으로 매핑해야 합니다.여러 스택 오버플로 게시물 및 배들둥 게시물을 읽은 후,
JPA로 지도 JSON 열을 Java Object에 매핑하는 방법
https://www.baeldung.com/hibernate-persist-json-object
아래와 같이 구성하였습니다.그러나 오류가 발생했습니다. "ERROR: 열 "headers"는 json 유형이지만 식은 문자 유형이 다릅니다."
이 문제를 해결할 포인터를 제공하십시오.
아래와 같은 엔티티 클래스가 있습니다.
@Entity
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class Task {
@Id
@GeneratedValue(strategy = IDENTITY)
private Integer id;
private String url;
private String httpMethod;
@Convert(converter = HashMapConverter.class)
@Column(columnDefinition = "json")
private Map<String, String> headers;
@Convert(converter = HashMapConverter.class)
@Column(columnDefinition = "json")
private Map<String, String> urlVariables;
}
엔티티가 지속되는지 여부를 테스트하기 위해 테스트 클래스를 만들었습니다.이 Junit을 실행할 때 아래 테스트 사례가 아래와 같은 오류로 실패하고 있습니다.
@SpringBootTest
class TaskRepositoryTest {
private static Task randomTask = randomTask();
@Autowired
private TaskRepository taskRepository;
@BeforeEach
void setUp() {
taskRepository.deleteAll();
taskRepository.save(randomTask);
}
public static Task randomTask() {
return randomTaskBuilder().build();
}
public static TaskBuilder randomTaskBuilder() {
Map<String,String> headers = new HashMap<>();
headers.put(randomAlphanumericString(10),randomAlphanumericString(10));
Map<String,String> urlVariables = new HashMap<>();
urlVariables.put(randomAlphanumericString(10),randomAlphanumericString(10));
return builder()
.id(randomPositiveInteger())
.httpMethod(randomAlphanumericString(10))
.headers(headers)
.urlVariables(urlVariables)
.url(randomAlphanumericString(10)));
}
}
liquibase를 사용하여 postgres DB에 테이블을 생성했고 열 데이터 유형을 json으로 볼 수 있었습니다.
databaseChangeLog:
- changeSet:
id: 1
author: abc
changes:
- createTable:
tableName: task
columns:
- column:
name: id
type: int
autoIncrement: true
constraints:
primaryKey: true
- column:
name: url
type: varchar(250)
constraints:
nullable: false
unique: true
- column:
name: http_method
type: varchar(50)
constraints:
nullable: false
- column:
name: headers
type: json
- column:
name: url_variables
type: json
rollback:
- dropTable:
tableName: task
이곳에 도착한 사람은 누구나 사용할 수 있습니다.JdbcTemplate
이 오류를 해결하는 방법은 매우 간단합니다.SQL 문에서 다음을 사용하여 JSON 인수를 캐스트합니다.::jsonb
.
예.String INSERT_SQL = "INSERT INTO xxx (id, json_column) VALUES(?, ?)";
된다String INSERT_SQL = "INSERT INTO xxx (id, json_column) VALUES(?, ?::jsonb)";
위의 구성이 작동하지 않았습니다.
따라서 사용 사례를 해결하기 위해 아래 링크를 따라갔습니다.
https://vladmihalcea.com/how-to-map-json-objects-using-generic-hibernate-types/
"Provider com.fasterxml.jackson.module.jaxb.Spring Boot 업그레이드 후 "Jaxb Annotation Module을 찾을 수 없음"
pom.xml에 종속성이 추가되었습니다.
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>2.9.11</version>
</dependency>
HashMapConverter 구성을 제거하고 엔티티 클래스에서 아래와 같이 변경했습니다.
@Entity
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@ToString(callSuper = true)
@TypeDefs({
@TypeDef(name = "json", typeClass = JsonStringType.class),
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
})
public class Task {
@Id
@GeneratedValue(strategy = IDENTITY)
private Integer id;
private String url;
private String httpMethod;
@Type(type = "jsonb")
@Column(columnDefinition = "json")
private Map<String, String> headers;
@Type(type = "jsonb")
@Column(columnDefinition = "json")
private Map<String, String> urlVariables;
}
이러한 변경 후에는 태스크테스트 통과.
다음을 사용한 대체 솔루션org.hibernate.annotations.ColumnTransformer
샘플 엔티티
import org.hibernate.annotations.ColumnTransformer;
@Entity
@Table
public class SomeEntity {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@Column(name = "some_class", columnDefinition = "jsonb")
@Convert(converter = SomeClassConvertor.class)
@ColumnTransformer(write = "?::jsonb")
private SomeClass someClass;
}
샘플 변환기
import java.io.IOException;
import javax.persistence.AttributeConverter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.airtel.africa.entity.SomeClass;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SomeClassConvertor implements AttributeConverter<SomeClass, String> {
@Autowired
ObjectMapper objectMapper;
@Override
public String convertToDatabaseColumn(SomeClass someClass) {
String someClassJson = null;
try {
someClassJson = objectMapper.writeValueAsString(someClass);
} catch (final JsonProcessingException e) {
log.error("JSON writing error", e);
}
return someClassJson;
}
@Override
public SomeClass convertToEntityAttribute(String someClassJSON) {
SomeClass someClass = null;
if (StringUtils.isBlank(someClassJSON)) {
return someClass;
}
try {
someClass = objectMapper.readValue(someClassJSON, someClass.class);
} catch (final IOException e) {
log.error("JSON reading error", e);
}
return someClass;
}
}
MySQL 8.0.21에서 Postgres 13으로 프로젝트를 마이그레이션할 때 이 문제가 발생했습니다.내 프로젝트는 최대 절전 모드 유형 종속성 버전 2.7.1과 함께 Spring boot을 사용합니다.저의 경우 해결책은 간단했습니다.
제가 해야 할 일은 그것을 바꾸는 것이었고 그것은 작동했습니다.
(후대를 위하여)완전히 안전하지는 않지만(문자열에서/문자열로 자동 캐스트) 제어하는 중요하지 않은 또는 데이터/구조에 적합한 대안이 있습니다.
postgresql 연결 문자열에 ?stringtype=unspecified를 추가합니다.
예: (application.yml에서)
spring:
datasource:
url: jdbc:postgresql://localhost:5432/dbname?stringtype=unspecified
이것은 postgresql이 당신의 문자열을 json에 자동으로 캐스트하도록 할 것입니다.추가 가져오기나 @type 정의 또는 사용자 지정 sql-query가 필요하지 않습니다. 질문의 예는 다음과 같습니다.
@Convert(converter = HashMapConverter.class)
@Column(columnDefinition = "json")
private Map<String, String> headers;
PPS: 저는 jsonb나 다른 데이터베이스 공급업체와 함께 이것을 시도해 본 적이 없습니다.
언급URL : https://stackoverflow.com/questions/65478350/error-column-is-of-type-json-but-expression-is-of-type-character-varying-in-hib
'source' 카테고리의 다른 글
Jquery Ajax에서 요청에 헤더를 추가하는 방법은 무엇입니까? (0) | 2023.08.24 |
---|---|
텍스트 보기에서 글머리 기호를 추가하려면 어떻게 해야 합니까? (0) | 2023.08.24 |
jQuery 셀렉터에서 선두 콜론의 목적은 무엇입니까? (0) | 2023.08.24 |
asp.net c#의 Web.config 파일에서 시작 페이지를 설정하는 방법 (0) | 2023.08.24 |
null 값으로 날짜 열을 인덱싱하는 방법은 무엇입니까? (0) | 2023.08.24 |