怎样用此列表来排序彼列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
private List<TagGroup> reorder(Long id, List<TagGroup> entities) {
final AccountSettings accountSettings = getAccountSetting(
id);
final List<Long> tagGroupOrders = accountSettings.getTagGroupOrders();
// 根据 tagGroupOrders 里提供的 tagGroupId 对 entities 排序
if (CollectionUtils.isNotEmpty(tagGroupOrders)) {
entities.sort((o1, o2) -> {
int index1 = tagGroupOrders.indexOf(o1.getTagGroupId());
int index2 = tagGroupOrders.indexOf(o2.getTagGroupId());
// 不对没有出现在列表里的 tagGroup 进行排序
if (index1 == -1 || index2 == -1) {
return sortByModifiedTime(o1, o2);
}
return index1 - index2;
});
}
// 还有一种潜在的排序方法是在这里加一个else分支,只对modified time 进行排序

// 返回排序后的结果
return entities;
}

private static int sortByModifiedTime(TagGroup o1, TagGroup o2) {
final long time1 = o1.getLastModifiedTime().getTime();
final long time2 = o2.getLastModifiedTime().getTime();
if (time1 < time2) {
return -1;
} else if (time1 > time2) {
return 1;
} else {
return 0;
}
}

怎样每次生成一把锁实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
@Slf4j
@Component
@Scope("prototype")
public class LockRunner {

private RedissonClient redissonClient;

/**
* 私有构造器
*/
@Autowired
public LockRunner(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}

@WithSpan
public void runInLock(@SpanAttribute("lockConfig") LockKey lockKeyConfig, Runnable runnable) {
final String lockKey = lockKeyConfig.getLockKey();
RLock lock = redissonClient.getLock(lockKey);
// 新的锁是无限锁模式,只要锁的key包含细颗粒的id(手机号、线索id、呼叫id)就不会超时有问题
lock.lock();
try {
runnable.run();
} finally {
unlock(lock);
}
}

@WithSpan
public <V> V callInLock(@SpanAttribute("lockConfig") LockKey lockKeyConfig, Callable<V> callable) {
final String lockKey = lockKeyConfig.getLockKey();
RLock lock = redissonClient.getLock(lockKey);
// 新的锁是无限锁模式,只要锁的key包含细颗粒的id(手机号、线索id、呼叫id)就不会超时有问题
lock.lock();
try {
return callable.call();
} catch (Exception e) {
throw new SystemInternalException("callable.call()失败:" + e.getMessage(), e);
} finally {
unlock(lock);
}
}

private void unlock(RLock lock) {
log.info("unlock for: {}", lock.getName());
lock.unlock();
}
}

@Component
public class LockRunnerFactory {

private final ApplicationContext applicationContext;

@Autowired
public LockRunnerFactory(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}

public LockRunner createLockRunner() {
return applicationContext.getBean(LockRunner.class);
}
}

一个更好的设计是去掉@Scope("prototype")LockRunnerFactoryLockRunner的可变状态都被参数化了,所有最好的设计实际上是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
@Data
public class LockConfig {

/**
* 锁的后缀
*/
public static final String LOCK_SUFFIX = "-lock";

/**
* 超时时间
*/
private final int expireSecs;

/**
* 真正的锁键
*/
private final String lockKey;

private LockConfig(final int expireSecs, final String lockKey) {
this.expireSecs = expireSecs;
this.lockKey = lockKey;
}

public LockConfig(final int expireSecs, final Object... objects) {
this(expireSecs, Joiner.on("-").join(objects) + LOCK_SUFFIX);
}
}

@Data
public class LockKey {

/**
* 锁的后缀
*/
public static final String LOCK_SUFFIX = "-lock";


/**
* 真正的锁键
*/
private final String lockKey;

public LockKey(final Object... objects) {
lockKey = Joiner.on("-").join(objects) + LOCK_SUFFIX;
}

}

在还原一个字段的时候,怎么确定它有没有被修改过?

一个字段是 ownerId。它曾经是1,无意之中被设置为0,能不能恢复为1?
假设有另一个字段为 ownerName,有意设置 ownerId 的时候,一定会清空 ownerName。则可以做这样的比对:

1
2
3
if (owner == 0 && StringUtils.isNotBlank(ownerName)) {
owner = 1;
}