首先,根据您所做的描述尚不清楚,但是您需要一个PlaylistSongs
包含a PlaylistId
和a 的表SongId
描述哪些歌曲属于哪些播放列表。
您必须在此表中添加订购信息。
我最喜欢的机制是实数。我最近实现了它,并且像个魅力一样起作用。当您要将一首歌曲移至特定位置时,可以将其新Ordering
值计算Ordering
为上一首和下一首歌曲的平均值。如果您使用64位实数,则将在大约死地狱的同一时间用完精度,但如果您实际上是为后代编写软件,则可以考虑Ordering
为每首歌曲中的所有歌曲重新分配漂亮的舍入整数值每隔一段时间播放一次播放列表。
另外,这是我编写的实现此目的的代码。当然,您不能按原样使用它,对我来说,现在为您清理它将是一件繁重的工作,因此,我仅将其发布给您以从中获取想法。
该类是ParameterTemplate
(无论什么都不要问!)。该方法从其父级获取此模板所属的参数模板的列表ActivityTemplate
。(无论如何,不要问!)代码中包含一些防止精度用完的保护措施。除数用于测试:单元测试使用大除数,以快速耗尽精度,从而触发精度保护代码。第二种方法是公共的,并且“仅供内部使用;请勿调用”,以便测试代码可以调用它。(它不能是私有程序包,因为我的测试代码与其测试的代码不在同一个程序包中。)控制顺序的字段称为Ordering
,通过getOrdering()
和访问setOrdering()
。您没有看到任何SQL,因为我正在通过Hibernate使用对象关系映射。
/**
* Moves this {@link ParameterTemplate} to the given index in the list of {@link ParameterTemplate}s of the parent {@link ActivityTemplate}.
*
* The index must be greater than or equal to zero, and less than or equal to the number of entries in the list. Specifying an index of zero will move this item to the top of
* the list. Specifying an index which is equal to the number of entries will move this item to the end of the list. Any other index will move this item to the position
* specified, also moving other items in the list as necessary. The given index cannot be equal to the current index of the item, nor can it be equal to the current index plus
* one. If the given index is below the current index of the item, then the item will be moved so that its new index will be equal to the given index. If the given index is
* above the current index, then the new index of the item will be the given index minus one.
*
* NOTE: this method flushes the persistor and refreshes the parent node so as to guarantee that the changes will be immediately visible in the list of {@link
* ParameterTemplate}s of the parent {@link ActivityTemplate}.
*
* @param toIndex the desired new index of this {@link ParameterTemplate} in the list of {@link ParameterTemplate}s of the parent {@link ActivityTemplate}.
*/
public void moveAt( int toIndex )
{
moveAt( toIndex, 2.0 );
}
/**
* For internal use only; do not invoke.
*/
public boolean moveAt( int toIndex, double divisor )
{
MutableList<ParameterTemplate<?>> parameterTemplates = getLogicDomain().getMutableCollections().newArrayList();
parameterTemplates.addAll( getParentActivityTemplate().getParameterTemplates() );
assert parameterTemplates.getLength() >= 1; //guaranteed since at the very least, this parameter template must be in the list.
int fromIndex = parameterTemplates.indexOf( this );
assert 0 <= toIndex;
assert toIndex <= parameterTemplates.getLength();
assert 0 <= fromIndex;
assert fromIndex < parameterTemplates.getLength();
assert fromIndex != toIndex;
assert fromIndex != toIndex - 1;
double order;
if( toIndex == 0 )
{
order = parameterTemplates.fetchFirstElement().getOrdering() - 1.0;
}
else if( toIndex == parameterTemplates.getLength() )
{
order = parameterTemplates.fetchLastElement().getOrdering() + 1.0;
}
else
{
double prevOrder = parameterTemplates.get( toIndex - 1 ).getOrdering();
parameterTemplates.moveAt( fromIndex, toIndex );
double nextOrder = parameterTemplates.get( toIndex + (toIndex > fromIndex ? 0 : 1) ).getOrdering();
assert prevOrder <= nextOrder;
order = (prevOrder + nextOrder) / divisor;
if( order <= prevOrder || order >= nextOrder ) //if the accuracy of the double has been exceeded
{
parameterTemplates.clear();
parameterTemplates.addAll( getParentActivityTemplate().getParameterTemplates() );
for( int i = 0; i < parameterTemplates.getLength(); i++ )
parameterTemplates.get( i ).setOrdering( i * 1.0 );
rocs3dDomain.getPersistor().flush();
rocs3dDomain.getPersistor().refresh( getParentActivityTemplate() );
moveAt( toIndex );
return true;
}
}
setOrdering( order );
rocs3dDomain.getPersistor().flush();
rocs3dDomain.getPersistor().refresh( getParentActivityTemplate() );
assert getParentActivityTemplate().getParameterTemplates().indexOf( this ) == (toIndex > fromIndex ? toIndex - 1 : toIndex);
return false;
}