如何在辅助表中的非主键列上连接表?
我有一种情况,我需要在ORM类层次结构中的对象上连接表,其中连接列不是基类的主键。 以下是表格设计的示例:
CREATE TABLE APP.FOO ( FOO_ID INTEGER NOT NULL, TYPE_ID INTEGER NOT NULL, PRIMARY KEY( FOO_ID ) ) CREATE TABLE APP.BAR ( FOO_ID INTEGER NOT NULL, BAR_ID INTEGER NOT NULL, PRIMARY KEY( BAR_ID ), CONSTRAINT bar_fk FOREIGN KEY( FOO_ID ) REFERENCES APP.FOO( FOO_ID ) ) CREATE TABLE APP.BAR_NAMES ( BAR_ID INTEGER NOT NULL, BAR_NAME VARCHAR(128) NOT NULL, PRIMARY KEY( BAR_ID, BAR_NAME), CONSTRAINT bar_names_fk FOREIGN KEY( BAR_ID ) REFERENCES APP.BAR( BAR_ID ) )
这里是映射(为了简洁而消除了吸气剂和固定剂
@Entity @Table(name = "FOO") @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name = "TYPE_ID", discriminatorType = javax.persistence.DiscriminatorType.INTEGER) public abstract class Foo { @Id @Column(name = "FOO_ID") private Long fooId; } @Entity @DiscriminatorValue("1") @SecondaryTable(name = "BAR", pkJoinColumns = { @PrimaryKeyJoinColumn(name = "FOO_ID", referencedColumnName = "FOO_ID") }) public class Bar extends Foo{ @Column(table = "BAR", name = "BAR_ID") Long barId; }
如果BAR_NAMES
的连接列不是FOO_ID
,而是BAR_ID
,我如何添加BAR_NAMES
的映射?
我尝试过以下方法:
@CollectionOfElements(fetch = FetchType.LAZY) @Column(name = "BAR_NAME") @JoinTable(name = "BAR_NAMES", joinColumns = @JoinColumn(table = "BAR", name = "BAR_ID", referencedColumnName="BAR_ID")) List names = new ArrayList();
这会失败,因为用于检索Bar对象的SQL尝试从FOO表中获取BAR_ID值。 我也尝试用。替换JoinTable注释
@JoinTable(name = "BAR_NAMES", joinColumns = @JoinColumn(name = "BAR_ID"))
这不会产生SQL错误,但也不会检索任何数据,因为针对BAR_NAMES的查询使用FOO_ID作为连接值而不是BAR_ID。
出于测试目的,我使用以下命令填充了DB
insert into FOO (FOO_ID, TYPE_ID) values (10, 1); insert into BAR (FOO_ID, BAR_ID) values (10, 20); insert into BAR_NAMES (BAR_ID, BAR_NAME) values (20, 'HELLO');
在获取ID 10的Foo对象时(与包含1个名称的集合相对),许多似乎有效的解决方案将返回空集合
我能够找到解决方案。 如果您像这样映射Bar类
@Entity @DiscriminatorValue("1") @SecondaryTable(name = "BAR", pkJoinColumns = { @PrimaryKeyJoinColumn(name = "FOO_ID", referencedColumnName = "FOO_ID") }) public class Bar extends Foo { @OneToOne @JoinColumn(table = "BAR", name = "BAR_ID") MiniBar miniBar; }
并添加以下类
@Entity @SqlResultSetMapping(name = "compositekey", entities = @EntityResult(entityClass = MiniBar.class, fields = { @FieldResult(name = "miniBar", column = "BAR_ID"), })) @NamedNativeQuery(name = "compositekey", query = "select BAR_ID from BAR", resultSetMapping = "compositekey") @Table(name = "BAR") public class MiniBar { @Id @Column(name = "BAR_ID") Long barId; }
然后,您可以将任何类型的映射添加到MiniBar
类,就像barId是主键一样,然后进一步使其在外部Bar
类中可用。
不知道如何使用JPA / Annotations,但使用Hibernate XML映射文件,它将是这样的:
你将无法做你想做的事。 @CollectionOfElements(和@OneToMany,就此而言) 始终通过所有者的实体主键进行映射。
映射Foo / Barinheritance的方式也很奇怪 – 它们显然不在同一个表中; 似乎使用JoinedSubclass会是一种更好的方法。 请记住,仍然无法帮助您将bar_names
映射到bar_id
因为主键值在层次结构中共享(即使子列的列名可能不同)。
一种可能的替代方法是在Foo和Bar之间使用@OneToOne映射而不是inheritance。 这是你能够将bar_names
映射到bar_id
以及为你的表结构映射最合适的映射的唯一方法(尽管可能不是你的域模型)。
- Hibernate – 激活Bean Validation集成时出错
- 无法转换为内部代表
- Spring Data REST – 检测到具有相同关系类型的多个关联链接
- 如果没有活动事务,Spring Hibernate集成抛出getFlushMode无效
- 引起:java.lang.ClassCastException:java.lang.Class无法强制转换为java.lang.reflect.ParameterizedType
- 创建名为’sessionFactory’的bean时出错无法实例化默认tuplizer
- @Transactional如何影响Hibernate中的当前会话?
- JPA spring boot内部join – with-clause引用了两个不同的from-clause元素错误
- JPA 2 @SequenceGenerator @GeneratedValue产生唯一约束违规