Частично заполните дочерний набор с NHibernate

Как Вы уже заявляете в своем вопросе, основное различие между union и struct - то, что union участники накладывают память друг друга так, чтобы sizeof объединения был тем, в то время как struct участники размечаются тот друг после друга (с дополнительным промежуточным дополнением). Также объединение является достаточно большим, чтобы содержать всех его участников и иметь выравнивание, которое соответствует всем его участникам. Так скажем, int может только быть сохранен в 2-байтовых адресах и 2 байта шириной, и долго может только храниться в 4-байтовых адресах и 4 байта длиной. Следующее объединение

union test {
    int a;
    long b;
}; 

могло иметь sizeof из 4 и требование выравнивания 4. И объединение и структура могут иметь дополнение в конце, но не в их начале. Запись в структуру изменяет только значение участника, записанного в. Запись в члена объединения представит значение всех других недопустимых участников. Вы не можете получить доступ к ним, если Вы не записали в них прежде, иначе поведение не определено. GCC обеспечивает как расширение, которое можно на самом деле считать от членов объединения, даже при том, что Вы не записали в них последний раз. Для Операционной системы не должно иметь значения, пишет ли пользовательская программа в объединение или в структуру. Это на самом деле - только выпуск компилятора.

Другое важное свойство объединения и структуры, они признают, что указатель на них может указать на типы любого из его участников . Таким образом, следующее допустимо:

struct test {
    int a;
    double b;
} * some_test_pointer;

some_test_pointer может указать на [1 110] или double*. При кастинге адреса типа test к [1 113] он укажет своему первому участнику, a, на самом деле. То же верно для объединения также. Таким образом, потому что объединение будет всегда иметь выравнивание по правому краю, можно использовать объединение для создания указывающий на некоторый тип допустимый:

union a {
    int a;
    double b;
};

, Что объединение на самом деле будет в состоянии указать на интервал и двойное:

union a * v = (union a*)some_int_pointer;
*some_int_pointer = 5;
v->a = 10;
return *some_int_pointer;    

на самом деле допустимо, как указано стандартом C99:

объект должен иметь свою хранимую сумму полученной доступ только по lvalue выражению, которое имеет один из следующих типов:

  • тип, совместимый с эффективным типом объекта
  • ...
  • агрегат или тип объединения, который включает один из вышеупомянутых типов среди его участников

, компилятор не оптимизирует v->a = 10;, поскольку это могло влиять на значение [1 116] (и функция возвратится 10 вместо [1 118]).

6
задан Adi Lester 3 September 2012 в 17:12
поделиться

5 ответов

Для этого есть преобразователь результатов, см. документацию.

Цитата:

Примечание. что в коллекции котят экземплярами Cat, возвращенными предыдущие два запроса не предварительно отфильтрован по критериям! если ты хотите вернуть только котят, которые соответствовать критериям, вы должны использовать SetResultTransformer (CriteriaUtil.AliasToEntityMap) .

 Iist cats =
сесс.CreateCriteria (typeof (Cat))
 .CreateCriteria ("Котята", "kt")
 .Add (Expression.Eq ("Имя", "F%"))
 .SetResultTransformer (CriteriaUtil.AliasToEntityMap)
 .Список();

Вы также можете использовать фильтры, которые активируются с помощью session.EnableFilter (name) .

Здесь есть аналогичный вопрос .

2
ответ дан 17 December 2019 в 20:34
поделиться

На самом деле вы не делаете ничего плохого - спящий режим просто так не работает.

Если вы перейдете от BlogPost к комментариям, Hibernate заполнит комментарии на основе ассоциации сопоставление, которое вы указали, а не запрос, который вы использовали для получения BlogPost. Предположительно ваше отображение просто выполняет соединение на ключевом столбце. Вы можете использовать фильтр , чтобы получить желаемый эффект . Но я думаю, что при этом будут извлечены все комментарии, а затем произведен пост-фильтр.

Проще говоря, просто запросите то, что вы хотите:

List<Comments> comments = session.CreateCriteria<BlogPost>()
            .Add(Restrictions.Eq("Id", 1))
            .CreateAlias("Comments", "c")
            .Add(Restrictions.Eq("c.DatePosted", new DateTime(2009, 8, 1)))
            .list();

Это фактически вернет только комментарии с указанной даты. если это заставляет вас чувствовать себя лучше, вы можете установить их следующим образом:

post.setComments(comments); //having already retreived the post elsewhere

Я тоже был удивлен таким поведением, когда впервые столкнулся с ним. Это похоже на ошибку, но мне сказали, что это сделано намеренно.

0
ответ дан 17 December 2019 в 20:34
поделиться

Я согласен, это похоже на взлом вручную заполнить коллекцию.

Вместо этого вы можете использовать собственный загрузчик. Примерно так:

<query name="loadComments">
<return alias="comments" class="Comment"/>
<load-collection alias="comments" role="Post.comments"/>
from Comments c where c.Id = ? and c.DatePosted = SYSDATE
</query>

Кроме того, вы можете использовать sql-запрос, если хотите больше контроля. Я иногда опускался до написания пользовательских загрузчиков, когда не мог перейти в спящий режим, чтобы сгенерировать нужный мне запрос. В любом случае, не знаю, почему я вообще не подумал об этом.

0
ответ дан 17 December 2019 в 20:34
поделиться

спасибо за ответ, когда я запускаю следующий код, первый запрос делает то, что вы ожидаете, возвращается только одно сообщение, но как только выполняется второй запрос, два запроса отправляются в базу данных, первый для получения отфильтрованных комментариев (бинго!), а затем секунда, чтобы заполнить свойство post.Comments всеми комментариями, именно то, что я пытаюсь избежать!

        var post = session.CreateCriteria<BlogPost>()
            .Add(Restrictions.Eq("Id", 1))
            .UniqueResult<BlogPost>();

        var comments = session.CreateCriteria<Comment>()
            .Add(Restrictions.Eq("BlogPostId", 1))
            .Add(Restrictions.Eq("DatePosted", new DateTime(2009, 8, 1)))
            .List<Comment>();

        post.Comments = comments;

это очень странно, это не то, что я перечисляю по списку комментариев post.Comments, так почему он его заселяет ?! вот мои классы и карты:

public class BlogPostMap : ClassMap<BlogPost>
{
    public BlogPostMap()
    {
        Id(b => b.Id);
        Map(b => b.Title);
        Map(b => b.Body);
        HasMany(b => b.Comments).KeyColumnNames.Add("BlogPostId");
    }
}
public class CommentMap : ClassMap<Comment>
{
    public CommentMap()
    {
        Id(c => c.Id);
        Map(c => c.BlogPostId);
        Map(c => c.Text);
        Map(c => c.DatePosted);
    }
}

public class BlogPost
{
    public virtual int Id { get; set; }
    public virtual string Title { get; set; }
    public virtual string Body { get; set; }
    public virtual IList<Comment> Comments { get; set; }
}
public class Comment
{
    public virtual int Id { get; set; }
    public virtual int BlogPostId { get; set; }
    public virtual string Text { get; set; }
    public virtual DateTime DatePosted { get; set; }
}

есть идеи?

0
ответ дан 17 December 2019 в 20:34
поделиться

Сделайте коллекцию комментариев ленивой, чтобы спящий режим не загружал ее, когда вы получаете BlogPost. Затем используйте фильтр для коллекции комментариев.

comments = session.CreateFilter(blogPost.Comments, ... ).List();
0
ответ дан 17 December 2019 в 20:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: