docker-compose up
# If using Docker Compose Engine V2:
docker compose up
Maven:
mvn clean
mvn install
mvn spring-boot:run
Gradle:
./gradlew clean
./gradlew build
./gradlew run
SSL:
keytool -genkey \
-alias bootexample \
-keystore bootexample.p12 \
-storetype PKCS12 \
-keyalg RSA \
-storepass af3DF*34afefwefehu \
-validity 730 \
-keysize 4096
Some default credentials are supplied (to simplify spinning up the example). These are "dummy" credentials (although valid) and aren't or shouldn't be used in any live or PRODUCTION deployment. (In a real-world enterprise app, such credentials would be stored in a service like AWS KMS and be made available or injected during the build.)
- springboot/src/main/resources/application.yml
- springboot/src/main/java/io/thoughtscript/bootexample/config/SecurityConfiguration.java
user
andpassword
are the default Spring Security credentials. Use them to log in and call the API as needed.
- postgresql/init_sql.sql
- Uses Hikari Connection Pooling and postgres Max Connections
- Uses
@EnableCaching
through Spring Cache - Uses Virtual Threads through application.yml
- Uses Hibernate
@Cacheable
within the Entity Framework domain - Uses
@Transactional(readOnly = true)
on Services
Endpoint testing is supplied through bash
:
bash test_curl.sh
https://localhost:8080/api/example/all
[
{
"id": 1,
"name": "aa",
"oneToOneRelation": {
"id": 1,
"name": "a"
},
"oneToManyRelations": [
{
"id": 1,
"name": "aaa",
"examplefk": 1
},
{
"id": 2,
"name": "bbb",
"examplefk": 1
}
],
"manyonerelationfk": 1,
"manyToManyRelations": [
{
"id": 1,
"name": "aaaaa"
},
{
"id": 2,
"name": "bbbbb"
}
]
},
{
"id": 2,
"name": "bb",
"oneToOneRelation": {
"id": 2,
"name": "b"
},
"oneToManyRelations": [
{
"id": 3,
"name": "ccc",
"examplefk": 2
},
{
"id": 4,
"name": "ddd",
"examplefk": 2
}
],
"manyonerelationfk": 2,
"manyToManyRelations": []
},
{
"id": 3,
"name": "cc",
"oneToOneRelation": {
"id": 3,
"name": "c"
},
"oneToManyRelations": [
{
"id": 5,
"name": "aaa",
"examplefk": 3
},
{
"id": 6,
"name": "bbb",
"examplefk": 3
}
],
"manyonerelationfk": 3,
"manyToManyRelations": []
},
{
"id": 4,
"name": "dd",
"oneToOneRelation": {
"id": 4,
"name": "d"
},
"oneToManyRelations": [
{
"id": 7,
"name": "ccc",
"examplefk": 4
},
{
"id": 8,
"name": "ddd",
"examplefk": 4
}
],
"manyonerelationfk": 4,
"manyToManyRelations": []
},
{
"id": 52,
"name": "aa",
"oneToOneRelation": {
"id": 52,
"name": "a"
},
"oneToManyRelations": [
{
"id": 52,
"name": "aaa",
"examplefk": 52
},
{
"id": 53,
"name": "bbb",
"examplefk": 52
}
],
"manyonerelationfk": 52,
"manyToManyRelations": [
{
"id": 52,
"name": "aaaaa"
},
{
"id": 53,
"name": "bbbbb"
}
]
},
{
"id": 53,
"name": "bb",
"oneToOneRelation": {
"id": 53,
"name": "b"
},
"oneToManyRelations": [
{
"id": 54,
"name": "ccc",
"examplefk": 53
},
{
"id": 55,
"name": "ddd",
"examplefk": 53
}
],
"manyonerelationfk": 53,
"manyToManyRelations": []
},
{
"id": 54,
"name": "cc",
"oneToOneRelation": {
"id": 54,
"name": "c"
},
"oneToManyRelations": [
{
"id": 56,
"name": "aaa",
"examplefk": 54
},
{
"id": 57,
"name": "bbb",
"examplefk": 54
}
],
"manyonerelationfk": 54,
"manyToManyRelations": []
},
{
"id": 55,
"name": "dd",
"oneToOneRelation": {
"id": 55,
"name": "d"
},
"oneToManyRelations": [
{
"id": 58,
"name": "ccc",
"examplefk": 55
},
{
"id": 59,
"name": "ddd",
"examplefk": 55
}
],
"manyonerelationfk": 55,
"manyToManyRelations": []
}
]
https://localhost:8080/api/relations/many/many/all
Suppressed List<Example>
field.
[
{
"id": 1,
"name": "aaaaa"
},
{
"id": 2,
"name": "bbbbb"
},
{
"id": 3,
"name": "ccccc"
},
{
"id": 4,
"name": "ddddd"
},
{
"id": 52,
"name": "aaaaa"
},
{
"id": 53,
"name": "bbbbb"
},
{
"id": 54,
"name": "ccccc"
},
{
"id": 55,
"name": "ddddd"
}
]
https://localhost:8080/api/relations/one/many/all
[
{
"id": 1,
"name": "aaa",
"examplefk": 1
},
{
"id": 2,
"name": "bbb",
"examplefk": 1
},
{
"id": 3,
"name": "ccc",
"examplefk": 2
},
{
"id": 4,
"name": "ddd",
"examplefk": 2
},
{
"id": 5,
"name": "aaa",
"examplefk": 3
},
{
"id": 6,
"name": "bbb",
"examplefk": 3
},
{
"id": 7,
"name": "ccc",
"examplefk": 4
},
{
"id": 8,
"name": "ddd",
"examplefk": 4
},
{
"id": 52,
"name": "aaa",
"examplefk": 52
},
{
"id": 53,
"name": "bbb",
"examplefk": 52
},
{
"id": 54,
"name": "ccc",
"examplefk": 53
},
{
"id": 55,
"name": "ddd",
"examplefk": 53
},
{
"id": 56,
"name": "aaa",
"examplefk": 54
},
{
"id": 57,
"name": "bbb",
"examplefk": 54
},
{
"id": 58,
"name": "ccc",
"examplefk": 55
},
{
"id": 59,
"name": "ddd",
"examplefk": 55
}
]
https://localhost:8080/api/relations/one/one/all
[
{
"id": 1,
"name": "a"
},
{
"id": 2,
"name": "b"
},
{
"id": 3,
"name": "c"
},
{
"id": 4,
"name": "d"
},
{
"id": 52,
"name": "a"
},
{
"id": 53,
"name": "b"
},
{
"id": 54,
"name": "c"
},
{
"id": 55,
"name": "d"
}
]
https://localhost:8080/api/relations/many/one/all
[
{
"id": 1,
"name": "aaaa",
"example": {
"id": 1,
"name": "aa",
"oneToOneRelation": {
"id": 1,
"name": "a"
},
"oneToManyRelations": [
{
"id": 1,
"name": "aaa",
"examplefk": 1
},
{
"id": 2,
"name": "bbb",
"examplefk": 1
}
],
"manyonerelationfk": 1,
"manyToManyRelations": [
{
"id": 1,
"name": "aaaaa"
},
{
"id": 2,
"name": "bbbbb"
}
]
}
},
{
"id": 2,
"name": "bbbb",
"example": {
"id": 2,
"name": "bb",
"oneToOneRelation": {
"id": 2,
"name": "b"
},
"oneToManyRelations": [
{
"id": 3,
"name": "ccc",
"examplefk": 2
},
{
"id": 4,
"name": "ddd",
"examplefk": 2
}
],
"manyonerelationfk": 2,
"manyToManyRelations": []
}
},
{
"id": 3,
"name": "cccc",
"example": {
"id": 3,
"name": "cc",
"oneToOneRelation": {
"id": 3,
"name": "c"
},
"oneToManyRelations": [
{
"id": 5,
"name": "aaa",
"examplefk": 3
},
{
"id": 6,
"name": "bbb",
"examplefk": 3
}
],
"manyonerelationfk": 3,
"manyToManyRelations": []
}
},
{
"id": 4,
"name": "dddd",
"example": {
"id": 4,
"name": "dd",
"oneToOneRelation": {
"id": 4,
"name": "d"
},
"oneToManyRelations": [
{
"id": 7,
"name": "ccc",
"examplefk": 4
},
{
"id": 8,
"name": "ddd",
"examplefk": 4
}
],
"manyonerelationfk": 4,
"manyToManyRelations": []
}
},
{
"id": 52,
"name": "aaaa",
"example": {
"id": 52,
"name": "aa",
"oneToOneRelation": {
"id": 52,
"name": "a"
},
"oneToManyRelations": [
{
"id": 52,
"name": "aaa",
"examplefk": 52
},
{
"id": 53,
"name": "bbb",
"examplefk": 52
}
],
"manyonerelationfk": 52,
"manyToManyRelations": [
{
"id": 52,
"name": "aaaaa"
},
{
"id": 53,
"name": "bbbbb"
}
]
}
},
{
"id": 53,
"name": "bbbb",
"example": {
"id": 53,
"name": "bb",
"oneToOneRelation": {
"id": 53,
"name": "b"
},
"oneToManyRelations": [
{
"id": 54,
"name": "ccc",
"examplefk": 53
},
{
"id": 55,
"name": "ddd",
"examplefk": 53
}
],
"manyonerelationfk": 53,
"manyToManyRelations": []
}
},
{
"id": 54,
"name": "cccc",
"example": {
"id": 54,
"name": "cc",
"oneToOneRelation": {
"id": 54,
"name": "c"
},
"oneToManyRelations": [
{
"id": 56,
"name": "aaa",
"examplefk": 54
},
{
"id": 57,
"name": "bbb",
"examplefk": 54
}
],
"manyonerelationfk": 54,
"manyToManyRelations": []
}
},
{
"id": 55,
"name": "dddd",
"example": {
"id": 55,
"name": "dd",
"oneToOneRelation": {
"id": 55,
"name": "d"
},
"oneToManyRelations": [
{
"id": 58,
"name": "ccc",
"examplefk": 55
},
{
"id": 59,
"name": "ddd",
"examplefk": 55
}
],
"manyonerelationfk": 55,
"manyToManyRelations": []
}
}
]
- https://www.codejava.net/frameworks/spring-boot/connect-to-postgresql-database-examples
- https://www.baeldung.com/spring-boot-security-autoconfiguration
- https://www.baeldung.com/spring-postconstruct-predestroy
- https://dev.to/jhonifaber/hibernate-onetoone-onetomany-manytoone-and-manytomany-8ba
- https://stackoverflow.com/questions/56424524/getting-infinite-json-response-when-using-many-to-one-mapping-in-spring
- https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion
- https://www.baeldung.com/hibernate-one-to-many
- https://www.baeldung.com/spring-boot-hikari
- https://docs.spring.io/spring-boot/reference/io/caching.html#io.caching.provider.simple
- https://medium.com/@avi.singh.iit01/optimizing-performance-with-spring-data-jpa-85583362cf3a
- https://thorben-janssen.com/hibernate-performance-tuning/
- https://www.danvega.dev/blog/jdk-24-virtual-threads-without-pinning