Spring Data JPA – Programmatically Create JPA Repository Not Saving Data

  Kiến thức lập trình

Creating a JPA repository “on the fly” does not seem to work for saving entities (with or without transaction management). Yet it works fine for retrieving data. No error is thrown. With SQL debugging enabled, SQL statements are shown for data retrieval but not for saving data.

I know I can use spring annotations to do this, but I need to create the repository on the fly to allow access to multiple databases. Configuring emf, em and transaction manager beans using @Bean is also not suitable, because in my “real” application, only when the saveIt method (below example) runs, do we know the actual datasource. The datasource can change in realtime depending on various business rules.

    @RestController
@RequestMapping("/api")
public class BasicRestController {

    private final CompanyService databaseService;

    public BasicRestController(CompanyService databaseService) {
        this.databaseService = databaseService;
    }

    @GetMapping("/saveIt")
    public ResponseEntity<String> saveIt() {
        databaseService.saveIt();
        return new ResponseEntity<>("whatever", HttpStatus.OK);
    }

    @GetMapping("/saveItInTx")
    public ResponseEntity<String> saveItInTransaction() {
        databaseService.saveItInTransaction();
        return new ResponseEntity<>("whatever", HttpStatus.OK);
    }

@Service
public class CompanyService {

    private final Environment env;

    private EntityManagerFactory emf;

    public CompanyService(Environment env) {
        this.env = env;
    }

    public void saveIt() {
        CompanyRepository companyRepository = createJpaRepository();
        // This correctly prints "Stupid Company"
        System.out.println("Allegedly saved company: " + companyRepository.save(new Company("Stupid Company")).getName());
        // This list all the companies already in the database - the allegedly saved company is missing!
        companyRepository.findAll().forEach(company -> System.out.println(company.getName()));
    }

    public void saveItInTransaction() {
        TransactionTemplate transactionTemplate = createTransactionTemplate();
        transactionTemplate.execute(status -> {
            saveIt();
            return null;
        });
    }

    private CompanyRepository createJpaRepository() {
        LocalContainerEntityManagerFactoryBean emfBean = createEntityManagerFactoryBean();
        emf = emfBean.getObject();
        assert emf != null;
        EntityManager em = emf.createEntityManager();
        return new JpaRepositoryFactory(em).getRepository(CompanyRepository.class);
    }

    private LocalContainerEntityManagerFactoryBean createEntityManagerFactoryBean() {
        LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean();
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl(env.getProperty("spring.datasource.url"));
        dataSource.setUsername(env.getProperty("spring.datasource.username"));
        dataSource.setPassword(env.getProperty("spring.datasource.password"));
        dataSource.setDriverClassName(Objects.requireNonNull(env.getProperty("spring.datasource.driver-class-name")));
        emfBean.setDataSource(dataSource);
        emfBean.setPackagesToScan("com.crowfoot.crap.model");
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        emfBean.setJpaVendorAdapter(vendorAdapter);
        HashMap<String, Object> properties = new HashMap<>();
        properties.put("hibernate.hbm2ddl.auto", env.getProperty("spring.jpa.properties.hibernate.ddl-auto"));
        properties.put("hibernate.physical_naming_strategy", env.getProperty("spring.jpa.properties.hibernate.naming.physical-strategy"));
        properties.put("hibernate.dialect", env.getProperty("spring.jpa.properties.hibernate.dialect"));
        emfBean.setJpaPropertyMap(properties);
        emfBean.setPersistenceUnitName("tryItPU");
        emfBean.afterPropertiesSet();
        return emfBean;
    }

    private TransactionTemplate createTransactionTemplate() {
        PlatformTransactionManager platformTransactionManager = new JpaTransactionManager(emf);
        return new TransactionTemplate(platformTransactionManager);
    }

}

@Repository
public interface CompanyRepository extends JpaRepository<Company, Integer> {
}

spring:
  datasource:
    url: jdbc:mariadb://localhost:3306/comparison_tim_test
    username: some_user
    password: some_password
    driver-class-name: org.mariadb.jdbc.Driver
  jpa:
    properties:
      hibernate:
        ddl-auto: none
        naming:
          physical-strategy: org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
      open-in-view: false
      # Debug Hql
      show_sql: true
      format_sql: true
logging:
  level:
    root: info
    org:
      hibernate:
        SQL: debug
        type:
          descriptor:
            sql: trace



Theme wordpress giá rẻ Theme wordpress giá rẻ Thiết kế website

LEAVE A COMMENT