SpringBoot 中 Service 的只读权限

问题描述 投票:0回答:1

我在 SpringBoot 中有一个控制器,当向端点发出请求时,它会调用 SpringBoot 服务。

该服务使用entityManager 在数据库上执行查询。这些查询可以是任何类型,包括选择和截断,这会修改我的数据库,但我不希望这样。

我希望我的服务具有只读权限。但是,我的应用程序中还有其他服务需要写入权限,因此更改数据库用户对我来说不起作用。

我使用的案例的示例代码是:

@RestController
public class TestController {

  @Autowired private TestService testService;

  @GetMapping(value = “/test”, produces = "text/plain")
  @ResponseBody
  public ResponseEntity<String> getResponse(@RequestParam(value = “message”) String message) {
    log.info("Received message: {}", message);
    List<Map<String, Object>> response = testService.getResults(message);
    // ad hoc code
  }
}

接下来,我想要对数据库具有只读权限的服务(通过entityManager)

@Service
public class TestService {

  @Autowired client<?> client;

  @PersistenceContext EntityManager entityManager;

  public List<Map<String, Object>> getResults(String userMessage) {
    final String query = client.generateQuery(userMessage).toLowerCase();
    NativeQueryImpl nativeQuery = (NativeQueryImpl) entityManager.createNativeQuery(query);
    nativeQuery.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
    List<Map<String, Object>> result = nativeQuery.getResultList();
    return result;
  }
}

只要能达到预期的结果,任何其他方法都是合适的。

我尝试将服务设置为Transactional(readOnly = true),但它只影响性能,而不影响服务权限:

    /**
     * A boolean flag that can be set to {@code true} if the transaction is
     * effectively read-only, allowing for corresponding optimizations at runtime.
     * <p>Defaults to {@code false}.
     * <p>This just serves as a hint for the actual transaction subsystem;
     * it will <i>not necessarily</i> cause failure of write access attempts.
     * A transaction manager which cannot interpret the read-only hint will
     * <i>not</i> throw an exception when asked for a read-only transaction
     * but rather silently ignore the hint.
     * @see org.springframework.transaction.interceptor.TransactionAttribute#isReadOnly()
     * @see org.springframework.transaction.support.TransactionSynchronizationManager#isCurrentTransactionReadOnly()
     */
    boolean readOnly() default false;
java spring spring-boot entitymanager
1个回答
0
投票

第一个想法:我认为这通常是不强制执行的。您可以编写一个只执行读取操作的服务,并将其注入到您的控制器中。毕竟,您可以控制自己的代码。

进一步看,您可以将存储库与服务分开。在您的示例中,两者都在一个类中,通常它们是分开的。这将允许您为此目的创建一个只读存储库。

@Service
public class TestService {

    @Autowired
    private TestReadOnlyRepository testReadOnlyRepository;

    public List<TestEntry> getResults(String userMessage) {
        return testReadOnlyRepository.findById(userMessage);
    }

创建一个与存储库一起使用的实体,而不是列表>

@Entity
public class TestEntry {
    @Id
    @GeneratedValue
    private String key;
    private String value;
}

注意,我没有使用对象作为值,因为我不知道对象在数据库中是什么列类型。

对于存储库本身,我们可以从 Baeldung 借用来创建一个通用的只读 Spring 数据存储库:

@NoRepositoryBean
public interface ReadOnlyRepository<T, ID> extends Repository<T, ID> {
    Optional<T> findById(ID id);
    List<T> findAll();
}

public interface TestReadOnlyRepository extends ReadOnlyRepository<TestEntry , String> { 
    // we only use the methods offered by the ReadOnlyRepository
} 
© www.soinside.com 2019 - 2024. All rights reserved.