【问题标题】:Mapping a boolean with hibernate使用休眠映射布尔值
【发布时间】:2011-09-05 12:44:36
【问题描述】:

我遇到了休眠问题。我最近将我的 hbm2ddl 设置为验证,它一直在抱怨错误的数据类型。除了布尔值,我已经解决了所有问题。

我的班级中有一个字段opener,映射为:

<property column="opener" name="opener" type="boolean"/>

opener 列是 tinyint (4),值为 1 或 0。到目前为止,我已经尝试更改类型,但无济于事。我还尝试在我的 hibernate.cfg 中使用以下设置:

<property name="hibernate.query.substitutions">true 1, false 0</property>

但我仍然遇到同样的错误。我做错了什么?

org.hibernate.HibernateException: Wrong column type: opener, expected: bit
    at org.hibernate.mapping.Table.validateColumns(Table.java:261)
    at org.hibernate.cfg.Configuration.validateSchema(Configuration.java:1083)
    at org.hibernate.tool.hbm2ddl.SchemaValidator.validate(SchemaValidator.java:116)
    at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:317)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1294)
    at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:859)

注意:我无权访问数据库。

【问题讨论】:

    标签: java hibernate hbm2ddl hbm


    【解决方案1】:

    您可以将 DB 列定义为 char(1),并在 Hibernate 映射文件中将属性定义为 type="yes_no",这是一种 Java 布尔类型。这些将在 DB 中显示为 YN 值。

    如果你想使用tiny_int,那么大小必须为 1,但我不能 100% 确定它是如何映射到 HBM 文件中的。

    【讨论】:

    • 对不起,我必须更清楚地说明这一点,但我无法控制数据库,它在 OP 中。
    【解决方案2】:

    试试这个:

    <property column="opener" name="opener" access="field" />
    

    假设你有一个吸气剂

     boolean isOpener() ;
    

    和一个二传手

    void setOpener(boolean b);
    

    【讨论】:

    • 如果不起作用,您必须将您的 TINYINT(4) 更改为 TINYINT(1)。
    【解决方案3】:

    你可以尝试使用numeric_boolean作为类型:

    <property column="opener" name="opener" type="numeric_boolean"/>
    

    【讨论】:

    • 我想我在某处看到过类似这样的事情的 jpa annonation。这对我没有帮助,当我将开启器类型映射为 numeric_boolean 时,我得到:org.hibernate.MappingException:无法确定类型:numeric_boolean,对于列:[org.hibernate.mapping.Column(opener)]
    • 你的回答让我得到了这个更完整的答案,解决了我的问题:stackoverflow.com/a/5567818/1657465
    【解决方案4】:

    如果您无法更改表中的 SQL 类型,我建议您这样做:

    <property name="opener" column="opener" type="path.to.your.package.YourClassUserType"/>
    

    并创建您的课程:

    import org.hibernate.usertype.UserType;
    
    public class YourClassUserType implements UserType{
     ...
    }
    

    你必须从 UserType 接口实现方法。 该实现会将字节转换为布尔值(因为 TINYINT 在 Java 中映射为字节)

    examples here

    祝你好运:)

    【讨论】:

      【解决方案5】:

      这是一个棘手的问题,因为您无权访问数据库。但这可以通过一些工作来完成

      您需要做的是创建一个自定义类型类。此类基本上将从数据库中检索值(1 或 0),并将包含返回 true 或 false 布尔对象的逻辑。

      这是一个例子:

      http://alenovarini.wikidot.com/mapping-a-custom-type-in-hibernate

      您的新类型的映射将如下所示:

          <typedef class="com.path.to.my.package.CustomBooleanType" name="myBoolType" />
      

      该类 nullSafeGet 方法将返回您的布尔对象,该对象将包含真或假。

      因此您的新映射将包含:

      <property column="opener" name="opener" type="myBoolType"/>
      

      【讨论】:

        【解决方案6】:

        对于遇到与我相同问题的任何人,我使用了此处发布的两个答案的组合。

        我实现了一个自定义用户类型来处理我的 tinyint 字段:

        public class TinyIntegerToBoolean implements UserType {
        
            public int[] sqlTypes() {
                return new int[]{Types.TINYINT};
            }
        
            public Class returnedClass() {
                return Boolean.class;
            }
        
            public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor si, Object owner) throws HibernateException, SQLException {
                return (rs.getByte(names[0]) != 0);
            }
        
            public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor si) throws HibernateException, SQLException {
                st.setByte(index, Boolean.TRUE.equals(value) ? (byte) 1 : (byte) 0);
            }
        
            /* boilerplate... */
            public boolean isMutable() {
                return false;
            }
        
            public boolean equals(Object x, Object y) throws HibernateException {
                if (x == null || y == null) {
                    return false;
                } else {
                    return x.equals(y);
                }
            }
        
            public int hashCode(Object x) throws HibernateException {
                assert (x != null);
                return x.hashCode();
            }
        
            public Object deepCopy(Object value) throws HibernateException {
                return value;
            }
        
            public Object replace(Object original, Object target, Object owner)
                    throws HibernateException {
                return original;
            }
        
            public Serializable disassemble(Object value) throws HibernateException {
                return (Serializable) value;
            }
        
            public Object assemble(Serializable cached, Object owner)
                    throws HibernateException {
                return cached;
            }
        }
        

        然后我将以下内容添加到我的映射中:

        <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
        <hibernate-mapping>
            <typedef class="com.test.model.TinyIntegerToBoolean" name="tinyint_boolean"/>
        </hibernate-mapping>
        

        然后在我的开场白中我使用type=tinyint_boolean,它就像一个魅力:)

        【讨论】:

        • 如果这是您想在应用程序中映射布尔值的默认方式,并且如果您碰巧正在运行 Hibernate 4,恕我直言,更好的替代方法是实现 org.hibernate.type.BasicType 而不是 UserType 和 regsiter这个实现带有 org.hibernate.type.BasicTypeRegistry。特别注意 BasicType#getRegistrationKeys。您的类型将成为您在其下注册类型的任何键的默认类型映射。在这里,您将在 ["boolean", "java.lang.Boolean"] 下注册它。见docs.jboss.org/hibernate/orm/4.1/manual/en-US/html_single/…
        • 我正在运行 hibernate 4.1,它不是映射布尔值的默认方式,但它被大量使用。上面的解决方案真的很丑,恕我直言,所以我会尽快研究一下,谢谢!
        • 因此使用带有 getRegistrationKeys == ["tinyint_boolean"] 的 BasicType 将等效于 typedef 映射。
        • 这样可以节省一些样板代码和一个 xml 文件 :)!感谢您提及这一点!
        • 我们一直在使用 Jadira Usertype 将 Jodatime DateTime 字段映射到休眠状态。 Jadira Usertype 框架也有一个 AbstractUserType 来处理你所有的样板代码。
        猜你喜欢
        • 2011-12-23
        • 1970-01-01
        • 2015-07-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多