我有两张桌子; t_users(user_id pk,user_name,password)和t_transactions(trans_id pk,user_id fk,item_name,amount)。 我们可以看到,t_users是父表,而t_transactions是子表,所以我为它们创建了两个类:
public class User
{
public int ID {get; set;}
public string Name {get; set;}
public string Password {get; set;}
public IList<Transaction> Transactions {get; set;}
public IList<Group> Groups {get; set;}
}
public class Transaction
{
public Transaction()
{
}
public int ID {get; set;}
public int UserID {get; set;}
public string ItemName {get; set;}
public decimal Amount {get; set;}
public User User {get; set;}
}
这是我的映射:
用户
<class name="User" table="t_users" lazy="false">
<id name="ID" column="user_id" />
<property name="Name" column="user_name"/>
<property name="Password" column="password" />
<bag name="Transactions" lazy="false" cascade="all">
<key column="user_id" />
<one-to-many class="Transaction" />
</bag>
<bag name="Groups" table="t_users_groups" lazy="false" cascade="all" inverse="true">
<key column="user_id" />
<many-to-many column="group_id" class="Group" />
</bag>
</class>
交易:
<class name="Transaction" table="t_transactions" lazy="false">
<id name="ID" column="trans_id" />
<property name="UserID" column="user_id"/>
<property name="ItemName" column="item_name" />
<property name="Amount" column="amount" />
<many-to-one name="User" column="user_id" class="User" />
</class>
我如何调用此查询
SELECT u.user_id, u.user_name, u.password, t.trans_id, t.user_id, t.item_name, t.amount
FROM t_users u INNER JOIN t_transactions t on u.user_id = t.user_id
WHERE amount <= :limit
哪个应该返回唯一的父对象(u),并且重复的子表(t)应该部分/放置在类User的属性Transactions中?
谢谢!
答案 0 :(得分:1)
你做错了,因为你不能拥有域实体的“一半”。你想要的是交易,所以你应该查询交易。
在hql中:
from Transaction t
where t.Amount <= :limit
您是否希望获取用户属性?
from Transaction t
join fetch t.User
where t.Amount <= :limit
然后您可以创建命名查询,也可以执行
session.CreateQuery(query).List<Transaction>();
如果您需要类似域对象的对象结构,则可以执行以下操作:
public class UserWithTransactionsViewModel
{
public string UserName {get; set; }
public IEnumerable<TransactionViewModel> Transactions {get; set;}
}
您可以按如下方式在内存中创建投影:
var vms = session.CreateQuery(query)
.List<Transaction>()
.GroupBy(t => t.User)
.Select( g => new UserWithTransactionViewModel
{
UserName = g.Key.Name
Transactions = g.Select(t => new TransactionViewModel(....)).ToArray()
});
另一个方法是查询具有大于...的一个事务的用户,然后在投影到viewmodel或dto时过滤内存中的事务。但我不喜欢这个,因为你有两个不同位置的过滤逻辑,它的性能更差,因为你甚至可以获得内存,甚至是你不想要的事务。
我的一般建议是,当您使用ORM时,您的实例应该在内存中保持一致始终。
PS:您不需要Transaction类中的UserId属性。这是一个设计错误。