【问题标题】:How to store values from different objects in one table如何将来自不同对象的值存储在一个表中
【发布时间】:2013-10-09 12:59:38
【问题描述】:

在我的代码中,“Book”类包含一些字符串字段和“BookKey”字段,该字段具有一些静态方法,并且只有一个字段具有字符串“key”值。我的问题是如何只存储这个“键”值(不是 BookKey ID 的关系),“书”表中的值?

我不想在我的数据库中创建表“BookKey”。我只想要带有列的表“Book”:“Key”、“Title”和“Description”,其中“Key”是 BookKey 对象的字符串值。 我知道如果我不想创建表,我必须使用 static transients=['key'],但我不知道如何将来自不同对象的值存储在一个表中。

class BookKey{
    public final String key;

    public BookKey(){
        this.key="key-undefined"
    }

    public BookKey(String key){
        this.key=key;
    }

    static BookKey generate(){
        String uuid = UUID.randomUUID().toString();
        String key="book-"+uuid;
        return new BookKey(key)
    }

    static BookKey from(String key){
        return new BookKey(key)
    }
}

public class Book {
    BookKey key=BookKey.generate();
    String title;
    String description;

    static transients = ['key']

    static mapping = {
        key column: 'bKey'
    }
}

【问题讨论】:

    标签: grails grails-orm


    【解决方案1】:

    将您的 BookKey 类放入 src/groovy 并将您的域类配置为使用 embedded。文档中的示例:

    class Person {
        String name
        Country bornInCountry
        Country livesInCountry
    
        static embedded = ['bornInCountry', 'livesInCountry']
    }
    
    // If you don't want an associated table created for this class, either
    // define it in the same file as Person or put Country.groovy under the
    // src/groovy directory.
    class Country {
        String iso3
        String name
    }
    

    【讨论】:

    • 它有效,但仅当我在 BookKey 类中使​​用“字符串键”时。当我使用“最终字符串键”时,在运行应用程序期间出现错误:Caused by: org.hibernate.PropertyNotFoundException: Could not find a setter for property key in class domain.model.keys.BookKey
    【解决方案2】:

    您应该查看 Grails 域类的 embedded 属性:

     static embedded = ['key']
    

    详情请见Composition in GORM

    【讨论】:

      【解决方案3】:

      我处理过同样的任务。我从 DroolsGormPlugin impl 得到了一个想法。这个想法是使用唯一的 BusinessKey。前任。 id=123 的书有 'book@123' BusinessKey && id='q23s' 的作者有 'author@q23s' BusinessKey。然后这些 BusinessKeys 你可以在任何地方使用。例如:

      class LogDomain{
        String businessKey
        ...
      }  
      

      您不需要为每个 Damain 提供关键表。 Spring Security 中使用了另一种方法来确定 ACL。

      【讨论】:

        【解决方案4】:

        使用static embedded 没问题,但在我的情况下,最好定义我自己的"user-type" 并将其添加到GORM 映射中。

        我的班级中只有一个带有随机生成业务密钥的String 字段,因此我想将此值作为varchar 存储在db 中。解决办法是:

        Config.groovy 中定义:

        grails.gorm.default.mapping={
          "user-type" (type: my.package.persistence.PersistentBookKey, class: BookKey)
        }
        

        创建实现UserType接口的类PersistentBookKey并覆盖一些方法:

        final class PersistentBookKey implements UserType
        {
            @Override
            protected BookKey createKeyFromString(String key) {
                BookKey.from(key)
            }
        
            @Override
            Class returnedClass() {
                BookKey
            }
        
            private static int [] SQL_TYPES=[Types.VARCHAR] as int[]
        
            @Override
            int[] sqlTypes() {
                return SQL_TYPES
            }
        
            @Override
            boolean equals(Object x, Object y) throws HibernateException {
                return x.equals(y);
            }
        
            @Override
            int hashCode(Object x) throws HibernateException {
                return x.hashCode()
            }
        
            @Override
            Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
                def key=rs.getString(names[0])
                return this.createKeyFromString(key);
            }
        
            @Override
            void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
                BookKey persistent=value as BookKey
                st.setString(index,persistent?.getKey())
            }
        
            @Override
            Object deepCopy(Object value) throws HibernateException {
                return value
            }
        
            @Override
            boolean isMutable() {
                return false  //To change body of implemented methods use File | Settings | File Templates.
            }
        
            @Override
            Serializable disassemble(Object value) throws HibernateException {
                return value as Serializable
            }
        
            @Override
            Object assemble(Serializable cached, Object owner) throws HibernateException {
                return cached
            }
        
            @Override
            Object replace(Object original, Object target, Object owner) throws HibernateException {
                return original
            }
        
        
        }
        

        现在 BookKey 对象作为 Varchar 存储在数据库中,但是当我获取它们时,它们会转换回 BookKey 对象。

        更多信息可以看这里:

        http://grails.org/doc/2.0.x/ref/Database%20Mapping/Usage.html

        http://grails.1312388.n4.nabble.com/Working-example-of-user-type-td1377468.html

        【讨论】:

          猜你喜欢
          • 2022-06-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-11-19
          • 2012-08-05
          • 1970-01-01
          • 1970-01-01
          • 2013-07-18
          相关资源
          最近更新 更多