2017-12-18 127 views
0

我有一个名为box的实体。每个包含一些参数的参数对于许多唯一的ID都是相同的。唯一ID只是数字,并没有任何其他角色。 所以我创建它们作为postgresql和Java中的文本数组,我将它们作为ArrayList并使用自定义用户类型进行映射。 package com.geniedoc.utils;在postgresql中包含/ in文本数组的Hibernate条件

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(); 
      } 


} 

这是我的休眠条件: -

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

我需要包含一个特定的独特id.But它不工作的框。 仅当我在数据库中的文本数组中有一个值时才返回结果。 但是,如果我有在数据库中的多个值,它不显示任何结果。

任何帮助表示赞赏。

回答

0

实施UserType通常是不值得的。由于Postgres接受数组的字符串格式,因此将类型@PrePersist,​​和@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个优化你可以做这个代码,使其速度更快,更少的内存大户,但这是短版。

如果您想要做同样的事情,但是对于字符串数组,您必须非常了解该场景中阵列的正确转义语法,更糟糕的是,可选的双引号。

相关问题