我有一个实体。我想可以选择从辅助表中加载有关实体的其他信息。我有以下映射。
@Entity
@Table( name = "program", schema = "myschema" )
@SecondaryTable( name = "program_info", schema = "myschema", pkJoinColumns =
@PrimaryKeyJoinColumn( name = "program_id", referencedColumnName = "program_id" ) )
public class Program { ... }
我已正确映射所有列,并且可以使用单元测试。当程序表中的一行没有在program_info表中有相应的行时,就会出现问题。在这种情况下,它根本不会加载程序。我需要能够将整个辅助表标记为可选。我宁愿不必创建另一个实体/ dao / service并进行1-1映射。
我正在使用eclipselink,但如果可以的话,我希望远离提供商的具体细节。
答案 0 :(得分:9)
我需要能够将整个辅助表标记为可选。
EclipseLink将使用INNER JOIN
执行SecondaryTable
,因此如果辅助表中没有相应的行,您将什么也得不到。换句话说,EL期望在辅助表中找到一行(在创建,读取,更新,删除时)。
如果您想要的是OUTER JOIN
,则应使用可选的OneToOne
关联(在您的情况下可能使用共享主键)。
另一种方法是使用数据库视图(执行OUTER JOIN
)并映射视图。
我宁愿不必创建另一个实体/ dao / service并进行1-1映射。
我不明白为什么有一个可选的OneToOne
强制您拥有相应的DAO和服务。通过主“持有人”部分管理可选部分。
答案 1 :(得分:0)
TopLink,EclipseLink:如果数据库支持where子句中的外部连接语法的使用(Oracle,Sybase,SQL Server),则多表 join表达式可用于配置外部联接,以用于读取表。
我在Oracle数据库上有 Eclipselink 多表实体的自定义程序
public class OuterJoinCustomizer implements DescriptorCustomizer {
public void customize(ClassDescriptor descriptor) {
Map<DatabaseTable, Map<DatabaseField, DatabaseField>> tables =
descriptor.getAdditionalTablePrimaryKeyFields();
ExpressionBuilder builder = new ExpressionBuilder();
Expression expression = null;
for (Map.Entry<DatabaseTable, Map<DatabaseField, DatabaseField>> table :
descriptor.getAdditionalTablePrimaryKeyFields().entrySet()) {
Expression criteria = null;
for (Map.Entry<DatabaseField, DatabaseField> fields : table.getValue().entrySet()) {
// NOTE: equalOuterJoin (+)= SUPPORTED BY ORACLE!
Expression fieldExp =
builder.getField(fields.getValue()).equalOuterJoin(builder.getField(fields.getKey()));
criteria = (criteria == null) ? fieldExp : criteria.and(fieldExp);
}
if (criteria != null)
expression = (expression == null) ? criteria : expression.and(criteria);
}
if (expression != null)
descriptor.getQueryManager().setMultipleTableJoinExpression(expression);
}
}
}
在休眠模式下,变得更加容易
@Table(optional = true)