Как Вы уже заявляете в своем вопросе, основное различие между 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]).
Для этого есть преобразователь результатов, см. документацию.
Цитата:
Примечание. что в коллекции котят экземплярами Cat, возвращенными предыдущие два запроса не предварительно отфильтрован по критериям! если ты хотите вернуть только котят, которые соответствовать критериям, вы должны использовать
SetResultTransformer (CriteriaUtil.AliasToEntityMap)
.Iist cats = сесс.CreateCriteria (typeof (Cat)) .CreateCriteria ("Котята", "kt") .Add (Expression.Eq ("Имя", "F%")) .SetResultTransformer (CriteriaUtil.AliasToEntityMap) .Список();
Вы также можете использовать фильтры, которые активируются с помощью session.EnableFilter (name)
.
Здесь есть аналогичный вопрос .
На самом деле вы не делаете ничего плохого - спящий режим просто так не работает.
Если вы перейдете от 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
Я тоже был удивлен таким поведением, когда впервые столкнулся с ним. Это похоже на ошибку, но мне сказали, что это сделано намеренно.
Я согласен, это похоже на взлом вручную заполнить коллекцию.
Вместо этого вы можете использовать собственный загрузчик. Примерно так:
<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-запрос, если хотите больше контроля. Я иногда опускался до написания пользовательских загрузчиков, когда не мог перейти в спящий режим, чтобы сгенерировать нужный мне запрос. В любом случае, не знаю, почему я вообще не подумал об этом.
спасибо за ответ, когда я запускаю следующий код, первый запрос делает то, что вы ожидаете, возвращается только одно сообщение, но как только выполняется второй запрос, два запроса отправляются в базу данных, первый для получения отфильтрованных комментариев (бинго!), а затем секунда, чтобы заполнить свойство 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; }
}
есть идеи?
Сделайте коллекцию комментариев ленивой, чтобы спящий режим не загружал ее, когда вы получаете BlogPost. Затем используйте фильтр для коллекции комментариев.
comments = session.CreateFilter(blogPost.Comments, ... ).List();