воскресенье, 18 января 2015 г.

Hibernate Enum + Hstore

PostgreSQL has a lot of pecific types, which need a workaround in different ORM frameworks. In this article I want to show my way of dealing with such types as Enum and Hstore in Hibernate.


Google can help you find some examples that offer to implement org.hibernate.usertype.UserType interface. However, I'll show here my variant of using Enum and Hstore in Hibernate. It seems to me, this methods are easier and quicker to implement.

Enum

Let's say you have a dispute_status enum in a database and a table with such field:
CREATE TYPE dispute_status AS ENUM ('CREATED', 'JOINED', 'CLOSED');

CREATE TABLE Dispute(
    id serial  NOT NULL,
    status dispute_status  NOT NULL,
    CONSTRAINT PK_Dispute PRIMARY KEY (id)
);

And we want to map it to a Java enum:
Status.java
package org.project.model.type;

public enum Status {
  CREATED, JOINED, CLOSED
}

First, we have to create an Entity class:
Dispute.java
 package org.project.model;

import java.io.Serializable;
import javax.persistence.*
import javax.validation.constraints.NotNull;

import org.project.model.type.Status;

@Entity
@Table(name = "dispute")
public class Dispute implements Serializable {
  
private static final long serialVersionUID = 1L;
  
  public Dispute () {
    
  }
  
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(columnDefinition = "serial")
  private Integer id;
  
  @NotNull
  @Enumerated(EnumType.STRING)
  private Status status;
  
  public Integer getId() {
    return id;
  }

  public Status getStatus() {
    return status;
  }

  public void setId(Integer id) {
    this.id = id;
  }

  public void setStatus(Status status) {
    this.status = status;
  }
  
}

And that's it. So easy. Now you cat work with it:
Query myDisputeQuery = sessionFactory.getCurrentSession()
            .createQuery("from Dispute d where d.id=:d_id")
            .setParameter("d_id", 0);
Dispute dispute = myDisputeQuery.uniqueResult();
System.out.println(dispute.getStatus());

Hstore

Hibernate has a very good class org.postgresql.util.HStoreConverter, which help you to work with hstore PG type. It has method fromString that helps you to get a java Map object from a String, and toString that converts Map to a String that is compatible with PG hstore type. So we can use it in getter and setter of  ther Entity hstore field:
import java.io.Serializable;
import java.sql.SQLException;
import java.util.Map;

import javax.persistence.*
import javax.validation.constraints.NotNull;

import org.postgresql.util.HStoreConverter;

@Entity
@Table(name = "properties")
public class Properties implements Serializable {

  private static final long serialVersionUID = 1L;
  
  public Properties() {
    
  }
  
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(columnDefinition = "serial")
  private Integer id;
  
  @NotNull
  @Column(columnDefinition = "hstore")
  private String params;
  
  public Integer getId() {
    return id;
  }

  public void setId(Integer id) {
    this.id = id;
  }

  public Map getParams() {
    return HStoreConverter.fromString(params);
  }

  public void setParams(Map params) throws SQLException {
    this.params = HStoreConverter.toString(params);
  } 
  
}

So now, when you select from Properties table you can get Map<String, String> easily:
Properties properties = 
            (Properties )sessionFactory.getCurrentSession().createQuery("from Properties p where p.id=:p_id")
                    .setParameter("p_id", 0).uniqueResult();
System.out.println(properties.getParams()); // a usual map.toString() output

0 коммент.:

Отправить комментарий