Spring

Spring 데이터 JDBC에 jsonb postgres 형식 사용

기록만이살길 2021. 3. 20. 05:07
반응형

Spring 데이터 JDBC에 jsonb postgres 형식 사용

1. 질문(문제점):

다음 테스트 테이블이 있습니다.

CREATE TABLE user (
  id UUID NOT NULL PRIMARY KEY DEFAULT uuid_generate_v4(),
  name VARCHAR(100),
  address jsonb
)

내가 원하는 것은이 테이블을 엔터티에로드하는 것입니다.

public class Buddy{
  @Id
  private UUID id;
  private String name;
  private Address address;

  //getter and setter
}

주소는 다음과 같습니다.

public class Address {
    @JsonProperty("name")
    public String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

내 json 문자열을 java Pojo로 변환하는 방법이 명확하지 않습니까? 가능합니까, 아니면 범위를 벗어 났습니까?

2. 해결방안:

SpringData JDBC 사용

샘플 데이터-PostgreSQL에서 'user'라는 데이터베이스 테이블을 생성 할 수 없습니다.

drop table users;

CREATE TABLE users (
    id VARCHAR(10) NOT NULL PRIMARY KEY,
    name VARCHAR(100),
    address jsonb
);


insert into users values('1', 'Jhon Doe', '{ "name": "Main St Anytown, USA"}');

저장소

@Repository
public interface BuddyRepository extends CrudRepository<Buddy, String>{

}

변환기를 만들고 등록 할 수 있습니다.

@Configuration
@ComponentScan("com.example.demo")
public class Config extends AbstractJdbcConfiguration {

    @Bean
    public DataSource pgDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("org.postgresql.Driver");
        dataSource.setUrl("jdbc:postgresql://localhost:5432/db");
        dataSource.setUsername("postgres");
        dataSource.setPassword("postgres");

        return dataSource;
    }

    @Bean
    public JdbcCustomConversions jdbcCustomConversions() {
        final List<Converter<?, ?>> converters = new ArrayList<>();
        converters.add(EntityWritingConverter.INSTANCE);
        converters.add(EntityReadingConverter.INSTANCE);
        return new JdbcCustomConversions(converters);
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    @WritingConverter
    enum EntityWritingConverter implements  Converter<Address, PGobject> {
        INSTANCE;
        @Override
        public PGobject convert(Address source) {
            ObjectMapper objectMapper = new ObjectMapper();

            PGobject jsonObject = new PGobject();
            jsonObject.setType("json");
            try {
                jsonObject.setValue(objectMapper.writeValueAsString(source));
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            return jsonObject;
        }
    }

    @ReadingConverter
    enum EntityReadingConverter implements  Converter<PGobject, Address> {
        INSTANCE;
        @Override
        public Address convert(PGobject pgObject) {
             ObjectMapper objectMapper = new ObjectMapper();
            String source = pgObject.getValue();
            try {
                return objectMapper.readValue(source, Address.class);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
}

운영

@Autowired
    BuddyRepository repository;

    @Override
    public void run(String... arg0) throws Exception {
        Optional<Buddy> pojo = repository.findById("1");
        System.out.println(pojo.get().id);
        System.out.println(pojo.get().address.getName());
    }

결과

1 Main St Anytown, 미국

JPA 및 Hibernate 사용

이 방법으로 시도

Maven 의존성

<dependency>
    <groupId>com.vladmihalcea</groupId>
    <artifactId>hibernate-types-52</artifactId>
    <version>${hibernate-types.version}</version>
</dependency>

또는 Gradle 의존성

compile group: 'com.vladmihalcea', name: 'hibernate-types-52', version: '1.0.0'

-

import com.vladmihalcea.hibernate.type.json.JsonBinaryType
import org.hibernate.annotations.TypeDef

@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
public class Buddy{
  @Id
  private UUID id;
  private String name;

  @Type(type = "jsonb")
  @Column(columnDefinition = "jsonb")
  private Address address;

  //getter and setter
}


@JsonInclude(JsonInclude.Include.NON_NULL)
public class Address {
    @JsonProperty("name")
    public String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
65656089
반응형