代码之家  ›  专栏  ›  技术社区  ›  Colin Bowern

未应用于多对一引用的筛选器

  •  0
  • Colin Bowern  · 技术社区  · 14 年前

    我有一个奇怪的场景,其中有一个表引用了一个视图,该视图包含特定于用户的行。视图具有唯一的行ID,但从不用于引用项。相反,唯一值是从客户机ID、用户ID和对象键的组合中派生的。

        public BarMap()
        {
            Table(DatabaseObject.UserBars);
    
            Id(x => x.Id, "Resource_Id");
    
            Map(x => x.ClientId, "Client_Id");
            Map(x => x.UserId, "User_Id");
    
            Map(x => x.Key, "Bar_Key")
                .Length(10);
            Map(x => x.Name, "Bar_Name")
                .Length(255);
    

    我有一个过滤器应用于 应该 基于当前用户和客户机上下文输入WHERE子句。现在在实践中,当我尝试直接检索一个条时,我看到了这些过滤器的应用。但是,当我检索一个名为Foo的对象(它引用了一个Bar对象)时,在第二个SELECT调用中会跳过过滤器。

    public class FooMap : ClassMap<Foo>
    {
        public FooMap()
        {
            Table(DatabaseObject.Foos);
    
            References<Bar>(x => x.Bar, "BarId")
                .PropertyRef(x => x.Key)
                .Cascade.None()
                .Fetch.Join()
                .NotFound.Exception();
    

    基于上述情况,您可能希望Foo执行一个JOIN来连接Bar对象,但它似乎跳过了它,并坚持要检索Foo对象。我怀疑之所以发生第二个SELECT调用,是因为NH库正试图基于键的唯一值(在日志中)检索对象

    Loader.Loader - SELECT this_.Id as Id12_2_, this_.ClientId as ClientId12_2_,  this_.BarId as BarId12_2_, Foo1_.Id as Id13_0_, Foo1_.ClientId as ClientId13_0_, Foo1_.Name as Name13_0_, Bar2_.Resource_Id as Resource1_4_1_, Bar2_.Client_Id as Client7_4_1_, Bar2_.User_Id as User8_4_1_, Bar2_.Bar_Key as Bar9_4_1_, Bar2_.Bar_Name as Bar10_4_1_ FROM Foos this_ inner join FooSchedules Foo1_ on this_.ScheduleId=Foo1_.Id inner join User_Bars Bar2_ on this_.BarId=Bar2_.Bar_Key and (Bar2_.Client_Id = :p0 OR Bar2_.Client_Id IS NULL) and Bar2_.User_Id = :p1 WHERE (Foo1_.ClientId = :p2 OR Foo1_.ClientId IS NULL) and (this_.ClientId = :p3 OR this_.ClientId IS NULL) AND Foo1_.Name = :p4 and Bar2_.Bar_Key = :p5 and Bar2_.Client_Id = :p6 and Bar2_.User_Id = :p7
    Loader.Loader - processing result set
    Loader.Loader - result set row: 0
    

    我可以在这里看到,它把吧台装上了水,但不知什么原因它没有水合??

    Loader.Loader - result row: EntityKey[Core.Domain.FooSchedule#2929992], EntityKey[Core.Domain.Bar#470090], EntityKey[Core.Domain.Foo#3211664]
    Loader.Loader - Initializing object from DataReader: [Core.Domain.FooSchedule#2929992]
    Loader.Loader - Initializing object from DataReader: [Core.Domain.Foo#3211664]
    Loader.Loader - done processing result set (1 rows)
    Loader.Loader - total objects hydrated: 2
    Engine.TwoPhaseLoad - resolving associations for [Core.Domain.FooSchedule#2929992]
    Engine.Loading.LoadContexts - creating collection wrapper:[Core.Domain.FooSchedule.Foos#2929992]
    Engine.TwoPhaseLoad - done materializing entity [Core.Domain.FooSchedule#2929992]
    Engine.TwoPhaseLoad - resolving associations for [Core.Domain.Foo#3211664]
    Engine.Loading.LoadContexts - creating collection wrapper:[Core.Domain.Foo.Items#3211664]
    

    Loader.Entity.AbstractEntityLoader - Static select for entity Core.Domain.Bar: SELECT Bar0_.Resource_Id as Resource1_4_0_, Bar0_.Client_Id as Client7_4_0_, Bar0_.User_Id as User8_4_0_, Bar0_.Bar_Key as Bar9_4_0_, Bar0_.Bar_Name as Bar10_4_0_ FROM User_Bars Bar0_ WHERE Bar0_.Bar_Key=?
    Loader.Loader - loading entity: [Core.Domain.Bar#ABFDBC01]
    Engine.QueryParameters - BindParameters(Named:NHibernate.Type.StringType) ABFDBC01 -> [0]
    Loader.Loader - SELECT Bar0_.Resource_Id as Resource1_4_0_, Bar0_.Client_Id as Client7_4_0_, Bar0_.User_Id as User8_4_0_, Bar0_.Bar_Key as Bar9_4_0_, Bar0_.Bar_Name as Bar10_4_0_ FROM User_Bars Bar0_ WHERE Bar0_.Bar_Key=:p0
    Loader.Loader - processing result set
    

    我在JBoss端找到了一些Hibernate可能也会遭受 potentially related design issue . 通过查看NHibernate源代码,问题似乎集中在EntityJoinWalker上:

    SqlStringBuilder whereCondition = WhereString(Alias, uniqueKey, batchSize)
        //include the discriminator and class-level where, but not filters
        .Add(persister.FilterFragment(Alias, new CollectionHelper.EmptyMapClass<string, IFilter>()));
    

    如果我把它改成这样,一切都很好,但我不确定这一变化的影响是什么,评论也没有真正指出为什么过滤器应该被排除。

    SqlStringBuilder whereCondition = WhereString(Alias, uniqueKey, batchSize)
        .Add(persister.FilterFragment(Alias, enabledFilters));
    

    救命?!

    1 回复  |  直到 14 年前
        1
  •  0
  •   Colin Bowern    14 年前

    通过在map类中应用过滤解决(NH 2.1.2中的新外观):

    Where("Client_Id = :clientFilter.clientId AND User_Id = :userFilter.userId");