Hibernate/JPA - Foreign Key Index in Object itself
我目前正在研究100个Java对象,这些对象是由没有JPA / Hibernate经验的人创建的JPA实体。它们的对象基于类本身中的外键引用其他对象。所有主键都在数据库外部生成。
例如(仅作说明)
汽车
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | @Entity @Table(name="CAR") public class Car { private Integer id; private String name; @Id @Column(name="CAR_ID") public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(name="CAR_NAME") public String getName() { return name; } public void setName(String name) { this.name = name; } } |
引擎
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | @Entity @Table(name="ENGINE") public class Engine { private Integer id; private String name; private Integer carId; @Id @Column(name="ENGINE_ID") public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(name="ENGINE_NAME") public String getName() { return name; } public void setName(String name) { this.name = name; } @Column(name="CAR_ID") public Integer getCarId() { return carId; } public void setCarId(Integer carId) { this.carId = carId; } } |
以下是该架构的外观:
1 2 3 | CREATE TABLE CAR(CAR_ID INTEGER NOT NULL PRIMARY KEY,CAR_NAME VARCHAR(255)) CREATE TABLE ENGINE(ENGINE_ID INTEGER NOT NULL PRIMARY KEY,CAR_ID INTEGER,ENGINE_NAME VARCHAR(255)) ALTER TABLE ENGINE ADD FOREIGN KEY (CAR_ID) REFERENCES CAR(CAR_ID) ON DELETE CASCADE ON UPDATE CASCADE |
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 | Car c = new Car(); c.setId(100); c.setName("Dodge Intrepid"); em.persist(c); Engine e = new Engine(); e.setId(999); e.setName("V6"); e.setCarId(c.getId()); em.persist(e); Object entity = em.find(c.getClass(),c.getId()); em.remove(entity); |
因此,汽车ID在数据库中保存了对引擎的引用。丢失延迟加载并不重要,因为我们正在使用事务实体管理器。我已经对此进行了测试,它似乎可以正常工作。
我是否缺少与此相关的任何明显问题?我知道它不完全符合JPA / Hibernate规范,但我认为它可以工作。
您丢失的主要事情是轻松浏览对象图,而不必始终通过数据访问层通过ID显式获取关联的对象。我知道您不愿意将所有对象ID都转换为对象引用,但从长远来看,您最好还是进行这项投资。通过继续当前的设计,您将最终编写大量额外的数据访问代码,以在每次需要导航关联时获取相关对象。另外,当对象未持久存储在数据库中时(例如,在构造新的对象图或在单元测试中时),将更难以对对象关系进行建模。您还将放弃级联(可传递)的保存和更新。
简而言之,我认为从长远来看,您的系统将更加难以维护,除非您解决此设计问题,否则导航对象图将非常笨拙。
由于没有任何映射关系,因此几乎不可能在HQL查询或条件中进行任何联接。一个简单的
1 | from Engine as eng where eng.car.name = 'DODGE' |
如果至少您对主要的关系进行了编码,从长远来看,这将使事情变得容易得多。