在没有在实体上添加一对多映射而在DB中没有外键关系的情况下,是否可以在休眠中返回包含父级的父级列表?
我有两张桌子A和B.
表'A'包含列idA,name,city,first_id列
表'B'包含列idB,col1,col2,second_id列
我没有在表格之间做过任何明确的外键关系。 此外,我还没有映射实体之间的任何一对多映射。
但是从这两个表first_id和second_id列表示它们之间的关系。
我想将数据返回为 一个A可以有多个B数据。
我正在做什么,
public List<A> Data(){ // This should return A list containing respective B list
Criteria critA = session.createCriteria(A.class); // load table A data
List aList = critA.list();
for(int i=0;i<aList.size();i++)// iterate over table A list
{
A a = (A) alist.get(i);
String **firstId**= a.getFirst_Id();
Criteria critB = session.createCriteria(B.class); // load table B data
critB.add(Restrictions.eq("second_Id", **firstId**)); // query Table b data with respect to table A "first_id" column
criB.list();
}
}
我不明白如何将criB.list添加到aList并最终只返回aList?
答案 0 :(得分:1)
您可以使用HQL / JPQL查询不相关的实体,如下所示:
SELECT a, b FROM A a, B b WHERE b.second_id = a.id
由于您正在进行假one-to-many
关系,因此实体A
无需维护有关该关系的任何信息。这种关系很容易直接来自实体B
。如果使用@OneToMany
和@ManyToOne
建模此关系而没有连接表,那么这也正是数据库模式的建模方式。
为了处理上述查询的结果集:
List<Object[]> results = entityManager.createQuery( query ).getResultList();
for ( Object[] row : results ) {
A a = row[ 0 ];
B b = row[ 1 ];
/* note that A will repeat for each matched B relationship */
}
为了获得您想要的结果,您可以按以下方式使用上述片段:
public List<A> getData() {
Map<Integer, A> aMap = new LinkedHashMap<>();
List<Object[]> results = getEntityManager.createQuery( query ).getResultList();
for( Object[] row : results ) {
final A a = row[ 0 ];
final B b = row[ 1 ];
if ( !aMap.containsKey( a.getId() ) ) {
aMap.put( a.getId(), a );
}
// get the transient property List<B> bList;
aMap.get( a.getId() ).getBList().add( b );
}
return aMap.values();
}
正如我所指出的,您需要在实体@Transient private List<B> bList
上放置A
属性,以便在迭代结果集后返回List<A>
即可填充它每个都包含List<B>
个实例。
<强>跟进强>
如果在实体映射中应用关系,则可以按如下方式查询实体:
public List<A> getData() {
final String query = "SELECT a FROM A a JOIN FETCH bList";
return getEntityManager().createQuery( query ).getResultList();
}
你基本上告诉hibernate到JOIN
两个实体并获取列表,以便在getData()
方法返回时急切地加载并可用。