Postgre 저장 방법Spring Boot + JPA를 사용한SQL jsonb?
REST 서비스의 알 수 없는 데이터를 소비하는 이행 소프트웨어를 개발하고 있습니다.
이미 MongoDB를 사용할까 생각중이지만 사용하지 않고 Postgre를 사용하기로 했습니다.SQL.
이 글을 읽은 후 Spring JPA를 사용하여 Spring Boot 앱에 구현하려고 하는데 매핑을 할 수 없습니다.jsonb
내 실체에 있어
시도해 봤지만 아무것도 이해하지 못했어!
여기가 제 위치입니다.
@Repository
@Transactional
public interface DnitRepository extends JpaRepository<Dnit, Long> {
@Query(value = "insert into dnit(id,data) VALUES (:id,:data)", nativeQuery = true)
void insertdata( @Param("id")Integer id,@Param("data") String data );
}
그리고...
@RestController
public class TestController {
@Autowired
DnitRepository dnitRepository;
@RequestMapping(value = "/dnit", method = RequestMethod.GET)
public String testBig() {
dnitRepository.insertdata(2, someJsonDataAsString );
}
}
및 표:
CREATE TABLE public.dnit
(
id integer NOT NULL,
data jsonb,
CONSTRAINT dnit_pkey PRIMARY KEY (id)
)
이거 어떻게 해?
주의: 작업하는 엔티티는 필요 없습니다.JSON은 항상 String이지만 DB를 쿼리하려면 jsonb가 필요합니다.
시도해 봤지만 아무것도 이해하지 못했어!
Spring Data JPA(Hibernate) 프로젝트에서 Vlad Mihalcea의 hibernate-types lib를 완전히 사용하려면 다음 작업을 수행합니다.
1) 이 lib를 프로젝트에 추가합니다.
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>2.2.2</version>
</dependency>
2) 다음으로 엔티티에서 예를 들어 다음과 같은 유형을 사용합니다.
@Data
@NoArgsConstructor
@Entity
@Table(name = "parents")
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
public class Parent implements Serializable {
@Id
@GeneratedValue(strategy = SEQUENCE)
private Integer id;
@Column(length = 32, nullable = false)
private String name;
@Type(type = "jsonb")
@Column(columnDefinition = "jsonb")
private List<Child> children;
@Type(type = "jsonb")
@Column(columnDefinition = "jsonb")
private Bio bio;
public Parent(String name, List children, Bio bio) {
this.name = name;
this.children = children;
this.bio = bio;
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Child implements Serializable {
private String name;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Bio implements Serializable {
private String text;
}
다음 예를 정도 하다'라는 있을 거예요.JpaRepository
다음 중 하나:
public interface ParentRepo extends JpaRepository<Parent, Integer> {
}
parentRepo.save(new Parent(
"parent1",
asList(new Child("child1"), new Child("child2")),
new Bio("bio1")
)
);
Parent result = parentRepo.findById(1);
List<Child> children = result.getChildren();
Bio bio = result.getBio();
단순한 삽입문을 실행하기 위해 Spring Data JPA를 추가함으로써 작업이 지나치게 복잡해지고 있습니다.JPA 기능을 사용하지 않습니다.대신 다음을 수행합니다.
spring-boot-starter-data-jpa
spring-boot-starter-jdbc
DnitRepository
- 「」를
JdbcTemplate
서 '주입'을 합니다.DnitRepository
dnitRepository.insertdata(2, someJsonDataAsString );
jdbcTemplate.executeUpdate("insert into dnit(id, data) VALUES (?,to_json(?))", id, data);
이미 플레인 SQL(매우 복잡한 방식)을 사용하고 있었기 때문에 플레인 SQL이 필요한 경우(JPA가 필요하지 않은 경우) 그냥 SQL을 사용하십시오.
직접 JdbcTemplate
이러한 논리/복잡함을 저장소 또는 서비스에서 숨길 수 있습니다.
이미 몇 가지 답변이 있고 몇 가지 경우에 효과가 있을 것이라고 확신합니다.모르는 의존관계를 더 이상 사용하고 싶지 않기 때문에 다른 솔루션을 찾고 있습니다.중요한 부분은 AttributeConverter입니다.이 AttributeConverter는 jsonb를 DB에서 객체로 매핑하거나 그 반대로 매핑합니다.따라서 엔티티 내의 jsonb 컬럼 속성에 @Convert를 주석을 붙이고 AttributeConverter를 링크하고 @Column(Column Definition = "jsonb")도 추가해야 합니다.그러면 JPA는 DB에서 이것이 어떤 유형인지 알 수 있습니다.이것으로 스프링 부트애플리케이션을 기동할 수 있게 됩니다.그러나 JpaRepository에서 save()를 시도하면 문제가 발생합니다.메시지를 받았습니다.
PSQLException: ERROR: "myColumn" 열은 jsonb 유형이지만 식이 다양한 유형입니다.
힌트: 식을 다시 쓰거나 캐스팅해야 합니다.
이것은 postgres가 유형을 약간 심각하게 받아들이기 때문에 발생합니다.이 문제는 다음 변경으로 해결할 수 있습니다.
데이터 소스hikari.data-source-properties: string type=미지정
datasource.datas.connection-properties: stringtype=미지정
그 후, 그것은 마법처럼 나에게 효과가 있었고, 여기 최소한의 예가 있다.JpaRepository를 사용합니다.
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface MyEntityRepository extends JpaRepository<MyEntity, Integer> {
}
엔티티:
import javax.persistence.Column;
import javax.persistence.Convert;
public class MyEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Integer id;
@Convert(converter = MyConverter.class)
@Column(columnDefinition = "jsonb")
private MyJsonObject jsonContent;
}
json 모델:
public class MyJsonObject {
protected String name;
protected int age;
}
변환기는 여기서 Gson을 사용하지만 원하는 대로 매핑할 수 있습니다.
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
@Converter(autoApply = true)
public class MyConverter implements AttributeConverter<MyJsonObject, String> {
private final static Gson GSON = new Gson();
@Override
public String convertToDatabaseColumn(MyJsonObject mjo) {
return GSON.toJson(mjo);
}
@Override
public MyJsonObject convertToEntityAttribute(String dbData) {
return GSON.fromJson(dbData, MyJsonObject.class);
}
}
SQL:
create table my_entity
(
id serial primary key,
json_content jsonb
);
그리고 my application.yml (application.properties)
datasource:
hikari:
data-source-properties: stringtype=unspecified
tomcat:
connection-properties: stringtype=unspecified
이 경우, 저는 위의 맞춤형 컨버터 클래스를 사용하므로, 자유롭게 라이브러리에 추가할 수 있습니다.EclipseLink JPA Provider와 연동하고 있습니다.
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.log4j.Logger;
import org.postgresql.util.PGobject;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Map;
@Converter
public final class PgJsonbToMapConverter implements AttributeConverter<Map<String, ? extends Object>, PGobject> {
private static final Logger LOGGER = Logger.getLogger(PgJsonbToMapConverter.class);
private static final ObjectMapper MAPPER = new ObjectMapper();
@Override
public PGobject convertToDatabaseColumn(Map<String, ? extends Object> map) {
PGobject po = new PGobject();
po.setType("jsonb");
try {
po.setValue(map == null ? null : MAPPER.writeValueAsString(map));
} catch (SQLException | JsonProcessingException ex) {
LOGGER.error("Cannot convert JsonObject to PGobject.");
throw new IllegalStateException(ex);
}
return po;
}
@Override
public Map<String, ? extends Object> convertToEntityAttribute(PGobject dbData) {
if (dbData == null || dbData.getValue() == null) {
return null;
}
try {
return MAPPER.readValue(dbData.getValue(), new TypeReference<Map<String, Object>>() {
});
} catch (IOException ex) {
LOGGER.error("Cannot convert JsonObject to PGobject.");
return null;
}
}
}
사용 예, 엔티티에 대한 이름Customer
.
@Entity
@Table(schema = "web", name = "customer")
public class Customer implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Convert(converter = PgJsonbToMapConverter.class)
private Map<String, String> info;
public Customer() {
this.id = null;
this.info = null;
}
// Getters and setter omitted.
R2DBC를 사용하는 경우 종속성을 사용할 수 있습니다.io.r2dbc:r2dbc-postgresql
, 및 타입을 사용합니다.io.r2dbc.postgresql.codec.Json
다음과 같이 엔티티 클래스의 멤버 속성에 포함됩니다.
public class Rule {
@Id
private String client_id;
private String username;
private String password;
private Json publish_acl;
private Json subscribe_acl;
}
언급URL : https://stackoverflow.com/questions/51276703/how-to-store-postgresql-jsonb-using-springboot-jpa
'source' 카테고리의 다른 글
React useState() 후크를 사용한 상태 개체 업데이트 및 병합 (0) | 2023.02.16 |
---|---|
python에서 json 문자열을 개체로 역직렬화합니다. (0) | 2023.02.16 |
MongoDB GUI 클라이언트(크로스 플랫폼 또는 Linux) (0) | 2023.02.16 |
오류: ORA-01704: 문자열 리터럴이 너무 깁니다. (0) | 2023.02.16 |
html에서 rootScope 변수 사용 (0) | 2023.02.16 |