许多Web应用程序中一个非常常见的用例是,用户可以在Web界面中对域对象进行排序 - 并且该命令会保留以供以后使用;但我注意到,每次我需要实现这一点时,我总是会提出一个不同的解决方案,并为一个简单的域对象增加了相当大的重量和复杂性。例如,假设我有持久性实体Person
Person {
long id
String name
}
用户前往/myapp/persons
并按照他们获得补偿(或其他)的顺序查看系统中的所有人员 - 所有人都可以点击并拖放到另一个位置 - 当页面时再次加载,订单被记住。问题是关系数据库似乎没有一个很好的方法来做到这一点; ORM也不是(我使用的是休眠)
我一直在考虑使用通用排序方法 - 但是会有一些开销,因为数据会单独持久化,这可能会减慢某些用例的访问速度。我的问题是:有没有人想出一个非常好的方法来建模持久域对象的顺序?
我使用Hibernate或JDBCTemplate在JavaEE中工作 - 因此任何代码示例都将以这些技术为基础最有用。或者任何概念性的想法都会受到欢迎。
更新:我不确定我哪里出错了,但似乎我不清楚,因为大多数回复的回复都不符合我的问题(因为它在我脑海中)。问题不在于我如何在获取行时对行或列进行排序 - 这是域对象的顺序发生变化 - 有人点击并将“人”从列表底部拖到列表顶部 - 他们刷新页面和列表现在按照他们指定的顺序。
答案 0 :(得分:1)
获取结果时,只需使用不同的ORDER BY子句构建HQL查询,具体取决于用户上次使用的内容
答案 1 :(得分:1)
问题是关系数据库似乎没有一个很好的方法来做到这一点; ORM也不是(我使用的是休眠)
我不确定你会在哪里得到这种印象。 Hibernate specifically has support for mapping indexed collections(这是另一个名称的“列表”),通常归结为在包含项目集合的表中存储“list-index”列。
直接从手册中获取的一个例子:
<list name="carComponents"
table="CarComponents">
<key column="carId"/>
<list-index column="sortOrder"/>
<composite-element class="CarComponent">
<property name="price"/>
<property name="type"/>
<property name="serialNumber" column="serialNum"/>
</composite-element>
</list>
这将允许List<CarComponents>
与您的根实体相关联,存储在CarComponents
表中,并带有sortOrder
列。
答案 2 :(得分:1)
一种可能的通用解决方案:
创建一个表来保存排序信息,最简单的情况是每个实体有一个方向的可排序字段:
table 'sorts'
* id: PK
* entity: String
* field: String
* direction: ASC/DESC enumeration (or ascending boolean flag)
通过添加userId来执行每用户排序或添加带有外键的sort_items表以支持一次按多个字段排序,可能会使其变得更加复杂。
一旦您保持排序信息,就可以将Order实例添加到条件(如果这是您正在使用的内容)或将语句按顺序连接到HQL。
这也可以使您的实体自身免受有序信息的影响,在这种情况下听起来像是正确的方法,因为排序纯粹是出于用户交互的目的。
更新 - 保留实体订单 鉴于您希望能够重新排序实体,而不仅仅是为它们定义排序,那么您确实需要将序数或索引值作为实体定义的一部分。
问题,因为我确定你意识到需要更新的实体数量,最糟糕的情况是将最后一个实体移动到列表顶部。
您可以使用1以外的增量值(比如10),这样您就可以:
ordinal | name
10 | Crosby
20 | Stills
30 | Nash
40 | Young
大多数情况下,更新行将涉及选择两个项目并更新一个项目。如果我想将Young移动到位置2,我从数据库中选择当前项目2和前一项目以获得序数10和20.使用这些来创建新的序数((20 - 10)/ 2 + 10 = 15) 。现在以15的顺序对Young进行单次更新。
如果你达到二分之一与你刚刚加载的实体之一产生相同索引的程度,那就意味着它需要产生一个任务来根据原始增量标准化序数值。
答案 3 :(得分:0)
据我所知,JPA 2.0支持有序列表: https://secure.wikimedia.org/wikibooks/en/wiki/Java_Persistence/Relationships#Order_Column_.28JPA_2.0.29
答案 4 :(得分:0)
我认为关系数据库不能比专用订购列做得更好。
除了游标之外,“订单”的概念并没有在SQL中真正定义,它们不是核心关系概念,而是实现细节。据我所知,唯一要做的就是用@OrderColumn(JPA2,Hibernate 3.5+兼容)抽象排序列。