Skip to main content
deleted 22 characters in body
Source Link
life888888
  • 4k
  • 2
  • 8
  • 15
package com.example;AnagRepositoriesConfigexample;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
package com.example;AnagRepositoriesConfig

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
added 227 characters in body
Source Link
life888888
  • 4k
  • 2
  • 8
  • 15

For information on using non-default Datasource settings, please refer to howto.data-access.configure-two-datasources

For information on using non-default Datasource settings, please refer to howto.data-access.configure-two-datasources

Source Link
life888888
  • 4k
  • 2
  • 8
  • 15

This is a proof-of-concept test.

  • application.yaml : remove hibernate: hbm2ddl:
  • AnagSourceConfiguration.java : The main changes are all in this file.
  • AnagRepositoriesConfig.java : The file is not required.

Database - Docker

docker run \
    --name my-mysql-temp \
    -e MYSQL_ROOT_PASSWORD=Passw0rd! \
    -e MYSQL_DATABASE=demodb \
    -e MYSQL_USER=demouser \
    -e MYSQL_PASSWORD=Passw0rd! \
    -p 3306:3306 \
    -d \
    mysql:8.0.43-debian

Project Tree

demo-mysql-jpa_ST
├── pom.xml
├── README.txt
└── src
    └── main
        ├── resources
        │   └── application.yaml <-- Change
        └── java
            └── com
                └── example
                    ├── DemoApplication.java
                    ├── config
                    │   └── AnagSourceConfiguration.java <-- Change
                    ├── entity
                    │   └── anag
                    │       └── Student.java
                    ├── repo
                    │   └── anag
                    │       └── StudentRepository.java
                    ├── service
                    │   └── anag
                    │       └── StudentService.java
                    └── controller
                        └── anag
                            └── StudentController.java

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.5.7</version>
        <relativePath/>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo-mysql-jpa</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo-mysql-jpa</name>
    <description>Demo project for Spring Boot</description>
    <properties>
            <maven.compiler.source>17</maven.compiler.source>
                <maven.compiler.target>17</maven.compiler.target>
                <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
                <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
    <build>
    <finalName>app</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

application.yaml

  • remove hibernate: hbm2ddl:
spring:
  application:
    name: demo-mysql-jpa
  datasource:
    url: jdbc:mysql://localhost:3306/firstdb
    username: firstuser
    password: Passw0rd1
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
  anag:
    datasource:
      url: jdbc:mysql://localhost:3306/demodb
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: demouser
      password: Passw0rd!
    jpa:
      hibernate:
        ddl-auto: update
      show-sql: true

DemoApplication.java

package com.example;AnagRepositoriesConfig

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

AnagSourceConfiguration.java

The main changes are all in this file.

package com.example.config;

import com.zaxxer.hikari.HikariDataSource;
import jakarta.persistence.EntityManagerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

//@Configuration
//@ConditionalOnProperty(prefix = "spring.anag.datasource", name = "url")
@Configuration(proxyBeanMethods = false)
@EnableJpaRepositories(
        basePackages = "com.example.repo.anag",
        entityManagerFactoryRef = "anagEntityManagerFactory",
        transactionManagerRef = "anagTransactionManager"
)
public class AnagSourceConfiguration {

/*
    @Value("${spring.anag.hibernate.hbm2ddl.auto:validate}")
    private String hibernateHbm2ddlAuto;

    @Value("${hibernate.dialect}")
    private String hibernateDialect;
*/

/*
    @Bean(name = "anagDataSource")
    @ConfigurationProperties("spring.anag.datasource")
    public DataSource anagDataSource() {return DataSourceBuilder.create().build();
    }
*/

    // 1- DataSourceProperties binding YAML
    @Bean
    @ConfigurationProperties("spring.anag.datasource")
    public DataSourceProperties anagDataSourceProperties() {
        return new DataSourceProperties();
    }

    // 2- create HikariDataSource
    @Bean
    @ConfigurationProperties("anag.datasource.configuration")
    public HikariDataSource anagDataSource(
            @Qualifier("anagDataSourceProperties") DataSourceProperties properties) {
        return properties.initializeDataSourceBuilder()
                .type(HikariDataSource.class)
                .build();
    }

/*
    @Bean(name = "anagEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean anagEntityManagerFactory() {
       LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
       em.setDataSource(anagDataSource());
       em.setPackagesToScan("com.example.entity.anag");
       HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
       em.setJpaVendoimport com.zaxxer.hikari.HikariDataSource;
       final HashMap<String, Object> properties = new HashMap<>();
       properties.put("hibernate.hbm2ddl.auto", hibernateHbm2ddlAuto);
       properties.put("hibernate.dialect", hibernateDialect);
       em.setJpaPropertyMap(properties);
       return em;
    }
*/
    // 3- EntityManagerFactory binding DataSource + JPA properties
    @Bean(name = "anagEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean anagEntityManagerFactory(
            EntityManagerFactoryBuilder builder,
            @Qualifier("anagDataSource") DataSource anagDataSource) {
        return builder
                .dataSource(anagDataSource)
                .packages("com.example.entity.anag") // entity package
                .persistenceUnit("anag")
                .build();
    }

/*
    @Bean(name = "anagTransactionManager")
    public PlatformTransactionManager jpaTransactionManager(EntityManagerFactory anagEntityManagerFactory) {
       return new JpaTransactionManager(anagEntityManagerFactory);
    }
*/

