【问题标题】:Using PostgreSQL ltree type with a Java ORM layer将 PostgreSQL ltree 类型与 Java ORM 层一起使用
【发布时间】:2011-05-17 12:05:24
【问题描述】:

我喜欢在我的一个项目中使用来自 PostgreSQL contrib 的 ltree,并且我喜欢在数据库之上使用某种 ORM 层(Hibernate、EclipseLink)。我没有发现持久使用这种类型有什么用处。我想我必须用一种新类型和相应的运算符来扩展当前的 PostgreSQL 方言。但是我真的不知道从哪里开始以及正确的方法是什么。 ltree 非常像字符串,所以我想我应该从字符串表示开始。

有人可以给我建议和/或链接到正在做类似事情的示例吗?我还没有找到完整的教程。

【问题讨论】:

    标签: java postgresql persistence


    【解决方案1】:

    这个:

    @Column(name = "dir", nullable = false, columnDefinition = "ltree")
    @Type(type = "ru.zen0n.hibernate.types.LTreeType")
    private String path;
    

    还有这个:

    package ru.zen0n.hibernate.types;
    
    import java.io.Serializable;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Types;
    
    import org.hibernate.HibernateException;
    import org.hibernate.usertype.UserType;
    
    public class LTreeType implements UserType {
    
        @Override
        public int[] sqlTypes() {
            return  new int[] {Types.OTHER};
        }
    
        @SuppressWarnings("rawtypes")
        @Override
        public Class returnedClass() {
            return String.class;
        }
    
        @Override
        public boolean equals(Object x, Object y) throws HibernateException {
            return x.equals(y);
        }
    
        @Override
        public int hashCode(Object x) throws HibernateException {
            return x.hashCode();
        }
    
        @Override
        public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
                throws HibernateException, SQLException {
            return rs.getString(names[0]);
        }
    
        @Override
        public void nullSafeSet(PreparedStatement st, Object value, int index)
                throws HibernateException, SQLException {
            st.setObject(index, value, Types.OTHER);
        }
    
        @Override
        public Object deepCopy(Object value) throws HibernateException {
            return new String((String)value);
        }
    
        @Override
        public boolean isMutable() {
            return false;
        }
    
        @Override
        public Serializable disassemble(Object value) throws HibernateException {
            return (Serializable)value;
        }
    
        @Override
        public Object assemble(Serializable cached, Object owner)
                throws HibernateException {
            return cached;
        }
    
        @Override
        public Object replace(Object original, Object target, Object owner)
                throws HibernateException {
            // TODO Auto-generated method stub
            return deepCopy(original);
        }
    
    }
    

    【讨论】:

    • 在 Hibernate 5.2.16 中,nullSafeGet 方法签名更改如下 Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException;void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException;
    【解决方案2】:

    这里有一些可以帮助你的建议。这不是一个完整的答案,但评论有点太多了。

    Hibernate 和 EclipseLink 都实现了 JPA 标准,但也有自己的一些扩展并允许自定义行为。

    我没有对 ltree 做任何具体的工作,但我认为你可以只使用 java String 类并向列添加注释来否决所使用的普通列类型(这可以在标准 JPA 中完成)。

    @Column(columnDefinition="ltree")
    private String myLtreeValue;
    

    如果 Java 端的 String 不够用,您可以创建自己的类并为其编写转换器类。你可以在this question 中看到一个例子。这将取决于持久性提供程序。

    当使用涉及 ltree 值的条件执行查询时,您可能最好使用 JPA @NamedNativeQuery 注释来定义涉及特殊运算符的查询。例如see here

    【讨论】:

    • 谢谢,看起来很有希望。遗憾的是,由于时间不够,我们决定放弃 ORM,所以我可以稍后尝试。我放弃了。
    • 我们在解决方案中使用了 Spring 的 SQL 行映射器。它实际上不是 ORM 层,但我们只有几个表,所以它仍然非常易于维护。因为我没有时间测试它,而你的是这里唯一相关的答案,我接受它。
    猜你喜欢
    • 2020-07-23
    • 1970-01-01
    • 1970-01-01
    • 2021-07-27
    • 1970-01-01
    • 2022-01-12
    • 1970-01-01
    • 2019-01-09
    • 1970-01-01
    相关资源
    最近更新 更多