我有这个庞大的数据结构 - 我想避免为每种类型指定类...
使用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]
答案 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方法,甚至不需要定义数据模式。