我试图执行通过DAO对象数据库访问,我也碰到了,我需要查询的另一个实体的现场情况。
考虑到两个实体(EntityA和EntityB),可通过外键连接实体A EntityA.idEntityB
。
我有GenericDao<EntityA> daoA
,我试图让所有符合EntityB的确定的场,结果: idEntityB.fieldOfB
所有在DAO相同find方法。
可能吗? 如果是这样的一些方向将是很好。 谢谢
编辑
我的代码示例:
实体
public class EntityA {
@JoinColumn(name = "id_entity_b", referencedColumnName = "id")
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private EntityB idEntityB;
// getter+setter...
}
public class EntityB {
// ...
private String fieldOfB;
// getter+setter...
}
DAO Access
GenericDao<EntityA> daoA = // ...
Set<Criterion> filter = new HashSet<Criterion>();
filter.add(Restrictions.eq("idEntityB.fieldOfB"));
List<EntityA> list = dao.findByFilter(filter);
该错误消息是类似“ 无法解析财产idEntityB.fieldOfB”
编辑2
我能找到的东西像什么,我想做的事情。 虽然我的API略有不同,我相信这是helful的人谁在自己的项目的早期阶段过这个问题得到。
http://code.google.com/p/hibernate-generic-dao/
该框架拥有一个强大而灵活的搜索功能。 这是通过搜索对象要搜索的一般和通用的DAO方法使用。
与嵌套属性搜索在这个项目中得到充分支持。
这里是我的通用标准过滤方法。
根据豆约定属性有如下形式foo.bar.name
。
与标准API树可以从一个给定的过滤映射来建立并且可以添加限制。 我在测试过程中发现的一个特殊情况是,因为这个属性已经获取的标识属性过滤并不需要一个新的子标准。
/**
* Creates a detached criteria from the given Type and given map of filters.
*
* @param type Target type the Criteria is build for.
* @param identifierPropertyName If provided (not null) the identifier
* property name can be identified for the given type to simplify
* the queries if the identifier property is the only property
* used on the parent no subqueries are needed.
* @param filters
*
* @see #createTree(Set, String)
* @see #addRestrictions(DetachedCriteria, TreeNode)
*
* @return
*/
public static DetachedCriteria createDetachedCriteria(final Class<?> type, final String identifierPropertyName,
final Map<String, Criterion> filters)
{
final DetachedCriteria criteria = DetachedCriteria.forClass(type);
// add restrictions using tree
final TreeNode<Entry<String, Criterion>> rootNode = HibernateUtils2.createTree(filters.entrySet(),
identifierPropertyName);
final Iterator<TreeNode<Entry<String, Criterion>>> it = rootNode.getChildren().iterator();
while (it.hasNext())
HibernateUtils.addRestrictions(criteria, it.next());
return criteria;
}
/**
* Creates a Tree from the given Set using a fictional root TreeNode.
*
* @param <T>
*
* @param filters
* @param identifierPropertyName Property name which is merged with its
* parent property. Example: <b>user.id</b> is treated as single
* property.
* @return
*/
public static <T extends Object> TreeNode<Entry<String, T>> createTree(final Set<Entry<String, T>> filters,
final String identifierPropertyName)
{
final Iterator<Entry<String, Object>> it = filters.iterator();
/*
* create key property tree for Entity properties
*/
final TreeNode<Entry<String, Object>> rootNode = new TreeNode<Entry<String, Object>>(
new SimpleEntry<String, Object>("root", null));
while (it.hasNext())
{
final Entry<String, Object> entry = it.next();
// foo.bar.name
final String key = entry.getKey();
String[] props;
/*
* check if we have a nested hierarchy
*/
if (key.contains("."))
{
props = key.split("\\.");
// check for identifier since identifier property name does not
// need new subcriteria
if (!StringUtils.isBlank(identifierPropertyName))
{
int propsTempLength = props.length - 1;
if (props[propsTempLength].equals(identifierPropertyName))
{
props = Arrays.copyOf(props, propsTempLength);
propsTempLength--;
props[propsTempLength] = props[propsTempLength] + "." + identifierPropertyName;
}
}
// check for "this" identifier of beginning, which needs to be
// added for projections because of hibernate not recognizing it
if (props.length > 1 && props[0].equals("this"))
{
props[0] = "this." + props[1];
props = ArrayUtils.remove(props, 1);
}
}
else
props = new String[]
{
key
};
TreeNode<Entry<String, Object>> currNode = rootNode;
// create nested criteria
for (int i = 0; i < props.length; i++)
{
Object valueAdd;
// only leaf needs value
if (i != props.length - 1)
valueAdd = null;
else
valueAdd = entry.getValue();
final TreeNode<Entry<String, Object>> childTempNode = new TreeNode<Entry<String, Object>>(
new SimpleEntry<String, Object>(props[i], valueAdd));
// try to get the real node
TreeNode<Entry<String, Object>> childNode = currNode.getChild(childTempNode.getElement());
// check if we already have a unique node
if (childNode == null)
{
childNode = childTempNode;
// add new child to set if its a new node
currNode.addChild(childNode);
}
currNode = childNode;
}
}
return rootNode;
}
/**
* Recursively adds the given Restriction's wrapped in the given TreeNode to
* the Criteria.
*
* @param criteria
* @param treeNode
*/
public static void addRestrictions(final DetachedCriteria criteria,
final TreeNode<Entry<String, Criterion>> treeNode)
{
// if we have a leaf simply add restriction
if (treeNode.getChildren().size() == 0)
criteria.add(treeNode.getElement().getValue());
else
{
// create new sub Criteria and iterate children's
final DetachedCriteria subCriteria = criteria.createCriteria(treeNode.getElement().getKey());
final Iterator<TreeNode<Entry<String, Criterion>>> it = treeNode.getChildren().iterator();
while (it.hasNext())
HibernateUtils.addRestrictions(subCriteria, it.next());
}
}
/*
* Utility classes
*/
/**
* Generic TreeNode implementation with a Set to hold its children to only allow
* unique children's.
*/
public class TreeNode<T>
{
private final T element;
private final Set<TreeNode<T>> childrens;
public TreeNode(final T element)
{
if (element == null)
throw new IllegalArgumentException("Element cannot be null");
this.element = element;
this.childrens = new HashSet<TreeNode<T>>();
}
public void addChildren(final TreeNode<T> children)
{
this.childrens.add(children);
}
/**
* Retrieves the children which equals the given one.
*
* @param children
* @return If no children equals the given one returns null.
*/
public TreeNode<T> getChildren(final TreeNode<T> children)
{
final Iterator<TreeNode<T>> it = this.childrens.iterator();
TreeNode<T> next = null;
while (it.hasNext())
{
next = it.next();
if (next.equals(children))
return next;
}
return null;
}
public T getElement()
{
return this.element;
}
public Set<TreeNode<T>> getChildrens()
{
return this.childrens;
}
/**
* Checks if the element of this instance equals the one of the given
* Object.
*/
@Override
public boolean equals(final Object obj)
{
if (this == obj)
return true;
if (obj != null && obj instanceof TreeNode)
{
final TreeNode<?> treeNode = (TreeNode<?>) obj;
return this.element.equals(treeNode.element);
}
else
return false;
}
@Override
public int hashCode()
{
int hash = 1;
hash = hash * 17 + this.element.hashCode();
return hash;
}
}
希望这可以帮助你。 或者看看你提到的通用的DAO项目。 我知道这个项目,并检查出来,但从来没有下载它。
使用这种方法查询可以创建类似下面的很简单:
Map<String, Object> filters = new HashMap<String, Object>();
filters.put("foo.bar.name", Restrictions.like("name", "peter"));
filters.put("foo.test.id", Restrictions.eq("id", 2));
List<Class> data = HibernateUtils.createDetachedCriteria(Class, "get identifier from sessionFactory", filters).getExecutableCriteria(session).list();
这个奇怪的方法来添加属性名称作为键,进入限制是相关的事实,限制对属性名称不getter和setter。
自定义筛选
我真正的应用程序使用不局限于类似的代码Criterion
唯一的类。 对于我的web层我创建了相当于限制API,但客户并不需要冬眠罐子的再定义过滤器。
编辑
不支持跨非实体,如组件和复合-ID的通用过滤。 它可以很容易地帮助扩展ClassMetadata
支持他们,而不需要进行反思。 如果需要的代码,我可以提供。
看看这个例子: http://viralpatel.net/blogs/hibernate-one-to-one-mapping-tutorial-using-annotation/
您需要声明实体之间的关系
public class EntityA {
@JoinColumn(name = "id_entity_b")
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private EntityB idEntityB;
// getter+setter... and the rest
}
取而代之的Integer
使用EntityB
。
这点ORM是Hibernate提供:您不需要用钥匙工作,你有对象。 转换该表示与钥匙的关系映射是Hibernate的ORM层的工作。