2017-12-18 5 views
0

상자라는 엔터티가 있습니다. 각 상자에는 많은 고유 ID에 대해 동일한 매개 변수가 있습니다. 고유 ID는 숫자이며 다른 역할은 없습니다. 그래서 postgresql에서 텍스트 배열로 만들었고 Java에서 ArrayList로 만들고 사용자 정의 사용자 유형으로 매핑했습니다. package com.geniedoc.utils; postgresql의 텍스트 배열에 포함 된 in/in에 대한 최대 절전 기준

import java.io.Serializable; 
import java.sql.Array; 
import java.sql.Connection; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.sql.Types; 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.Iterator; 
import java.util.List; 
import java.util.StringTokenizer; 
import org.hibernate.HibernateException; 
import org.hibernate.engine.spi.SessionImplementor; 
import org.hibernate.usertype.UserType; 

public class PostgresTextArrayType implements UserType { 

    protected static final int[] SQL_TYPES = {Types.ARRAY}; 
    public Class<String> returnedClass() { 
      return String.class; 
     } 

    public final int[] sqlTypes() { 
      return SQL_TYPES; 
     } 


     @Override 
     public Object nullSafeGet(ResultSet resultSet, String[] names, 
       SessionImplementor arg2, Object arg3) 
       throws HibernateException, SQLException { 
      List<String> list = null; 
      String nameVal = resultSet.getString(names[0]); 
      if (nameVal != null) { 
       nameVal = nameVal.substring(1,nameVal.length()-1); 
       list = new ArrayList<>(); 
       StringTokenizer tokenizer = new StringTokenizer(nameVal, ","); 
       while (tokenizer.hasMoreElements()) { 
        String val = (String) tokenizer.nextElement(); 
        list.add(val); 
       } 
      } 

      return list; 

     } 

     @Override 
     public void nullSafeSet(PreparedStatement statement, Object value, int index, 
       SessionImplementor arg3) throws HibernateException, 
       SQLException { 
      Connection connection = statement.getConnection(); 
       if (value == null) { 
        statement.setNull(index, SQL_TYPES[0]); 
       } else { 
        System.out.println("statement>>>>"+statement); 
        System.out.println("value>>>>"+ value); 
        System.out.println("index>>>>"+index); 
        @SuppressWarnings("unchecked") 
        ArrayList<String> parameter=new ArrayList<>(); 
        if(value instanceof Array) 
        { parameter=(ArrayList<String>) value; 
        }else 
        { 
         parameter.add((String) value); 
        } 
        ArrayList<String> list=parameter; 
        String[] castObject = Arrays.copyOf(list.toArray(), list.toArray().length, String[].class); 
        Array array = connection.createArrayOf("text", castObject); 
        statement.setArray(index, array); 
        System.out.println("statement>>>>"+statement); 
       } 
     } 
     @Override 
     public final Object deepCopy(final Object value) throws HibernateException { 
      return value; 
     } 

     @Override 
     public final boolean isMutable() { 
      return false; 
     } 

     @Override 
     public final Object assemble(final Serializable serializable, final Object arg1) 
       throws HibernateException { 
      return serializable; 
     } 

     @Override 
     public final Serializable disassemble(final Object o) throws HibernateException { 
      return (Serializable) o; 
     } 

     @Override 
     public final boolean equals(final Object x, final Object y) throws HibernateException { 
      if (x == y) { 
       return true; 
      } else if (x == null || y == null) { 
       return false; 
      } else { 
       return x.equals(y); 
      } 
     } 

     @Override 
     public final int hashCode(final Object x) throws HibernateException { 
      return x.hashCode(); 
     } 

     @Override 
     public final Object replace(
      final Object original, 
      final Object target, 
      final Object owner) throws HibernateException { 
      return original; 
     } 
      private String serialize(List<String> list) { 
       StringBuilder strbul = new StringBuilder(); 
       Iterator<String> iter = list.iterator(); 
       strbul.append("{"); 
       while (iter.hasNext()) { 
        strbul.append(iter.next()); 
        if (iter.hasNext()) { 
         strbul.append(","); 
        } 
       } 
       strbul.append("}"); 
       return strbul.toString(); 
      } 


} 

내 최대 절전 모드 기준입니다 : - 나는 그것이 작동하지 않는 특정 독특한 id.But이 들어있는 상자를 얻을 필요가

Session session=getSession(); 
    Criteria criteria=session.createCriteria(Box.class); 
    criteria.add(Restrictions.in("unique_id", unique_id)); 
    return (Unit)criteria.uniqueResult(); 

. DB의 텍스트 배열에 하나의 값이있는 경우에만 결과를 반환합니다. 하지만 DB에 값이 여러 개있는 경우 결과가 표시되지 않습니다.

도움을 주시면 감사하겠습니다.

답변

0

UserType을 구현하는 것은 일반적으로 노력할 가치가 없습니다. Postgres는 배열에 문자열 형식을 허용하기 때문에 @PrePersist, @PreUpdate@PostLoad 함수를 클래스에 추가하는 것이 좋습니다. 숫자 일 뿐이므로 변형은 간단합니다.

@Transient 
private long[] theids; 

@Column(name = "the_ids") 
private String therealids; 

@PrePersist 
@PreUpdate 
private void encode() { 
    therealids = "{" + java.util.Arrays.toString(theids) + "}"; 
} 

@PostLoad 
private void decode() { 
    String[] ids = therealids.split(","); 
    theids = new long[ids.length]; 
    if (ids.length == 0) { 
     return; 
    } 
    int last = ids.length - 1; 
    // remove the "{" 
    ids[0] = ids[0].substr(1); 
    // remove the "}" 
    ids[last] = ids[last].substr(0, ids[last].length() - 1); 
    for (int i = 0; i < ids.length; i++) theids[i] = Long.parseLong(ids[i]); 
} 

보다 빠르고 적은 메모리 사용량이 있지만, 이것이 짧은 버전 있도록이 코드를 할 수있는 최소 4 최적화가 있습니다.

동일하지만 문자열 배열을 사용하려면 해당 시나리오의 배열에 대해 적절한 이스케이프 구문을 알고 있어야하며, 더 나쁜 경우에는 큰 따옴표를 사용해야합니다.