我正在寻找一种有效的方法来坚持一周的日子。换句话说,用户将从工作日列表中选择任意天数。具体日期无关紧要,只是一周中的某一天。我需要将这一天存储在一个休眠实体中。
我可以存储其中一个:
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。
我担心的是对这样的字段执行查询。我是否能够找到所有选择了Wed的实体?
这看起来像是一种好方法吗?有没有人有更好的主意?
谢谢!
答案 0 :(得分:5)
您可以使用枚举来设置星期几
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;
}
不要忘记复合元素的生命周期或值类型实例受拥有实体实例的生命周期限制。
如上所述:
我是否能够找到所有选择了Wed的实体?
是
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
}
}
因此,某些用例仅是否需要CUSTOMER,我打电话
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 :(得分:1)
比特方法确实会使所有具有特定工作日的实体难以查询。
在SQL或HQL中查询它的自然方法是让SQL函数使用SQL位操作进行解码。或者,如果您正在使用Criteria和Restrictions,则可以构建一个IN子句,该子句匹配具有相应位集的所有数字。这些都不是很好......
您也可以使用七个单独的布尔字段对其进行映射,这样可以简化查询,但Java实体代码很难看。
我将创建一个工作日枚举并在您的实体中放置一个Set<Weekday>
,这将创建一个额外的表,但保持Java实体的合理性和查询相对容易。而且我可能会使用eager(FetchMode.JOIN)获取来映射该Set,因为该集合最多只有七个元素。
Map<Weekday, Boolean>
也是可能的,但我肯定会跳过这一个!
答案 2 :(得分:0)
我也是这样做的
为了清楚起见,有些人会在表格中插入X行或列(每天一个)
事情是,你需要速度还是清晰度?
答案 3 :(得分:0)
我认为这不比Set简单。它使用较少的数据库空间,但数据库空间通常不昂贵。它肯定会使查询变得更加困难,并且还会使您的代码更易于人工阅读。
答案 4 :(得分:0)
将其存储为一个集合 - 最有可能在单独的'days'和'userChosenDays'表中 - 将是最具人类可读性的,特别是如果您直接处理查询语言。它也是最具扩展性的。
但是,SQL确实提供了按位运算符,因此如果您计划通过Web界面处理数据库或者无论如何都会使用复选框样式的过滤器,那么就可以轻松地对单列进行逐位查询可用性不会受到影响。
假设数据库已正确索引和规范化,空间和速度差异应该是可以忽略的,我建议存储一整套方法,因为可维护性通常比较小的性能提升更重要。