    // 4- TransactionManager
    @Bean(name = "anagTransactionManager")
    public PlatformTransactionManager anagTransactionManager(
            @Qualifier("anagEntityManagerFactory") EntityManagerFactory emf) {
        return new JpaTransactionManager(emf);
    }
}

The AnagRepositoriesConfig.java file is not required.

Student.java

package com.example.entity.anag;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDate;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = "student")
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(length = 100, nullable = false)
    private String name;

    @Column(name = "birth_date")
    private LocalDate birthDate;

    @Column(length = 100)
    private String email;

    @Column(length = 2)
    private String grade;

    @Column(name = "enrollment_date")
    private LocalDate enrollmentDate;
}

StudentRepository.java

package com.example.repo.anag;

import com.example.entity.anag.Student;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface StudentRepository extends JpaRepository<Student, Integer> {
    List<Student> findByName(String name);
}

StudentService.java

package com.example.service.anag;

import com.example.entity.anag.Student;
import com.example.repo.anag.StudentRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

@Service
@RequiredArgsConstructor
@Transactional(transactionManager = "anagTransactionManager")
public class StudentService {

    private final StudentRepository repo;

    public List<Student> listAll() {
        return repo.findAll();
    }

    public Optional<Student> findById(Integer id) {
        return repo.findById(id);
    }

    public List<Student> findByName(String name) {
        return repo.findByName(name);
    }

    public Student create(Student student) {
        return repo.save(student);
    }

    public Student update(Integer id, Student student) {
        return repo.findById(id)
                .map(s -> {
                    s.setName(student.getName());
                    s.setBirthDate(student.getBirthDate());
                    s.setEmail(student.getEmail());
                    s.setGrade(student.getGrade());
                    s.setEnrollmentDate(student.getEnrollmentDate());
                    return repo.save(s);
                })
                .orElseThrow(() -> new RuntimeException("Student ID not found: " + id));
    }

    public void delete(Integer id) {
        repo.deleteById(id);
    }
}

StudentController.java

package com.example.controller.anag;

import com.example.entity.anag.Student;
import com.example.service.anag.StudentService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/anag/students")
public class StudentController {

    private final StudentService service;

    @GetMapping
    public List<Student> listAll() {
        return service.listAll();
    }

    @GetMapping("/{id}")
    public Student findById(@PathVariable Integer id) {
        return service.findById(id).orElse(null);
    }

    @GetMapping("/name/{name}")
    public List<Student> findByName(@PathVariable String name) {
        return service.findByName(name);
    }

    // CREATE
    @PostMapping
    public Student create(@RequestBody Student student) {
        return service.create(student);
    }

    // UPDATE
    @PutMapping("/{id}")
    public Student update(@PathVariable Integer id, @RequestBody Student student) {
        return service.update(id, student);
    }

    // DELETE
    @DeleteMapping("/{id}")
    public void delete(@PathVariable Integer id) {
        service.delete(id);
    }
}

Build

mvn clean package

Run

java -jar target/app.jar

Test

Create

curl -X POST http://localhost:8080/api/anag/students \
-H "Content-Type: application/json" \
-d '{
  "name": "Alice",
  "birthDate": "2005-05-20",
  "email": "[email protected]",
  "grade": "A",
  "enrollmentDate": "2023-09-01"
}'

List All

curl http://localhost:8080/api/anag/students

Update

curl -X PUT http://localhost:8080/api/anag/students/1 \
-H "Content-Type: application/json" \
-d '{
  "name": "AliceUpdated",
  "birthDate": "2005-05-20",
  "email": "[email protected]",
  "grade": "A",
  "enrollmentDate": "2023-09-01"
}'

Read Id: 1

curl http://localhost:8080/api/anag/students/1

Read Name is AliceUpdated

curl http://localhost:8080/api/anag/students/name/AliceUpdated

Delete Id: 1

curl -X DELETE http://localhost:8080/api/anag/students/1