Hibernate如何实现动态数据结构

时间:2013-12-06 03:51:31

标签: hibernate data-structures orm

我有这个庞大的数据结构 - 我想避免为每种类型指定类...
使用hibernate,这个结构能否以添加新物种或外键的方式实现 - 不需要重新编译?

Animal
|
    Birds
    |   Parakeet 
        |   Love Bird  -> [one to many:visit record]
        |   Budgerigar -> [one to many:visit record]
    Mammals
    |   Dog -> [one to many:vaccinations] [one to many:visit record] [one to many:Haircuts] 
    |   Cat -> [one to many:vaccinations] [one to many:visit record]
    |   Horse -> [one to many:vaccinations] [one to many:Horse breeding]


Tree is about 100+ types of animals

所以例如 -

示例1:我可以添加其他类型而无需重新编译代码

     | Cow -> [one to many:vaccinations] -> [one to many:pregnancy dates]

示例2:在实体之间创建动态链接的能力

    |   Horse -> [one to many:vaccinations] [one to many:Horse breeding]
            LinkToOwner->   [one to one: owner]

2 个答案:

答案 0 :(得分:4)

Hibernate Dynamic mappings是此用例的推荐解决方案。使用动态Hibernate映射,所有内容都会映射到Java Maps中,其中键是字符串,值是String,Integer等类型或其他映射。

因此,在您的示例中,您将获得一个带有两个条目的地图,其中包含“Birds”和“Mammals”键,它们本身就是地图。

哺乳动物的价值将是一个包含3个条目“狗”,“猫”和“马”的地图。 “Cat”值将是具有两个条目的地图:“疫苗接种”和“访问记录”等。

动态映射可以与更常用的静态映射一起使用。

动态映射不是Hibernate最常用的功能,但它们很长一段时间都很稳定,而且它们在这个用例中是精确的。

答案 1 :(得分:2)

在我看来,hibernate并不是真的适合这种情况。 Hibernate需要在编译时映射到预定义的java类类型,因此它知道如何生成SQL。

但是,您可以尝试在没有hibernate的情况下编写JDBC ResultSet数据访问类,该类允许更改架构,而无需使用ResultSet getMetadata() method进行Java编译并将所有列存储在Map中。映射的关键是SQL列名:

public class Animal {
  private Map<String,Object> properties = new HashMap<String,Object>();

  // getters & setters..
}

使用这种方法时的一个问题是你不知道应该使用哪个jdbc ResultSet get方法:rs.getString(),rs.getInt(),rs.getLong()...... ?? < / p>

您可以尝试使用通用rs.getObject(columnName)方法。查询&amp;使用Spring JdbcOperations映射结果集可能如下所示:

List<Animal> animals = jdbcOperation.query("select * from animal", new RowMapper<Animal>() {
  @Overrides Animal mapRow(ResultSet rs, int rowNum) throws SQLException {
    Animal animal = new Animal();
    ResultSetMetaData meta = rs.getMetaData();
    for(int i = 1; i <= meta.getColumnCount(); i++) {
      String columnName = meta.getColumnName(i);
      animal.getProperties().put(columnName, rs.getObject(columnName));
    }
    return animal;
  }
});

如果添加/删除列,上面的代码将不需要重新编译。您还可以对更新/插入应用相同的概念。但是,检索列值会变得很难看。由于所有内容都存储为Object,因此您需要知道将其转换为内容。

// Getting this animal's name
String name = (String) animal.getProperties().get("name");

我能想到的其他方法是使用NoSQL方法,甚至不需要定义数据模式。