#spring-boot #spring-data-jpa #spring-data
Вопрос:
В моем приложении spring boot версии v2.5.5 настроена основная подчиненная база данных mysql.
Конфигурация Основного Источника Данных
@EnableJpaRepositories( basePackages = "com.dummy", excludeFilters = @ComponentScan.Filter(ReadOnlyRepository.class), entityManagerFactoryRef = "primaryEntityManagerFactory", transactionManagerRef = "primaryTransactionManager" ) @Configuration public class PrimaryDataSourceConfig { @Autowired private Environment env; @Value("${master.jdbc.url}") private String jdbcURL; @Bean @Primary public DataSource primaryDataSource() throws Exception { return DataSourceBuilder.create() .driverClassName("com.mysql.jdbc.Driver") .url(jdbcURL) .username("root") .password("root").build(); } @Bean @Primary public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory() throws Exception { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(primaryDataSource()); em.setPackagesToScan("com.dummy"); HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); vendorAdapter.setGenerateDdl(false); em.setJpaVendorAdapter(vendorAdapter); em.setJpaProperties(additionalProperties()); return em; } @Bean @Primary public PlatformTransactionManager primaryTransactionManager() throws Exception { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(primaryEntityManagerFactory().getObject()); return transactionManager; } final Properties additionalProperties() { final Properties hibernateProperties = new Properties(); hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("primary.hibernate.hbm2ddl.auto")); hibernateProperties.setProperty("hibernate.dialect", env.getProperty("primary.hibernate.dialect")); hibernateProperties.setProperty("hibernate.show_sql", env.getProperty( "primary.hibernate.show_sql")); hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", "false"); return hibernateProperties; } }
Конфигурация Подчиненного Источника Данных
@Configuration @EnableJpaRepositories( basePackages = "com.dummy.submodule", includeFilters = @ComponentScan.Filter(ReadOnlyRepository.class), entityManagerFactoryRef = "readOnlyEntityManagerFactory", transactionManagerRef = "readOnlyTransactionManager" ) public class ReadOnlyDataSourceConfig { @Autowired private Environment env; @Value("${slave.jdbc.url}") private String jdbcURL; @Bean public DataSource readOnlyDataSource() throws Exception { return DataSourceBuilder.create() .driverClassName("com.mysql.jdbc.Driver") .url(jdbcURL) .username("root") .password("root").build(); } @Bean public LocalContainerEntityManagerFactoryBean readOnlyEntityManagerFactory() throws Exception { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(readOnlyDataSource()); em.setPackagesToScan("com.dummy.submodule"); HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); vendorAdapter.setGenerateDdl(false); em.setJpaVendorAdapter(vendorAdapter); em.setJpaProperties(additionalProperties()); return em; } @Bean public PlatformTransactionManager readOnlyTransactionManager() throws Exception { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(readOnlyEntityManagerFactory().getObject()); return transactionManager; } final Properties additionalProperties() { final Properties hibernateProperties = new Properties(); hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("readonly.hibernate.hbm2ddl.auto")); hibernateProperties.setProperty("hibernate.dialect", env.getProperty("readonly.hibernate.dialect")); hibernateProperties.setProperty("hibernate.show_sql", env.getProperty( "readonly.hibernate.show_sql")); hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", "false"); return hibernateProperties; } }
Entity
@Entity @Getter @Setter public class Product implements Serializable { private static final long serialVersionUID = 8135071385764991866L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @OneToOne(fetch = FetchType.LAZY) @NotNull @JoinColumn(name = "status") private Order order } @Getter @Setter @Entity public class Order implements Serializable { private static final long serialVersionUID = 8135071385764991879L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private Date orderdate; }
I am trying to fetch Product from read only(slave) db in my service layer
@Service @AllArgsConstructor public class ProductService{ private ProductRepository repo; public void performOperation(){ Optionallt;Productgt; product = repo.findById(1l, Product.class); if(product.isPresent()){ Order order = product.get().getOrder(); Date orderDate = order.getOrderDate(); // this line gives below exception } } }
Репозиторий только для чтения:
@Repository @ReadOnlyRepository public interface ProductRepository extends JpaRepositorylt;Product, Longgt; { lt;Tgt; Optionallt;Tgt; findById(final Long id, Classlt;Tgt; type); }
Исключение:
2021-10-22 12:35:11,109 ERROR [http-nio-8080-exec-8] com.dummy.logging.LoggingClass:41 Exception_Occurred::{} org.springframework.orm.jpa.JpaSystemException: could not initialize proxy [com.dummy.submodule.entities.Order#orderdate] - no Session; nested exception is org.hibernate.LazyInitializationException: could not initialize proxy [com.dummy.submodule.entities.Order#orderdate] - no Session
Примечание: Исключение LazyInitializationException возникает только тогда, когда я извлекаю продукт из подчиненной бд. Когда та же операция, которую я пытаюсь выполнить с помощью основной базы данных, я не получаю исключение LazyInitializationException.
Эту проблему на данный момент я решил, сделав заказ как тип выборки.жаждущий. Но я пытаюсь выяснить причину этого в случае с бд master slave и как добиться этого с помощью ЛЕНИВОГО типа выборки.
Ответ №1:
Прокомментируйте performOperation
@Transactional
как показано ниже:
@Service @AllArgsConstructor public class ProductService{ private ProductRepository repo; @Transactional public void performOperation(){ Optionallt;Productgt; product = repo.findById(1l, Product.class); if(product.isPresent()){ Order order = product.get().getOrder(); Date orderDate = order.getOrderDate(); // this line gives below exception } } }