Estoy usando el repositorio de Spring data JPA para mi aplicación. Actualmente estoy usando operaciones CRUD básicas proporcionadas de forma predeterminada por los repositorios jpa de datos de primavera y para consultas de combinación complejas, estoy escribiendo consultas JPQL personalizadas de la siguiente manera:
public interface ContinentRepository extends JpaRepository<Continent, Long> { @Query(value = "SELECT u FROM Continent u JOIN FETCH ... WHERE u.id = ?1") public List<Continent> findContinent(Long id); }En mi clase de servicio, estoy autoconectando este repositorio y realizando operaciones de base de datos.
@Service public class MyService { @Autowired public ContinentRepository cr; public void read() { var result1 = cr.findContinent(1); var result2 = cr.findContinent(2); } @Transactional public void write() { var c = new Continent(); // setters c = cr.save(c); } } Actualmente solo estoy marcando write() como org.springframework.transaction.annotation.Transactional .
read() con Transactional(readOnly = true) ? Como solo realiza operaciones de lectura.findContinent(Long id) como Transactional(readOnly = true)? Leí que todos los métodos predeterminados están marcados como Transaccional https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions
- ¿Debería marcar también el método read() con Transactional(readOnly = true)? Como solo realiza operaciones de lectura.
No es realmente necesario, sin embargo, podría crear algunas optimizaciones con respecto al consumo de memoria caché de acuerdo con este blog https://vladmihalcea.com/spring-read-only-transaction-hibernate-optimization/
- ¿Debería marcar también findContinent(Long id) como Transactional(readOnly = true)? Leí que todos los métodos predeterminados están marcados como Transaccional https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions
La misma respuesta que en el primer caso.
- En la interfaz del repositorio, ¿debería marcar la anotación transaccional en el nivel de método o en el nivel de interfaz? (Además, sospecho que la mayoría de los métodos personalizados serán de solo lectura)
En general, agregué al nivel del método, porque tengo más control sobre los parámetros como la reversión.
- ¿Es bueno tener @Transactional tanto en la capa de Servicio como en la de Repositorio?
Te recomiendo que tengas en el nivel de Servicio porque, allí, puedes actualizar muchas tablas (para que puedas usar muchos repositorios), y quieres que toda tu actualización sea transaccional.
- ¿Debería marcar también el método read() con Transactional(readOnly = true)? Como solo realiza operaciones de lectura.
Sí. Es una buena práctica, sabrá de inmediato que este método no cambia nada en la base de datos y, lo que es más importante, deshabilitará algunos cambios no intencionales en la base de datos utilizando este método de servicio. Si este método intenta realizar alguna actualización en la base de datos, se lanzará una excepción y se llamará a la reversión.
- ¿Debería marcar también findContinent(Long id) como Transactional(readOnly = true)? Leí que todos los métodos predeterminados están marcados como Transaccional https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions
Depende de cómo lo estés usando. Si siempre está llamando a esto desde @Sevice, entonces no. Creo que es un caso de uso común hasta donde yo sé.
- En la interfaz del repositorio, ¿debería marcar la anotación transaccional en el nivel de método o en el nivel de interfaz? (Además, sospecho que la mayoría de los métodos personalizados serán de solo lectura)
Igual que 2.
- ¿Es bueno tener @Transactional tanto en la capa de Servicio como en la de Repositorio?
Igual que 2.