如何仅选择根实体和所有加载了标识符的内部实体使用 statlesssession

问题描述

我的 hbm 配置:

    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-cascade="save-update" default-lazy="false">
  <class xmlns="urn:nhibernate-mapping-2.2" dynamic-insert="true" dynamic-update="true" optimistic-lock="version" name="LittleNHibernateProject.Model.CompanyBanan,LittleNHibernateProject,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null" table="CompanyBanan">
    <cache region="CompanyBanan" usage="read-write" />
    <id name="Id" type="System.Int64,mscorlib,Version=4.0.0.0,PublicKeyToken=b77a5c561934e089">
      <column name="Id" />
      <generator class="increment" />
    </id>
    <version generated="always" name="VersionObject" type="System.Int64,PublicKeyToken=b77a5c561934e089" unsaved-value="0">
      <column name="VersionObject" not-null="true" default="1" />
    </version>
    <many-to-one class="LittleNHibernateProject.Model.FatherBanan,PublicKeyToken=null" foreign-key="FK_CompanyBanan_FatherBanan" name="FatherBanan">
      <column name="FatherBanan_id" />
    </many-to-one>
    <property name="Name" type="System.String,PublicKeyToken=b77a5c561934e089">
      <column name="Name" />
    </property>
  </class>
  <class xmlns="urn:nhibernate-mapping-2.2" dynamic-insert="true" dynamic-update="true" optimistic-lock="version" name="LittleNHibernateProject.Model.JobBanan,PublicKeyToken=null" table="JobBanan">
    <cache region="JobBanan" usage="read-write" />
    <id name="Id" type="System.Int64,PublicKeyToken=b77a5c561934e089" unsaved-value="0">
      <column name="VersionObject" not-null="true" default="1" />
    </version>
    <any id-type="System.Int64,PublicKeyToken=b77a5c561934e089" meta-type="System.String,PublicKeyToken=b77a5c561934e089" name="Banan">
      <meta-value value="MotherBanan" class="LittleNHibernateProject.Model.MotherBanan,PublicKeyToken=null" />
      <meta-value value="FatherBanan" class="LittleNHibernateProject.Model.FatherBanan,PublicKeyToken=null" />
      <column name="Banan_Type" />
      <column name="Banan_Id" />
    </any>
    <property name="JobName" type="System.String,PublicKeyToken=b77a5c561934e089">
      <column name="JobName" />
    </property>
  </class>
  <class xmlns="urn:nhibernate-mapping-2.2" dynamic-insert="true" dynamic-update="true" optimistic-lock="version" name="LittleNHibernateProject.Model.FatherBanan,PublicKeyToken=null" table="FatherBanan">
    <cache region="FatherBanan" usage="read-write" />
    <id name="Id" type="System.Int64,PublicKeyToken=b77a5c561934e089" name="WifeBanan">
      <meta-value value="MotherBanan" class="LittleNHibernateProject.Model.MotherBanan,PublicKeyToken=null" />
      <column name="Banan_Type" />
      <column name="Banan_Id" />
    </any>
    <property name="Name" type="System.String,PublicKeyToken=b77a5c561934e089">
      <column name="Name" />
    </property>
    <property name="Variety" type="System.String,PublicKeyToken=b77a5c561934e089">
      <column name="Variety" />
    </property>
  </class>
  <class xmlns="urn:nhibernate-mapping-2.2" dynamic-insert="true" dynamic-update="true" optimistic-lock="version" name="LittleNHibernateProject.Model.MotherBanan,PublicKeyToken=null" table="MotherBanan">
    <cache region="MotherBanan" usage="read-write" />
    <id name="Id" type="System.Int64,PublicKeyToken=b77a5c561934e089" name="HusbandBanan">
      <meta-value value="MotherBanan" class="LittleNHibernateProject.Model.MotherBanan,PublicKeyToken=null" />
      <column name="Banan_Type" />
      <column name="Banan_Id" />
    </any>
    <property name="Variety" type="System.String,PublicKeyToken=b77a5c561934e089">
      <column name="Variety" />
    </property>
  </class>
</hibernate-mapping>

我只需要选择加载了标识符的根实体和内部实体(我与 statlesssession 一起使用)。 如果我想选择FatherBanan,我使用扩展名:

public static List<FatherBanan> ToOnlyRefList(this IQueryable<FatherBanan> query)
        {
            var select = query.Select(sel => new {sel.Id,sel.Name,sel.Variety,WifeId = sel.WifeBanan.Id,sel.VersionObject}).ToList();

            var result = new List<FatherBanan>();
            foreach (var item in select)
            {
                result.Add(new FatherBanan
                {
                    Id = item.Id,Name = item.Name,Variety = item.Variety,VersionObject = item.VersionObject,WifeBanan = new MotherBanan{Id = item.WifeId}
                });
            }

            return result;
        }

选择FatherBanan:

                using (var sss = factorySession.OpenSession())
                {
                    var list = sss.Query<FatherBanan>().ToOnlyRefList();
                }

而且Nhibernate从FatherBanan表生成SQL,没问题。

但是如果我想选择 JobBanan:表达式选择新不起作用,生成异常不要将 JobBanan 转换为 Banan。好的,通过使用扩展解决了它的异常:

public static List<JobBanan> ToOnlyRefList(this IQueryOver<JobBanan,JobBanan> query)
        {
            var select = query
                .Select(
                Projections.Property("Id"),Projections.Property("JobName"),Projections.Property("VersionObject"),Projections.SqlProjection("banan_id as banan_id",new[] { "banan_id" },new IType[] { NHibernateUtil.Int64 }),Projections.SqlProjection("banan_type as banan_type",new[] { "banan_type" },new IType[] { NHibernateUtil.String })
                ).List<object[]>();

            var result = new List<JobBanan>();
            foreach (var item in select)
            {
                Banan banan = null;

                if (item[4] as string == nameof(FatherBanan))
                {
                    banan = new FatherBanan() { Id = (long)item[3] };
                }
                else
                if (item[4] as string == nameof(MotherBanan))
                {
                    banan = new MotherBanan { Id = (long)item[3] };
                }

                result.Add(new JobBanan
                {
                    Id = (long)item[0],JobName = (string)item[1],VersionObject = (long)item[2],Banan = banan
                });
            }

            return result;
        }

我得到了所有的香蕉 sss.Query<Banan>.ToOnlyRefList()

解决方法

我找到了一种方法 - 将所有嵌套在循环中:

var types = new Type[]{/*all type in Any mapping Banan*/};
var result = new List<Banan>();
foreach(var type in types)
{
    result.AddRange(sss.Query(type.FullName).ToOnlyRefList());
}

如果实体(和内部实体)不是抽象的,那么:


using (var session = factorySession.OpenSession())
            {
                var banan = 
                    session
                        .Query<CompanyBanan>()
                        .Select( sel => new
                        {
                            sel.Id,BananId = sel.FatherBanan == null ? (long?)null : sel.FatherBanan.Id,sel.Name,sel.VersionObject
                        })
                        .ToList()
                    ;
            }
//and convert typle to entity extension

这将生成 SQL:

select
    companyban0_.Id as col_0_0_,case when fatherbana1_.Id is null then TRUE else FALSE end as col_1_0_,companyban0_.FatherBanan_id as col_2_0_,companyban0_.Name as col_3_0_,companyban0_.VersionObject as col_4_0_ 
from CompanyBanan companyban0_
left outer join FatherBanan fatherbana1_ on companyban0_.FatherBanan_id=fatherbana1_.Id

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...