我有一个表结构:
------------------------------------------------
| id |daily_index|monthly_index| created |
------------------------------------------------
| GUID | 1 | 1 | 10-12-2014 |
| GUID | 2 | 2 | 10-12-2014 |
| GUID | 1 | 3 | 11-12-2014 |
| GUID | 1 | 1 | 01-01-2015 |
------------------------------------------------
我的目标是拥有一个具有灵活自然代码的交易对象,例如
INV-{daily_index} / {month_in_roman} / {year_in_roman} / {monthly_index}
或者
INV {ddmmyyyyhhiiss} - {monthly_index} - {daily_index}
或者用户希望的任何内容。
该类将具有Code
属性,该属性将编织这些私有字段,仅用于UI。
在纯mysql查询中,我会这样做:
INSERT INTO transaction VALUES (// Some GUID, (SELECT COUNT(*) + 1 FROM transaction WHERE DATE(created) = DATE(NOW)), (SELECT COUNT(*) + 1 FROM transaction WHERE MONTH(created) = MONTH(NOW)), NOW());
我的问题是有没有办法在NHibernate中重现这种INSERT机制?
我考虑了另一个选项,我想用COUNT查询SELECT查询,但我不知道NHibernate是否可以这样做。
另一个选择是制作一个MySQL触发器,但我很想知道这是否可以直接在我的项目中完成。
答案 0 :(得分:2)
NHibernate提供了一个覆盖默认插入语句的选项:sql-insert
:
在映射文件中使用此元素,您可以根据自己的喜好更改插入/更新语句:
<class name="Student">
<id name="Id" type="Int32">
<generator class="assigned" />
</id>
<property name="Code" length="2000" />
<many-to-one name="Class" column="ClassId" not-null="true"/>
<sql-insert>insert into Student (Code, ClassId, Id) values (UPPER(?), ? , ?)</sql-insert>
</class>
当然,您还必须自定义sql-update
。
虽然确定每列的正确位置很棘手。这来自NH文件:
您可以通过启用调试日志记录来查看预期的顺序 NHibernate.Persister.Entity级别。启用此级别的NHibernate 将打印出用于创建,更新,删除的静态SQL 等实体。 (要查看预期的序列,请记住不要包含 您在映射文件中的自定义SQL将覆盖 NHibernate生成了静态sql。)
答案 1 :(得分:1)
这就是我喜欢的NHibernate ......即使这里也是一个解决方案。我们需要的是:
小引用:
如前所述,自动和透明的对象/关系映射与对象状态的管理有关。这意味着对象状态在内存中可用,因此直接在数据库中操作(使用SQL数据操作语言(DML)语句:INSERT,UPDATE,DELETE)数据不会影响内存状态。但是,NHibernate提供了通过Hibernate查询语言(HQL)执行批量SQL样式DML语句执行的方法。
关于INSERT (小提取):
INSERT语句的伪语法是:INSERT INTO EntityName properties_list select_statement。有些要点需要注意:
- 仅支持INSERT INTO ... SELECT ...表单;不是INSERT INTO ... VALUES ...表格。
示例:
ISession session = sessionFactory.OpenSession();
ITransaction tx = session.BeginTransaction();
var hqlInsert = "insert into DelinquentAccount (id, name) " +
" select c.id, c.name from Customer c where ...";
int createdEntities = s.CreateQuery( hqlInsert )
.ExecuteUpdate();
tx.Commit();
session.Close();
有了这个我们可以创建这种选择:
var hqlSelect =
// HQL select clause
" SELECT " +
// guid on the DB side
" UUID(), " +
// this will return matches for today only
" CAST(SUM(CASE WHEN DAY(created)=DAY(CURRENT_TIMESTAMP) THEN 1 ELSE 0 END) as int),"+
// this will return matches for this month - see WHERE
" CAST(Count(*) as int)," +
// the time stamp into created
" CAST(CURRENT_TIMESTAMP as DateTime)" +
// From means - from some entity (the transaction here)
" FROM transaction" +
// Where is here restricting current month
// here we filter just this year and this month records
" WHERE MONTH(created) = MONTH(CURRENT_TIMESTAMP) " +
" AND YEAR(created) = YEAR(CURRENT_TIMESTAMP) ";
这将是COMPLETE插入
var hqlInsert = "INSERT INTO AuditLog (id, daily_index, monthly_index, created ) "
+ hqlSelect; // the above select
这应该做到的预期:
ISession session = sessionFactory.OpenSession();
ITransaction tx = session.BeginTransaction();
var hqlInsert = ... // see code above to create DML HQL
int createdEntities = session
.CreateQuery( hqlInsert )
.ExecuteUpdate();
tx.Commit();
session.Close();