我想使用HazlecastRepository保存一个新实体。当id为null时,KeyValueTemplate使用SecureRandom并生成类似于-123123123123123123的id。
我不想这样保存id,相反,我想从db的序列中获取它并将其放入地图。
我找到2个解决方案:
1)在AdminService中,从数据库序列中获取下一个值并进行设置
2)在Hazelcast服务器中创建原子计数器ID,并使用序列中的当前值对其进行初始化。在AdminService中,获取计数器,增加值并设置ID。
但是它们不是很漂亮。
您还有其他想法吗?
代码:
@Configuration
@EnableHazelcastRepositories(basePackages = "com.test")
public class HazelcastConfig {
@Bean
public HazelcastInstance hazelcastInstance(ClientConfig clientConfig) {
return HazelcastClient.newHazelcastClient(clientConfig);
}
@Bean
@Qualifier("client")
public ClientConfig clientConfig() {
ClientConfig clientConfig = new ClientConfig();
clientConfig.setClassLoader(HazelcastConfig.class.getClassLoader());
ClientNetworkConfig networkConfig = clientConfig.getNetworkConfig();
networkConfig.addAddress("127.0.0.1:5701");
networkConfig.setConnectionAttemptLimit(20);
return clientConfig;
}
@Bean
public KeyValueTemplate keyValueTemplate(ClientConfig clientConfig) {
return new KeyValueTemplate(new HazelcastKeyValueAdapter(hazelcastInstance(clientConfig)));
}
}
@Service
@RequiredArgsConstructor
public class AdminService {
private final UserRepository userRepository;
...
@Transactional
public User addOrUpdateUser(UserUpdateDto dto) {
validate(dto);
User user = dto.getId() != null ? userService.getUser(dto.getId()) : new User();
mapUser(user, dto);
return userRepository.save(user);
}
...
}
@Repository
public interface UserRepository extends HazelcastRepository<User, Long> {
}
@KeySpace("users")
@Entity
@Table(name = "users)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User extends DateAudit implements Serializable {
@javax.persistence.Id
@org.springframework.data.annotation.Id
// @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_generator")
// @SequenceGenerator(name="user_generator", sequenceName = "user_seq")
private Long id;
...
}
Hazelcast服务器:
@Component
@Slf4j
public class UserLoader implements ApplicationContextAware, MapStore<Long, User> {
private static UserJpaRepository userJpaRepository;
@Override
public User load(Long key) {
log.info("load({})", key);
return userJpaRepository.findById(key).orElse(null);
}
@Override
public Map<Long, User> loadAll(Collection<Long> keys) {
Map<Long, User> result = new HashMap<>();
for (Long key : keys) {
User User = this.load(key);
if (User != null) {
result.put(key, User);
}
}
return result;
}
@Override
public Iterable<Long> loadAllKeys() {
return userJpaRepository.findAllId();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
userJpaRepository = applicationContext.getBean(UserJpaRepository.class);
}
@Override
public void store(Long aLong, User user) {
userJpaRepository.save(user);
}
@Override
public void storeAll(Map<Long, User> map) {
for (Map.Entry<Long, User> mapEntry : map.entrySet()) {
store(mapEntry.getKey(), mapEntry.getValue());
}
}
@Override
public void delete(Long aLong) {
userJpaRepository.deleteById(aLong);
}
@Override
public void deleteAll(Collection<Long> collection) {
collection.forEach(this::delete);
}
}
public interface UserJpaRepository extends CrudRepository<User, Long> {
@Query("SELECT u.id FROM User u")
Iterable<Long> findAllId();
}
我认为没有比您描述的更好的方法了。
我会选择第二种解决方案,因为那样的话,您至少只与Hazelcast服务器耦合。