Сохраняя набор Дней недели - PullRequest
3 голосов
/ 10 февраля 2010

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

Я мог бы хранить один из них:

Set<DayOfWeek>
Set<Integer>

Но я думаю, что это может быть проще, чем это. Что, если я просто использую один int для хранения данных и использую побитовые операции. Например:

Sun = 1
Mon = 2
Tue = 4
Wed = 8
Thu = 16
Fri = 32
Sat = 64

Таким образом, чтобы представить множество Солнца, Понедельника, Среды, Сб, я бы сохранил целое число 75. Это потому, что 1 + 2 + 8 + 64 = 75.

Моя задача - выполнять запросы в таких областях, как это. Смогу ли я найти все объекты, которые были выбраны в Ср?

Это похоже на хороший подход? У кого-нибудь есть идея получше?

Спасибо!

Ответы [ 5 ]

5 голосов
/ 10 февраля 2010

Вы можете использовать Enum для установки дней недели

public enum DAYS_OF_THE_WEEK {
    SUN,
    MON,
    TUE,
    WED,
    THU,
    FRI,
    SAT;
}

Теперь вы можете использовать коллекцию типов значений, поскольку Hibernate поддерживает ее.

@CollectionOfElements
@Enumerated(EnumType.STRING)
@JoinTable(
    name="SELECTED_DAYS_OF_THE_WEEK",
    joinColumns=@JoinColumn(name="<OWNING_ENTITY_ID_GOES_HERE>")
)
public Set<DAYS_OF_THE_WEEK> getSelectedDays() {
    return this.selectedDays;
}

Не забывайте, что срок жизни составного элемента или экземпляра типа значения ограничен сроком жизни экземпляра объекта-владельца.

Как сказано:

Смогу ли я найти все объекты, которые были выбраны в Ср?

Да

select distinc OwningEntity _owningEntity inner join fetch _owningEntity.selectedDays selectedDay where selectedDay = :selectedDay

query.setParameter("selectedDay", DAYS_OF_THE_WEEK.WED);

query.list();

Добавлено к исходному ответу : как мне реализовать FetchingStrategy

Предположим, следующая модель

@Entity
public class Customer {

    private List<Order> orderList = new ArrayList<Order>();

    // getter's and setter's

}

Теперь наш интерфейс CustomerRepository

public interface CustomerRepository {

    Customer getById(Integer id, CustomerFetchingStrategy fetchingStrategy);
    List<Customer> getAll(CustomerFetchingStrategy fetchingStrategy);

    public static enum CustomerFetchingStrategy {
        PROXY,
        CUSTOMER,
        CUSTOMER_WITH_ORDERS;         
    }

}

Наша реализация

import static br.com.app.CustomerRepository.CustomerFetchingStrategy;

public class CustomerRepositoryImpl implements CustomerRepository {

    // Usually Spring IoC or Seam @In-jection or something else
    private SessionFactory sessionFactory;

    public Customer getById(Integer id, CustomerFetchingStrategy fetchingStrategy) {
        switch(fetchingStrategy) {
            case PROXY:
                return (Customer) sessionFactory.getCurrentSession().load(Customer.class, id);
            case CUSTOMER:
                return (Customer) sessionFactory.getCurrentSession().get(Customer.class, id);
            case CUSTOMER_WITH_ORDERS:
                return (Customer) sessionFactory.getCurrentSession().createQuery("from Customer c left join fetch c.orderList where c.id = :id")
                                  .setParameter("id", id)
                                  .list().get(0);
        }
    }

    public List<Customer> getAll(CustomerFetchingStrategy fetchingStrategy) {
        // Same strategy as shown above
    }

} 

Так что, если какой-то вариант использования только нуждается в ЗАКАЗЧИКЕ, я звоню

import static br.com.app.CustomerRepository.CustomerFetchingStrategy;

public class SomeController {

    // Again Spring Ioc or Seam @In-jection
    private CustomerRepository customerRepository;

    public void proccessForm(HttpServletRequest request, HttpServletResponse response) {
        request.setParameter("customer", customerRepository.getById(Integer.valueOf(request.getParameter("customerId"))), CUSTOMER);
    }
}

Я надеюсь, что это может быть полезно для вас

С уважением,

1 голос
/ 10 февраля 2010

Битовый подход действительно затруднит запросы для всех объектов с определенным днем ​​недели.

Естественный способ запросить это в SQL или HQL - задействовать функцию SQL, выполняющую декодирование с использованием битовых операций SQL. Или, если вы используете критерии и ограничения, вы можете создать предложение IN, соответствующее всем числам с соответствующим установленным битом. Ни один из них не хорош ...

В качестве альтернативы вы могли бы сопоставить его с семью отдельными логическими полями, что сделало бы запросы простыми, но код сущности Java уродливым.

Я бы пошел с созданием перечисления Weekday и помещением Set<Weekday> в вашу сущность, которая создаст дополнительную таблицу, но сохранит разумность сущности Java и сделает запрос относительно простым. И я бы, вероятно, отобразил этот Set с нетерпением (FetchMode.JOIN), так как в наборе будет всего семь элементов максимум.

A Map<Weekday, Boolean> также возможно, но я бы, конечно, пропустил это!

0 голосов
/ 10 февраля 2010

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

0 голосов
/ 10 февраля 2010

Хранение в виде набора - скорее всего, в отдельной таблице «days» и «userChosenDays» - будет наиболее читабельным, особенно если вы имеете дело непосредственно с языком запросов. Это также самый расширяемый.

Однако SQL предоставляет побитовые операторы, поэтому, если вы планируете работать с базой данных через веб-интерфейс или что-то, что в любом случае будет иметь фильтры в стиле флажков, было бы легко просто выполнить побитовый запрос к одному столбцу и на удобство использования не повлияет.

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

0 голосов
/ 10 февраля 2010

я бы тоже так сделал

некоторые люди просто для ясности вставляют X строк или столбцов (по одному на каждый день) в таблицу

Дело в том, вам нужна скорость или четкость?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...