Import spring petclinic backend
This commit is contained in:
commit
c6920bb4f7
139 changed files with 11950 additions and 0 deletions
1
.envrc
Normal file
1
.envrc
Normal file
|
@ -0,0 +1 @@
|
|||
use flake path:flake;
|
9
.gitattributes
vendored
Normal file
9
.gitattributes
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
# https://help.github.com/articles/dealing-with-line-endings/
|
||||
#
|
||||
# Linux start script should use lf
|
||||
/gradlew text eol=lf
|
||||
|
||||
# These are Windows script files and should use crlf
|
||||
*.bat text eol=crlf
|
||||
|
190
.gitignore
vendored
Normal file
190
.gitignore
vendored
Normal file
|
@ -0,0 +1,190 @@
|
|||
.direnv/
|
||||
.idea/
|
||||
.vscode/
|
||||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/intellij,linux,node,gradle
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=intellij,linux,node,gradle
|
||||
|
||||
### Linux ###
|
||||
*~
|
||||
|
||||
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||
.fuse_hidden*
|
||||
|
||||
# KDE directory preferences
|
||||
.directory
|
||||
|
||||
# Linux trash folder which might appear on any partition or disk
|
||||
.Trash-*
|
||||
|
||||
# .nfs files are created when an open file is removed but is still being accessed
|
||||
.nfs*
|
||||
|
||||
### Node ###
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
### Node Patch ###
|
||||
# Serverless Webpack directories
|
||||
.webpack/
|
||||
|
||||
# Optional stylelint cache
|
||||
|
||||
# SvelteKit build / generate output
|
||||
.svelte-kit
|
||||
|
||||
### Gradle ###
|
||||
.gradle
|
||||
**/build/
|
||||
!src/**/build/
|
||||
|
||||
# Ignore Gradle GUI config
|
||||
gradle-app.setting
|
||||
|
||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||
!gradle-wrapper.jar
|
||||
|
||||
# Avoid ignore Gradle wrappper properties
|
||||
!gradle-wrapper.properties
|
||||
|
||||
# Cache of project
|
||||
.gradletasknamecache
|
||||
|
||||
# Eclipse Gradle plugin generated files
|
||||
# Eclipse Core
|
||||
.project
|
||||
# JDT-specific (Eclipse Java Development Tools)
|
||||
.classpath
|
||||
|
||||
### Gradle Patch ###
|
||||
# Java heap dump
|
||||
*.hprof
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/intellij,linux,node,gradle
|
12
backend/.editorconfig
Normal file
12
backend/.editorconfig
Normal file
|
@ -0,0 +1,12 @@
|
|||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
|
||||
[*.{java,xml}]
|
||||
indent_size = 4
|
||||
trim_trailing_whitespace = true
|
13
backend/.gitignore
vendored
Normal file
13
backend/.gitignore
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
target/*
|
||||
.settings/*
|
||||
.classpath
|
||||
.project
|
||||
.idea
|
||||
*.iml
|
||||
/target
|
||||
|
||||
generated/
|
||||
|
||||
# Easier branch switching
|
||||
springboot-petclinic-client/
|
||||
springboot-petclinic-server/
|
201
backend/LICENSE.txt
Normal file
201
backend/LICENSE.txt
Normal file
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
120
backend/build.gradle.kts
Normal file
120
backend/build.gradle.kts
Normal file
|
@ -0,0 +1,120 @@
|
|||
plugins {
|
||||
java
|
||||
id("org.springframework.boot") version "3.3.6"
|
||||
id("io.spring.dependency-management") version "1.1.6"
|
||||
id("org.openapi.generator") version "7.10.0"
|
||||
idea
|
||||
jacoco
|
||||
}
|
||||
|
||||
group = "org.springframework.samples"
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(21)
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("org.springframework.boot:spring-boot-starter-actuator")
|
||||
implementation("org.springframework.boot:spring-boot-starter-cache")
|
||||
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
|
||||
implementation("org.springframework.boot:spring-boot-starter-jdbc")
|
||||
implementation("org.springframework.boot:spring-boot-starter-security")
|
||||
implementation("org.springframework.boot:spring-boot-starter-validation")
|
||||
implementation("org.springframework.boot:spring-boot-starter-web")
|
||||
implementation("org.springframework.data:spring-data-jdbc-core:1.2.1.RELEASE")
|
||||
implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0")
|
||||
implementation("org.mapstruct:mapstruct:${project.property("mapstructVersion")}")
|
||||
// implementation("org.openapitools:jackson-databind-nullable:0.2.6")
|
||||
annotationProcessor("org.mapstruct:mapstruct-processor:${project.property("mapstructVersion")}")
|
||||
runtimeOnly("org.hsqldb:hsqldb")
|
||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||
testImplementation("org.springframework.security:spring-security-test")
|
||||
testImplementation("com.jayway.jsonpath:json-path")
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||
}
|
||||
|
||||
openApiGenerate {
|
||||
inputSpec.set("${projectDir}/src/main/resources/openapi.yml")
|
||||
generatorName.set("spring")
|
||||
library.set("spring-boot")
|
||||
modelNameSuffix.set("Dto")
|
||||
apiPackage.set("org.springframework.samples.petclinic.rest.api")
|
||||
modelPackage.set("org.springframework.samples.petclinic.rest.dto")
|
||||
supportingFilesConstrainedTo.set(listOf("ApiUtil.java"))
|
||||
globalProperties.set(
|
||||
mapOf(
|
||||
"apis" to "",
|
||||
"models" to ""
|
||||
)
|
||||
)
|
||||
configOptions.set(
|
||||
mutableMapOf(
|
||||
"verbose" to "true",
|
||||
"interfaceOnly" to "true",
|
||||
"performBeanValidation" to "true",
|
||||
"dateLibrary" to "java8",
|
||||
"useSpringBoot3" to "true",
|
||||
"openApiNullable" to "false",
|
||||
"serializationLibrary" to "jackson",
|
||||
"documentationProvider" to "springdoc",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
tasks.jacocoTestReport {
|
||||
dependsOn(tasks.test) // tests are required to run before generating the report
|
||||
classDirectories.setFrom(
|
||||
files(classDirectories.files.map {
|
||||
fileTree(it) {
|
||||
exclude(
|
||||
"**/org/springframework/samples/petclinic/rest/dto/**",
|
||||
"**/org/springframework/samples/petclinic/rest/api/**"
|
||||
)
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
tasks.jacocoTestCoverageVerification {
|
||||
violationRules {
|
||||
rule {
|
||||
element = "BUNDLE"
|
||||
limit {
|
||||
counter = "LINE"
|
||||
value = "COVEREDRATIO"
|
||||
minimum = "0.85".toBigDecimal()
|
||||
}
|
||||
limit {
|
||||
counter = "BRANCH"
|
||||
value = "COVEREDRATIO"
|
||||
minimum = "0.66".toBigDecimal()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<Test> {
|
||||
useJUnitPlatform()
|
||||
finalizedBy(tasks.jacocoTestReport) // report is always generated after tests run
|
||||
configure<JacocoTaskExtension> {
|
||||
}
|
||||
}
|
||||
|
||||
java.sourceSets["main"].java {
|
||||
srcDir(layout.buildDirectory.dir("generate-resources/main/src/main/java"))
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile> {
|
||||
dependsOn(tasks.openApiGenerate)
|
||||
options.compilerArgs = listOf(
|
||||
"-Amapstruct.suppressGeneratorTimestamp=true",
|
||||
"-Amapstruct.suppressGeneratorVersionInfoComment=true",
|
||||
"-Amapstruct.defaultComponentModel=spring"
|
||||
)
|
||||
}
|
26
backend/docker-compose.yml
Normal file
26
backend/docker-compose.yml
Normal file
|
@ -0,0 +1,26 @@
|
|||
services:
|
||||
mysql:
|
||||
image: mysql:8.4
|
||||
command: --mysql-native-password=ON
|
||||
ports:
|
||||
- "3306:3306"
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=
|
||||
- MYSQL_ALLOW_EMPTY_PASSWORD=true
|
||||
- MYSQL_USER=petclinic
|
||||
- MYSQL_PASSWORD=petclinic
|
||||
- MYSQL_DATABASE=petclinic
|
||||
volumes:
|
||||
- "./conf.d:/etc/mysql/conf.d:ro"
|
||||
profiles:
|
||||
- mysql
|
||||
postgres:
|
||||
image: postgres:16.3
|
||||
ports:
|
||||
- "5432:5432"
|
||||
environment:
|
||||
- POSTGRES_PASSWORD=petclinic
|
||||
- POSTGRES_USER=petclinic
|
||||
- POSTGRES_DB=petclinic
|
||||
profiles:
|
||||
- postgres
|
BIN
backend/petclinic-ermodel.png
Normal file
BIN
backend/petclinic-ermodel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 70 KiB |
223
backend/readme.md
Normal file
223
backend/readme.md
Normal file
|
@ -0,0 +1,223 @@
|
|||
# REST version of Spring PetClinic Sample Application (spring-framework-petclinic extend )
|
||||
|
||||
[![Java Build Status](https://github.com/spring-petclinic/spring-petclinic-rest/actions/workflows/maven-build.yml/badge.svg)](https://github.com/spring-petclinic/spring-petclinic-rest/actions/workflows/maven-build.yml)
|
||||
[![Docker Build Status](https://github.com/spring-petclinic/spring-petclinic-rest/actions/workflows/docker-build.yml/badge.svg)](https://github.com/spring-petclinic/spring-petclinic-rest/actions/workflows/docker-build.yml)
|
||||
|
||||
This backend version of the Spring Petclinic application only provides a REST API. **There is no UI**.
|
||||
The [spring-petclinic-angular project](https://github.com/spring-petclinic/spring-petclinic-angular) is a Angular front-end application which consumes the REST API.
|
||||
|
||||
## Understanding the Spring Petclinic application with a few diagrams
|
||||
|
||||
[See the presentation of the Spring Petclinic Framework version](http://fr.slideshare.net/AntoineRey/spring-framework-petclinic-sample-application)
|
||||
|
||||
### Petclinic ER Model
|
||||
|
||||
![alt petclinic-ermodel](petclinic-ermodel.png)
|
||||
|
||||
## Running Petclinic locally
|
||||
|
||||
### With Maven command line
|
||||
```sh
|
||||
git clone https://github.com/spring-petclinic/spring-petclinic-rest.git
|
||||
cd spring-petclinic-rest
|
||||
./mvnw spring-boot:run
|
||||
```
|
||||
|
||||
### With Docker
|
||||
```sh
|
||||
docker run -p 9966:9966 springcommunity/spring-petclinic-rest
|
||||
```
|
||||
|
||||
You can then access petclinic here: [http://localhost:9966/petclinic/](http://localhost:9966/petclinic/)
|
||||
|
||||
There is an actuator health check route as well:
|
||||
* [http://localhost:9966/petclinic/actuator/health](http://localhost:9966/petclinic/actuator/health)
|
||||
|
||||
## OpenAPI REST API documentation
|
||||
|
||||
You can reach the Swagger UI with this URL (after application start):
|
||||
[http://localhost:9966/petclinic/](http://localhost:9966/petclinic/swagger-ui.html).
|
||||
|
||||
You then can get the Open API description reaching this URL: [localhost:9966/petclinic/v3/api-docs](localhost:9966/petclinic/v3/api-docs).
|
||||
|
||||
## Screenshot of the Angular client
|
||||
|
||||
See its repository here: https://github.com/spring-petclinic/spring-petclinic-angular
|
||||
|
||||
<img width="1427" alt="spring-petclinic-angular2" src="https://cloud.githubusercontent.com/assets/838318/23263243/f4509c4a-f9dd-11e6-951b-69d0ef72d8bd.png">
|
||||
|
||||
## In case you find a bug/suggested improvement for Spring Petclinic
|
||||
Our issue tracker is available here: https://github.com/spring-petclinic/spring-petclinic-rest/issues
|
||||
|
||||
|
||||
## Database configuration
|
||||
|
||||
In its default configuration, Petclinic uses an in-memory database (HSQLDB) which gets populated at startup with data.
|
||||
|
||||
A similar setup is provided for MySQL and PostgreSQL if a persistent database configuration is needed.
|
||||
|
||||
Note that whenever the database type changes, the app needs to run with a different profile: `spring.profiles.active=mysql` for MySQL or `spring.profiles.active=postgres` for PostgreSQL.
|
||||
See the [Spring Boot documentation](https://docs.spring.io/spring-boot/how-to/properties-and-configuration.html#howto.properties-and-configuration.set-active-spring-profiles) for more detail on how to set the active profile.
|
||||
You can also change profile defined in the `application.properties` file.
|
||||
For MySQL database, it is needed to change param `hsqldb` to `mysql` in the following line of `application.properies` file:
|
||||
```properties
|
||||
spring.profiles.active=hsqldb,spring-data-jpa
|
||||
```
|
||||
|
||||
You can start MySQL or PostgreSQL locally with whatever installer works for your OS or use docker:
|
||||
|
||||
```bash
|
||||
docker run -e MYSQL_USER=petclinic -e MYSQL_PASSWORD=petclinic -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=petclinic -p 3306:3306 mysql:8.4
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```bash
|
||||
docker run -e POSTGRES_USER=petclinic -e POSTGRES_PASSWORD=petclinic -e POSTGRES_DB=petclinic -p 5432:5432 postgres:16.3
|
||||
```
|
||||
|
||||
Further documentation is provided for [MySQL](https://github.com/spring-projects/spring-petclinic/blob/main/src/main/resources/db/mysql/petclinic_db_setup_mysql.txt)
|
||||
and [PostgreSQL](https://github.com/spring-projects/spring-petclinic/blob/main/src/main/resources/db/postgres/petclinic_db_setup_postgres.txt).
|
||||
|
||||
Instead of vanilla `docker` you can also use the provided `docker-compose.yml` file to start the database containers. Each one has a profile just like the Spring profile:
|
||||
|
||||
```bash
|
||||
docker-compose --profile mysql up
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```bash
|
||||
docker-compose --profile postgres up
|
||||
```
|
||||
|
||||
|
||||
## API First Approach
|
||||
|
||||
This API is built following some [API First approach principles](https://swagger.io/resources/articles/adopting-an-api-first-approach/).
|
||||
|
||||
It is specified through the [OpenAPI](https://oai.github.io/Documentation/).
|
||||
It is specified in this [file](./src/main/resources/openapi.yml).
|
||||
|
||||
Some of the required classes are generated during the build time.
|
||||
Here are the generated file types:
|
||||
* DTOs
|
||||
* API template interfaces specifying methods to override in the controllers
|
||||
|
||||
To see how to get them generated you can read the next chapter.
|
||||
|
||||
## Generated code
|
||||
|
||||
Some of the required classes are generated during the build time using maven or any IDE (e.g., IntelliJ Idea or Eclipse).
|
||||
|
||||
All of these classes are generated into the ``target/generated-sources`` folder.
|
||||
|
||||
Here is a list of the generated packages and the corresponding tooling:
|
||||
|
||||
| Package name | Tool |
|
||||
|------------------------------------------------|------------------|
|
||||
| org.springframework.samples.petclinic.mapper | [MapStruct](https://mapstruct.org/) |
|
||||
| org.springframework.samples.petclinic.rest.dto | [OpenAPI Generator maven plugin](https://github.com/OpenAPITools/openapi-generator/) |
|
||||
|
||||
|
||||
To get both, you have to run the following command:
|
||||
|
||||
```jshelllanguage
|
||||
mvn clean install
|
||||
```
|
||||
|
||||
## Security configuration
|
||||
In its default configuration, Petclinic doesn't have authentication and authorization enabled.
|
||||
|
||||
### Basic Authentication
|
||||
In order to use the basic authentication functionality, turn in on from the `application.properties` file
|
||||
```properties
|
||||
petclinic.security.enable=true
|
||||
```
|
||||
This will secure all APIs and in order to access them, basic authentication is required.
|
||||
Apart from authentication, APIs also require authorization. This is done via roles that a user can have.
|
||||
The existing roles are listed below with the corresponding permissions
|
||||
|
||||
* `OWNER_ADMIN` -> `OwnerController`, `PetController`, `PetTypeController` (`getAllPetTypes` and `getPetType`), `VisitController`
|
||||
* `VET_ADMIN` -> `PetTypeController`, `SpecialityController`, `VetController`
|
||||
* `ADMIN` -> `UserController`
|
||||
|
||||
There is an existing user with the username `admin` and password `admin` that has access to all APIs.
|
||||
In order to add a new user, please make `POST /api/users` request with the following payload:
|
||||
|
||||
```json
|
||||
{
|
||||
"username": "secondAdmin",
|
||||
"password": "password",
|
||||
"enabled": true,
|
||||
"roles": [
|
||||
{ "name" : "OWNER_ADMIN" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Working with Petclinic in Eclipse/STS
|
||||
|
||||
### prerequisites
|
||||
The following items should be installed in your system:
|
||||
* Maven 3 (https://maven.apache.org/install.html)
|
||||
* git command line tool (https://help.github.com/articles/set-up-git)
|
||||
* Eclipse with the m2e plugin (m2e is installed by default when using the STS (http://www.springsource.org/sts) distribution of Eclipse)
|
||||
|
||||
Note: when m2e is available, there is an m2 icon in Help -> About dialog.
|
||||
If m2e is not there, just follow the install process here: http://eclipse.org/m2e/download/
|
||||
* Eclipse with the [mapstruct plugin](https://mapstruct.org/documentation/ide-support/) installed.
|
||||
|
||||
### Steps:
|
||||
|
||||
1) In the command line
|
||||
```sh
|
||||
git clone https://github.com/spring-petclinic/spring-petclinic-rest.git
|
||||
```
|
||||
2) Inside Eclipse
|
||||
```
|
||||
File -> Import -> Maven -> Existing Maven project
|
||||
```
|
||||
|
||||
|
||||
## Looking for something in particular?
|
||||
|
||||
| Layer | Source |
|
||||
|--|--|
|
||||
| REST API controllers | [REST folder](src/main/java/org/springframework/samples/petclinic/rest) |
|
||||
| Service | [ClinicServiceImpl.java](src/main/java/org/springframework/samples/petclinic/service/ClinicServiceImpl.java) |
|
||||
| JDBC | [jdbc folder](src/main/java/org/springframework/samples/petclinic/repository/jdbc) |
|
||||
| JPA | [jpa folder](src/main/java/org/springframework/samples/petclinic/repository/jpa) |
|
||||
| Spring Data JPA | [springdatajpa folder](src/main/java/org/springframework/samples/petclinic/repository/springdatajpa) |
|
||||
| Tests | [AbstractClinicServiceTests.java](src/test/java/org/springframework/samples/petclinic/service/clinicService/AbstractClinicServiceTests.java) |
|
||||
|
||||
|
||||
## Publishing a Docker image
|
||||
|
||||
This application uses [Google Jib]([https://github.com/GoogleContainerTools/jib) to build an optimized Docker image into the [Docker Hub](https://cloud.docker.com/u/springcommunity/repository/docker/springcommunity/spring-petclinic-rest/) repository.
|
||||
The [pom.xml](pom.xml) has been configured to publish the image with a the `springcommunity/spring-petclinic-rest`image name.
|
||||
|
||||
Command line to run:
|
||||
```sh
|
||||
mvn compile jib:build -X -DjibSerialize=true -Djib.to.auth.username=xxx -Djib.to.auth.password=xxxxx
|
||||
```
|
||||
|
||||
## Interesting Spring Petclinic forks
|
||||
|
||||
The Spring Petclinic master branch in the main [spring-projects](https://github.com/spring-projects/spring-petclinic)
|
||||
GitHub org is the "canonical" implementation, currently based on Spring Boot and Thymeleaf.
|
||||
|
||||
This [spring-petclinic-rest](https://github.com/spring-petclinic/spring-petclinic-rest/) project is one of the [several forks](https://spring-petclinic.github.io/docs/forks.html)
|
||||
hosted in a special GitHub org: [spring-petclinic](https://github.com/spring-petclinic).
|
||||
If you have a special interest in a different technology stack
|
||||
that could be used to implement the Pet Clinic then please join the community there.
|
||||
|
||||
|
||||
# Contributing
|
||||
|
||||
The [issue tracker](https://github.com/spring-petclinic/spring-petclinic-rest/issues) is the preferred channel for bug reports, features requests and submitting pull requests.
|
||||
|
||||
For pull requests, editor preferences are available in the [editor config](https://github.com/spring-petclinic/spring-petclinic-rest/blob/master/.editorconfig) for easy use in common text editors. Read more and download plugins at <http://editorconfig.org>.
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package org.springframework.samples.petclinic;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
|
||||
|
||||
@SpringBootApplication
|
||||
public class PetClinicApplication extends SpringBootServletInitializer {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(PetClinicApplication.class, args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.config;
|
||||
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import io.swagger.v3.oas.models.Components;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.info.Contact;
|
||||
import io.swagger.v3.oas.models.info.Info;
|
||||
import io.swagger.v3.oas.models.info.License;
|
||||
|
||||
/**
|
||||
* Java config for Springfox swagger documentation plugin
|
||||
*
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
@Configuration
|
||||
public class SwaggerConfig {
|
||||
|
||||
@Bean
|
||||
OpenAPI customOpenAPI() {
|
||||
|
||||
return new OpenAPI().components(new Components()).info(new Info()
|
||||
.title("REST Petclinic backend Api Documentation").version("1.0")
|
||||
.termsOfService("Petclinic backend terms of service")
|
||||
.description(
|
||||
"This is REST API documentation of the Spring Petclinic backend. If authentication is enabled, when calling the APIs use admin/admin")
|
||||
.license(swaggerLicense()).contact(swaggerContact()));
|
||||
}
|
||||
|
||||
private Contact swaggerContact() {
|
||||
Contact petclinicContact = new Contact();
|
||||
petclinicContact.setName("Vitaliy Fedoriv");
|
||||
petclinicContact.setEmail("vitaliy.fedoriv@gmail.com");
|
||||
petclinicContact.setUrl("https://github.com/spring-petclinic/spring-petclinic-rest");
|
||||
return petclinicContact;
|
||||
}
|
||||
|
||||
private License swaggerLicense() {
|
||||
License petClinicLicense = new License();
|
||||
petClinicLicense.setName("Apache 2.0");
|
||||
petClinicLicense.setUrl("http://www.apache.org/licenses/LICENSE-2.0");
|
||||
petClinicLicense.setExtensions(Collections.emptyMap());
|
||||
return petClinicLicense;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package org.springframework.samples.petclinic.mapper;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.springframework.samples.petclinic.model.Owner;
|
||||
import org.springframework.samples.petclinic.rest.dto.OwnerDto;
|
||||
import org.springframework.samples.petclinic.rest.dto.OwnerFieldsDto;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Maps Owner & OwnerDto using Mapstruct
|
||||
*/
|
||||
@Mapper(uses = PetMapper.class)
|
||||
public interface OwnerMapper {
|
||||
|
||||
OwnerDto toOwnerDto(Owner owner);
|
||||
|
||||
Owner toOwner(OwnerDto ownerDto);
|
||||
|
||||
@Mapping(target = "id", ignore = true)
|
||||
@Mapping(target = "pets", ignore = true)
|
||||
Owner toOwner(OwnerFieldsDto ownerDto);
|
||||
|
||||
List<OwnerDto> toOwnerDtoCollection(Collection<Owner> ownerCollection);
|
||||
|
||||
Collection<Owner> toOwners(Collection<OwnerDto> ownerDtos);
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package org.springframework.samples.petclinic.mapper;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.springframework.samples.petclinic.model.Pet;
|
||||
import org.springframework.samples.petclinic.model.PetType;
|
||||
import org.springframework.samples.petclinic.rest.dto.PetDto;
|
||||
import org.springframework.samples.petclinic.rest.dto.PetFieldsDto;
|
||||
import org.springframework.samples.petclinic.rest.dto.PetTypeDto;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Map Pet & PetDto using mapstruct
|
||||
*/
|
||||
@Mapper(uses = VisitMapper.class)
|
||||
public interface PetMapper {
|
||||
|
||||
@Mapping(source = "owner.id", target = "ownerId")
|
||||
PetDto toPetDto(Pet pet);
|
||||
|
||||
Collection<PetDto> toPetsDto(Collection<Pet> pets);
|
||||
|
||||
Collection<Pet> toPets(Collection<PetDto> pets);
|
||||
|
||||
@Mapping(source = "ownerId", target = "owner.id")
|
||||
Pet toPet(PetDto petDto);
|
||||
|
||||
@Mapping(target = "id", ignore = true)
|
||||
@Mapping(target = "owner", ignore = true)
|
||||
@Mapping(target = "visits", ignore = true)
|
||||
Pet toPet(PetFieldsDto petFieldsDto);
|
||||
|
||||
PetTypeDto toPetTypeDto(PetType petType);
|
||||
|
||||
PetType toPetType(PetTypeDto petTypeDto);
|
||||
|
||||
Collection<PetTypeDto> toPetTypeDtos(Collection<PetType> petTypes);
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package org.springframework.samples.petclinic.mapper;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.springframework.samples.petclinic.model.PetType;
|
||||
import org.springframework.samples.petclinic.rest.dto.PetTypeDto;
|
||||
import org.springframework.samples.petclinic.rest.dto.PetTypeFieldsDto;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Map PetType & PetTypeDto using mapstruct
|
||||
*/
|
||||
@Mapper
|
||||
public interface PetTypeMapper {
|
||||
|
||||
PetType toPetType(PetTypeDto petTypeDto);
|
||||
|
||||
@Mapping(target = "id", ignore = true)
|
||||
PetType toPetType(PetTypeFieldsDto petTypeFieldsDto);
|
||||
|
||||
PetTypeDto toPetTypeDto(PetType petType);
|
||||
PetTypeFieldsDto toPetTypeFieldsDto(PetType petType);
|
||||
|
||||
List<PetTypeDto> toPetTypeDtos(Collection<PetType> petTypes);
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package org.springframework.samples.petclinic.mapper;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.springframework.samples.petclinic.rest.dto.SpecialtyDto;
|
||||
import org.springframework.samples.petclinic.model.Specialty;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Map Specialty & SpecialtyDto using mapstruct
|
||||
*/
|
||||
@Mapper
|
||||
public interface SpecialtyMapper {
|
||||
Specialty toSpecialty(SpecialtyDto specialtyDto);
|
||||
|
||||
SpecialtyDto toSpecialtyDto(Specialty specialty);
|
||||
|
||||
Collection<SpecialtyDto> toSpecialtyDtos(Collection<Specialty> specialties);
|
||||
|
||||
Collection<Specialty> toSpecialtys(Collection<SpecialtyDto> specialties);
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package org.springframework.samples.petclinic.mapper;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.springframework.samples.petclinic.model.Role;
|
||||
import org.springframework.samples.petclinic.model.User;
|
||||
import org.springframework.samples.petclinic.rest.dto.RoleDto;
|
||||
import org.springframework.samples.petclinic.rest.dto.UserDto;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Map User/Role & UserDto/RoleDto using mapstruct
|
||||
*/
|
||||
@Mapper
|
||||
public interface UserMapper {
|
||||
|
||||
@Mapping(target = "id", ignore = true)
|
||||
@Mapping(target = "user", ignore = true)
|
||||
Role toRole(RoleDto roleDto);
|
||||
|
||||
RoleDto toRoleDto(Role role);
|
||||
|
||||
Collection<RoleDto> toRoleDtos(Collection<Role> roles);
|
||||
|
||||
User toUser(UserDto userDto);
|
||||
|
||||
UserDto toUserDto(User user);
|
||||
|
||||
Collection<Role> toRoles(Collection<RoleDto> roleDtos);
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package org.springframework.samples.petclinic.mapper;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.springframework.samples.petclinic.model.Vet;
|
||||
import org.springframework.samples.petclinic.rest.dto.VetDto;
|
||||
import org.springframework.samples.petclinic.rest.dto.VetFieldsDto;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Map Vet & VetoDto using mapstruct
|
||||
*/
|
||||
@Mapper(uses = SpecialtyMapper.class)
|
||||
public interface VetMapper {
|
||||
Vet toVet(VetDto vetDto);
|
||||
|
||||
@Mapping(target = "id", ignore = true)
|
||||
Vet toVet(VetFieldsDto vetFieldsDto);
|
||||
|
||||
VetDto toVetDto(Vet vet);
|
||||
|
||||
Collection<VetDto> toVetDtos(Collection<Vet> vets);
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package org.springframework.samples.petclinic.mapper;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.springframework.samples.petclinic.model.Visit;
|
||||
import org.springframework.samples.petclinic.rest.dto.VisitDto;
|
||||
import org.springframework.samples.petclinic.rest.dto.VisitFieldsDto;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Map Visit & VisitDto using mapstruct
|
||||
*/
|
||||
@Mapper(uses = PetMapper.class)
|
||||
public interface VisitMapper {
|
||||
@Mapping(source = "petId", target = "pet.id")
|
||||
Visit toVisit(VisitDto visitDto);
|
||||
|
||||
@Mapping(target = "id", ignore = true)
|
||||
@Mapping(target = "pet", ignore = true)
|
||||
Visit toVisit(VisitFieldsDto visitFieldsDto);
|
||||
|
||||
@Mapping(source = "pet.id", target = "petId")
|
||||
VisitDto toVisitDto(Visit visit);
|
||||
|
||||
Collection<VisitDto> toVisitsDto(Collection<Visit> visits);
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.model;
|
||||
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
/**
|
||||
* Simple JavaBean domain object with an id property. Used as a base class for objects needing this property.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
@MappedSuperclass
|
||||
public class BaseEntity {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
protected Integer id;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
@JsonIgnore
|
||||
public boolean isNew() {
|
||||
return this.id == null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.model;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
|
||||
|
||||
/**
|
||||
* Simple JavaBean domain object adds a name property to <code>BaseEntity</code>. Used as a base class for objects
|
||||
* needing these properties.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
@MappedSuperclass
|
||||
public class NamedEntity extends BaseEntity {
|
||||
|
||||
@Column(name = "name")
|
||||
@NotEmpty
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getName();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.model;
|
||||
|
||||
import org.springframework.beans.support.MutableSortDefinition;
|
||||
import org.springframework.beans.support.PropertyComparator;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.Digits;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* Simple JavaBean domain object representing an owner.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @author Michael Isvy
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "owners")
|
||||
public class Owner extends Person {
|
||||
@Column(name = "address")
|
||||
@NotEmpty
|
||||
private String address;
|
||||
|
||||
@Column(name = "city")
|
||||
@NotEmpty
|
||||
private String city;
|
||||
|
||||
@Column(name = "telephone")
|
||||
@NotEmpty
|
||||
@Digits(fraction = 0, integer = 10)
|
||||
private String telephone;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "owner", fetch = FetchType.EAGER)
|
||||
private Set<Pet> pets;
|
||||
|
||||
|
||||
public String getAddress() {
|
||||
return this.address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getCity() {
|
||||
return this.city;
|
||||
}
|
||||
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
public String getTelephone() {
|
||||
return this.telephone;
|
||||
}
|
||||
|
||||
public void setTelephone(String telephone) {
|
||||
this.telephone = telephone;
|
||||
}
|
||||
|
||||
protected Set<Pet> getPetsInternal() {
|
||||
if (this.pets == null) {
|
||||
this.pets = new HashSet<>();
|
||||
}
|
||||
return this.pets;
|
||||
}
|
||||
|
||||
protected void setPetsInternal(Set<Pet> pets) {
|
||||
this.pets = pets;
|
||||
}
|
||||
|
||||
public List<Pet> getPets() {
|
||||
List<Pet> sortedPets = new ArrayList<>(getPetsInternal());
|
||||
PropertyComparator.sort(sortedPets, new MutableSortDefinition("name", true, true));
|
||||
return Collections.unmodifiableList(sortedPets);
|
||||
}
|
||||
|
||||
public void setPets(List<Pet> pets) {
|
||||
this.pets = new HashSet<>(pets);
|
||||
}
|
||||
|
||||
public void addPet(Pet pet) {
|
||||
getPetsInternal().add(pet);
|
||||
pet.setOwner(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Pet with the given name, or null if none found for this Owner.
|
||||
*
|
||||
* @param name to test
|
||||
* @return true if pet name is already in use
|
||||
*/
|
||||
public Pet getPet(String name) {
|
||||
return getPet(name, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Pet with the given name, or null if none found for this Owner.
|
||||
*
|
||||
* @param name to test
|
||||
* @return true if pet name is already in use
|
||||
*/
|
||||
public Pet getPet(String name, boolean ignoreNew) {
|
||||
name = name.toLowerCase();
|
||||
for (Pet pet : getPetsInternal()) {
|
||||
if (!ignoreNew || !pet.isNew()) {
|
||||
String compName = pet.getName();
|
||||
compName = compName.toLowerCase();
|
||||
if (compName.equals(name)) {
|
||||
return pet;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Pet getPet(Integer petId) {
|
||||
return getPetsInternal().stream().filter(p -> p.getId().equals(petId)).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringCreator(this)
|
||||
|
||||
.append("id", this.getId())
|
||||
.append("new", this.isNew())
|
||||
.append("lastName", this.getLastName())
|
||||
.append("firstName", this.getFirstName())
|
||||
.append("address", this.address)
|
||||
.append("city", this.city)
|
||||
.append("telephone", this.telephone)
|
||||
.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.model;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
|
||||
/**
|
||||
* Simple JavaBean domain object representing an person.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
*/
|
||||
@MappedSuperclass
|
||||
public class Person extends BaseEntity {
|
||||
|
||||
@Column(name = "first_name")
|
||||
@NotEmpty
|
||||
protected String firstName;
|
||||
|
||||
@Column(name = "last_name")
|
||||
@NotEmpty
|
||||
protected String lastName;
|
||||
|
||||
public String getFirstName() {
|
||||
return this.firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return this.lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.model;
|
||||
|
||||
import org.springframework.beans.support.MutableSortDefinition;
|
||||
import org.springframework.beans.support.PropertyComparator;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import java.time.LocalDate;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* Simple business object representing a pet.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "pets")
|
||||
public class Pet extends NamedEntity {
|
||||
|
||||
@Column(name = "birth_date", columnDefinition = "DATE")
|
||||
private LocalDate birthDate;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "type_id")
|
||||
private PetType type;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "owner_id")
|
||||
private Owner owner;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "pet", fetch = FetchType.EAGER)
|
||||
private Set<Visit> visits;
|
||||
|
||||
public LocalDate getBirthDate() {
|
||||
return this.birthDate;
|
||||
}
|
||||
|
||||
public void setBirthDate(LocalDate birthDate) {
|
||||
this.birthDate = birthDate;
|
||||
}
|
||||
|
||||
public PetType getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public void setType(PetType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Owner getOwner() {
|
||||
return this.owner;
|
||||
}
|
||||
|
||||
public void setOwner(Owner owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
protected Set<Visit> getVisitsInternal() {
|
||||
if (this.visits == null) {
|
||||
this.visits = new HashSet<>();
|
||||
}
|
||||
return this.visits;
|
||||
}
|
||||
|
||||
protected void setVisitsInternal(Set<Visit> visits) {
|
||||
this.visits = visits;
|
||||
}
|
||||
|
||||
public List<Visit> getVisits() {
|
||||
List<Visit> sortedVisits = new ArrayList<>(getVisitsInternal());
|
||||
PropertyComparator.sort(sortedVisits, new MutableSortDefinition("date", false, false));
|
||||
return Collections.unmodifiableList(sortedVisits);
|
||||
}
|
||||
|
||||
public void setVisits(List<Visit> visits) {
|
||||
this.visits = new HashSet<>(visits);
|
||||
}
|
||||
|
||||
public void addVisit(Visit visit) {
|
||||
getVisitsInternal().add(visit);
|
||||
visit.setPet(this);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.model;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* Can be Cat, Dog, Hamster...
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "types")
|
||||
public class PetType extends NamedEntity {
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package org.springframework.samples.petclinic.model;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
@Entity
|
||||
@Table(name = "roles" ,uniqueConstraints = @UniqueConstraint(columnNames = {"username", "role"}))
|
||||
public class Role extends BaseEntity {
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "username")
|
||||
@JsonIgnore
|
||||
private User user;
|
||||
|
||||
@Column( name = "role")
|
||||
private String name;
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.model;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
/**
|
||||
* Models a {@link Vet Vet's} specialty (for example, dentistry).
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "specialties")
|
||||
public class Specialty extends NamedEntity {
|
||||
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package org.springframework.samples.petclinic.model;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
@Entity
|
||||
@Table(name = "users")
|
||||
public class User {
|
||||
|
||||
@Id
|
||||
@Column(name = "username")
|
||||
private String username;
|
||||
|
||||
@Column(name = "password")
|
||||
private String password;
|
||||
|
||||
@Column(name = "enabled")
|
||||
private Boolean enabled;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "user", fetch = FetchType.EAGER)
|
||||
private Set<Role> roles;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public Boolean getEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(Boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public Set<Role> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(Set<Role> roles) {
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public void addRole(String roleName) {
|
||||
if(this.roles == null) {
|
||||
this.roles = new HashSet<>();
|
||||
}
|
||||
Role role = new Role();
|
||||
role.setName(roleName);
|
||||
this.roles.add(role);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import org.springframework.beans.support.MutableSortDefinition;
|
||||
import org.springframework.beans.support.PropertyComparator;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Simple JavaBean domain object representing a veterinarian.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "vets")
|
||||
public class Vet extends Person {
|
||||
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
@JoinTable(name = "vet_specialties", joinColumns = @JoinColumn(name = "vet_id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "specialty_id"))
|
||||
private Set<Specialty> specialties;
|
||||
|
||||
@JsonIgnore
|
||||
protected Set<Specialty> getSpecialtiesInternal() {
|
||||
if (this.specialties == null) {
|
||||
this.specialties = new HashSet<>();
|
||||
}
|
||||
return this.specialties;
|
||||
}
|
||||
|
||||
protected void setSpecialtiesInternal(Set<Specialty> specialties) {
|
||||
this.specialties = specialties;
|
||||
}
|
||||
|
||||
@XmlElement
|
||||
public List<Specialty> getSpecialties() {
|
||||
List<Specialty> sortedSpecs = new ArrayList<>(getSpecialtiesInternal());
|
||||
PropertyComparator.sort(sortedSpecs, new MutableSortDefinition("name", true, true));
|
||||
return Collections.unmodifiableList(sortedSpecs);
|
||||
}
|
||||
|
||||
public void setSpecialties(List<Specialty> specialties) {
|
||||
this.specialties = new HashSet<>(specialties);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public int getNrOfSpecialties() {
|
||||
return getSpecialtiesInternal().size();
|
||||
}
|
||||
|
||||
public void addSpecialty(Specialty specialty) {
|
||||
getSpecialtiesInternal().add(specialty);
|
||||
}
|
||||
|
||||
public void clearSpecialties() {
|
||||
getSpecialtiesInternal().clear();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.model;
|
||||
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* Simple JavaBean domain object representing a visit.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "visits")
|
||||
public class Visit extends BaseEntity {
|
||||
|
||||
/**
|
||||
* Holds value of property date.
|
||||
*/
|
||||
@Column(name = "visit_date", columnDefinition = "DATE")
|
||||
private LocalDate date;
|
||||
|
||||
/**
|
||||
* Holds value of property description.
|
||||
*/
|
||||
@NotEmpty
|
||||
@Column(name = "description")
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* Holds value of property pet.
|
||||
*/
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "pet_id")
|
||||
private Pet pet;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance of Visit for the current date
|
||||
*/
|
||||
public Visit() {
|
||||
this.date = LocalDate.now();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Getter for property date.
|
||||
*
|
||||
* @return Value of property date.
|
||||
*/
|
||||
public LocalDate getDate() {
|
||||
return this.date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for property date.
|
||||
*
|
||||
* @param date New value of property date.
|
||||
*/
|
||||
public void setDate(LocalDate date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for property description.
|
||||
*
|
||||
* @return Value of property description.
|
||||
*/
|
||||
public String getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for property description.
|
||||
*
|
||||
* @param description New value of property description.
|
||||
*/
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for property pet.
|
||||
*
|
||||
* @return Value of property pet.
|
||||
*/
|
||||
public Pet getPet() {
|
||||
return this.pet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for property pet.
|
||||
*
|
||||
* @param pet New value of property pet.
|
||||
*/
|
||||
public void setPet(Pet pet) {
|
||||
this.pet = pet;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
/**
|
||||
* The classes in this package represent PetClinic's business layer.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.model;
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.samples.petclinic.model.BaseEntity;
|
||||
import org.springframework.samples.petclinic.model.Owner;
|
||||
|
||||
/**
|
||||
* Repository class for <code>Owner</code> domain objects All method names are compliant with Spring Data naming
|
||||
* conventions so this interface can easily be extended for Spring Data See here: http://static.springsource.org/spring-data/jpa/docs/current/reference/html/jpa.repositories.html#jpa.query-methods.query-creation
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @author Michael Isvy
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
public interface OwnerRepository {
|
||||
|
||||
/**
|
||||
* Retrieve <code>Owner</code>s from the data store by last name, returning all owners whose last name <i>starts</i>
|
||||
* with the given name.
|
||||
*
|
||||
* @param lastName Value to search for
|
||||
* @return a <code>Collection</code> of matching <code>Owner</code>s (or an empty <code>Collection</code> if none
|
||||
* found)
|
||||
*/
|
||||
Collection<Owner> findByLastName(String lastName) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Retrieve an <code>Owner</code> from the data store by id.
|
||||
*
|
||||
* @param id the id to search for
|
||||
* @return the <code>Owner</code> if found
|
||||
* @throws org.springframework.dao.DataRetrievalFailureException if not found
|
||||
*/
|
||||
Owner findById(int id) throws DataAccessException;
|
||||
|
||||
|
||||
/**
|
||||
* Save an <code>Owner</code> to the data store, either inserting or updating it.
|
||||
*
|
||||
* @param owner the <code>Owner</code> to save
|
||||
* @see BaseEntity#isNew
|
||||
*/
|
||||
void save(Owner owner) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Retrieve <code>Owner</code>s from the data store, returning all owners
|
||||
*
|
||||
* @return a <code>Collection</code> of <code>Owner</code>s (or an empty <code>Collection</code> if none
|
||||
* found)
|
||||
*/
|
||||
Collection<Owner> findAll() throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Delete an <code>Owner</code> to the data store by <code>Owner</code>.
|
||||
*
|
||||
* @param owner the <code>Owner</code> to delete
|
||||
*
|
||||
*/
|
||||
void delete(Owner owner) throws DataAccessException;
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.samples.petclinic.model.BaseEntity;
|
||||
import org.springframework.samples.petclinic.model.Pet;
|
||||
import org.springframework.samples.petclinic.model.PetType;
|
||||
|
||||
/**
|
||||
* Repository class for <code>Pet</code> domain objects All method names are compliant with Spring Data naming
|
||||
* conventions so this interface can easily be extended for Spring Data See here: http://static.springsource.org/spring-data/jpa/docs/current/reference/html/jpa.repositories.html#jpa.query-methods.query-creation
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @author Michael Isvy
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
public interface PetRepository {
|
||||
|
||||
/**
|
||||
* Retrieve all <code>PetType</code>s from the data store.
|
||||
*
|
||||
* @return a <code>Collection</code> of <code>PetType</code>s
|
||||
*/
|
||||
List<PetType> findPetTypes() throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Retrieve a <code>Pet</code> from the data store by id.
|
||||
*
|
||||
* @param id the id to search for
|
||||
* @return the <code>Pet</code> if found
|
||||
* @throws org.springframework.dao.DataRetrievalFailureException if not found
|
||||
*/
|
||||
Pet findById(int id) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Save a <code>Pet</code> to the data store, either inserting or updating it.
|
||||
*
|
||||
* @param pet the <code>Pet</code> to save
|
||||
* @see BaseEntity#isNew
|
||||
*/
|
||||
void save(Pet pet) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Retrieve <code>Pet</code>s from the data store, returning all owners
|
||||
*
|
||||
* @return a <code>Collection</code> of <code>Pet</code>s (or an empty <code>Collection</code> if none
|
||||
* found)
|
||||
*/
|
||||
Collection<Pet> findAll() throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Delete an <code>Pet</code> to the data store by <code>Pet</code>.
|
||||
*
|
||||
* @param pet the <code>Pet</code> to delete
|
||||
*
|
||||
*/
|
||||
void delete(Pet pet) throws DataAccessException;
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.repository;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.samples.petclinic.model.PetType;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*
|
||||
*/
|
||||
|
||||
public interface PetTypeRepository {
|
||||
|
||||
PetType findById(int id) throws DataAccessException;
|
||||
|
||||
PetType findByName(String name) throws DataAccessException;
|
||||
|
||||
Collection<PetType> findAll() throws DataAccessException;
|
||||
|
||||
void save(PetType petType) throws DataAccessException;
|
||||
|
||||
void delete(PetType petType) throws DataAccessException;
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.repository;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.samples.petclinic.model.Specialty;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*
|
||||
*/
|
||||
|
||||
public interface SpecialtyRepository {
|
||||
|
||||
Specialty findById(int id) throws DataAccessException;
|
||||
|
||||
List<Specialty> findSpecialtiesByNameIn(Set<String> names);
|
||||
|
||||
Collection<Specialty> findAll() throws DataAccessException;
|
||||
|
||||
void save(Specialty specialty) throws DataAccessException;
|
||||
|
||||
void delete(Specialty specialty) throws DataAccessException;
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package org.springframework.samples.petclinic.repository;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.samples.petclinic.model.User;
|
||||
|
||||
public interface UserRepository {
|
||||
|
||||
void save(User user) throws DataAccessException;
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.samples.petclinic.model.Vet;
|
||||
|
||||
/**
|
||||
* Repository class for <code>Vet</code> domain objects All method names are compliant with Spring Data naming
|
||||
* conventions so this interface can easily be extended for Spring Data See here: http://static.springsource.org/spring-data/jpa/docs/current/reference/html/jpa.repositories.html#jpa.query-methods.query-creation
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @author Michael Isvy
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
public interface VetRepository {
|
||||
|
||||
/**
|
||||
* Retrieve all <code>Vet</code>s from the data store.
|
||||
*
|
||||
* @return a <code>Collection</code> of <code>Vet</code>s
|
||||
*/
|
||||
Collection<Vet> findAll() throws DataAccessException;
|
||||
|
||||
Vet findById(int id) throws DataAccessException;
|
||||
|
||||
void save(Vet vet) throws DataAccessException;
|
||||
|
||||
void delete(Vet vet) throws DataAccessException;
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.samples.petclinic.model.BaseEntity;
|
||||
import org.springframework.samples.petclinic.model.Visit;
|
||||
|
||||
/**
|
||||
* Repository class for <code>Visit</code> domain objects All method names are compliant with Spring Data naming
|
||||
* conventions so this interface can easily be extended for Spring Data See here: http://static.springsource.org/spring-data/jpa/docs/current/reference/html/jpa.repositories.html#jpa.query-methods.query-creation
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @author Michael Isvy
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
public interface VisitRepository {
|
||||
|
||||
/**
|
||||
* Save a <code>Visit</code> to the data store, either inserting or updating it.
|
||||
*
|
||||
* @param visit the <code>Visit</code> to save
|
||||
* @see BaseEntity#isNew
|
||||
*/
|
||||
void save(Visit visit) throws DataAccessException;
|
||||
|
||||
List<Visit> findByPetId(Integer petId);
|
||||
|
||||
Visit findById(int id) throws DataAccessException;
|
||||
|
||||
Collection<Visit> findAll() throws DataAccessException;
|
||||
|
||||
void delete(Visit visit) throws DataAccessException;
|
||||
|
||||
}
|
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository.jdbc;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.BeanPropertyRowMapper;
|
||||
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
|
||||
import org.springframework.orm.ObjectRetrievalFailureException;
|
||||
import org.springframework.samples.petclinic.model.Owner;
|
||||
import org.springframework.samples.petclinic.model.Pet;
|
||||
import org.springframework.samples.petclinic.model.PetType;
|
||||
import org.springframework.samples.petclinic.model.Visit;
|
||||
import org.springframework.samples.petclinic.repository.OwnerRepository;
|
||||
import org.springframework.samples.petclinic.util.EntityUtils;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import jakarta.transaction.Transactional;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A simple JDBC-based implementation of the {@link OwnerRepository} interface.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
* @author Sam Brannen
|
||||
* @author Thomas Risberg
|
||||
* @author Mark Fisher
|
||||
* @author Antoine Rey
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
@Repository
|
||||
@Profile("jdbc")
|
||||
public class JdbcOwnerRepositoryImpl implements OwnerRepository {
|
||||
|
||||
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
|
||||
|
||||
private SimpleJdbcInsert insertOwner;
|
||||
|
||||
@Autowired
|
||||
public JdbcOwnerRepositoryImpl(DataSource dataSource) {
|
||||
|
||||
this.insertOwner = new SimpleJdbcInsert(dataSource)
|
||||
.withTableName("owners")
|
||||
.usingGeneratedKeyColumns("id");
|
||||
|
||||
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Loads {@link Owner Owners} from the data store by last name, returning all owners whose last name <i>starts</i> with
|
||||
* the given name; also loads the {@link Pet Pets} and {@link Visit Visits} for the corresponding owners, if not
|
||||
* already loaded.
|
||||
*/
|
||||
@Override
|
||||
public Collection<Owner> findByLastName(String lastName) throws DataAccessException {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("lastName", lastName + "%");
|
||||
List<Owner> owners = this.namedParameterJdbcTemplate.query(
|
||||
"SELECT id, first_name, last_name, address, city, telephone FROM owners WHERE last_name like :lastName",
|
||||
params,
|
||||
BeanPropertyRowMapper.newInstance(Owner.class)
|
||||
);
|
||||
loadOwnersPetsAndVisits(owners);
|
||||
return owners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the {@link Owner} with the supplied <code>id</code>; also loads the {@link Pet Pets} and {@link Visit Visits}
|
||||
* for the corresponding owner, if not already loaded.
|
||||
*/
|
||||
@Override
|
||||
public Owner findById(int id) throws DataAccessException {
|
||||
Owner owner;
|
||||
try {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("id", id);
|
||||
owner = this.namedParameterJdbcTemplate.queryForObject(
|
||||
"SELECT id, first_name, last_name, address, city, telephone FROM owners WHERE id= :id",
|
||||
params,
|
||||
BeanPropertyRowMapper.newInstance(Owner.class)
|
||||
);
|
||||
} catch (EmptyResultDataAccessException ex) {
|
||||
throw new ObjectRetrievalFailureException(Owner.class, id);
|
||||
}
|
||||
loadPetsAndVisits(owner);
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void loadPetsAndVisits(final Owner owner) {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("id", owner.getId());
|
||||
final List<JdbcPet> pets = this.namedParameterJdbcTemplate.query(
|
||||
"SELECT pets.id as pets_id, name, birth_date, type_id, owner_id, visits.id as visit_id, visit_date, description, visits.pet_id as visits_pet_id FROM pets LEFT OUTER JOIN visits ON pets.id = visits.pet_id WHERE owner_id=:id ORDER BY pets.id",
|
||||
params,
|
||||
new JdbcPetVisitExtractor()
|
||||
);
|
||||
Collection<PetType> petTypes = getPetTypes();
|
||||
for (JdbcPet pet : pets) {
|
||||
pet.setType(EntityUtils.getById(petTypes, PetType.class, pet.getTypeId()));
|
||||
owner.addPet(pet);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Owner owner) throws DataAccessException {
|
||||
BeanPropertySqlParameterSource parameterSource = new BeanPropertySqlParameterSource(owner);
|
||||
if (owner.isNew()) {
|
||||
Number newKey = this.insertOwner.executeAndReturnKey(parameterSource);
|
||||
owner.setId(newKey.intValue());
|
||||
} else {
|
||||
this.namedParameterJdbcTemplate.update(
|
||||
"UPDATE owners SET first_name=:firstName, last_name=:lastName, address=:address, " +
|
||||
"city=:city, telephone=:telephone WHERE id=:id",
|
||||
parameterSource);
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<PetType> getPetTypes() throws DataAccessException {
|
||||
return this.namedParameterJdbcTemplate.query(
|
||||
"SELECT id, name FROM types ORDER BY name", new HashMap<String, Object>(),
|
||||
BeanPropertyRowMapper.newInstance(PetType.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the {@link Pet} and {@link Visit} data for the supplied {@link List} of {@link Owner Owners}.
|
||||
*
|
||||
* @param owners the list of owners for whom the pet and visit data should be loaded
|
||||
* @see #loadPetsAndVisits(Owner)
|
||||
*/
|
||||
private void loadOwnersPetsAndVisits(List<Owner> owners) {
|
||||
for (Owner owner : owners) {
|
||||
loadPetsAndVisits(owner);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Owner> findAll() throws DataAccessException {
|
||||
List<Owner> owners = this.namedParameterJdbcTemplate.query(
|
||||
"SELECT id, first_name, last_name, address, city, telephone FROM owners",
|
||||
new HashMap<String, Object>(),
|
||||
BeanPropertyRowMapper.newInstance(Owner.class));
|
||||
for (Owner owner : owners) {
|
||||
loadPetsAndVisits(owner);
|
||||
}
|
||||
return owners;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void delete(Owner owner) throws DataAccessException {
|
||||
Map<String, Object> owner_params = new HashMap<>();
|
||||
owner_params.put("id", owner.getId());
|
||||
List<Pet> pets = owner.getPets();
|
||||
// cascade delete pets
|
||||
for (Pet pet : pets){
|
||||
Map<String, Object> pet_params = new HashMap<>();
|
||||
pet_params.put("id", pet.getId());
|
||||
// cascade delete visits
|
||||
List<Visit> visits = pet.getVisits();
|
||||
for (Visit visit : visits){
|
||||
Map<String, Object> visit_params = new HashMap<>();
|
||||
visit_params.put("id", visit.getId());
|
||||
this.namedParameterJdbcTemplate.update("DELETE FROM visits WHERE id=:id", visit_params);
|
||||
}
|
||||
this.namedParameterJdbcTemplate.update("DELETE FROM pets WHERE id=:id", pet_params);
|
||||
}
|
||||
this.namedParameterJdbcTemplate.update("DELETE FROM owners WHERE id=:id", owner_params);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository.jdbc;
|
||||
|
||||
import org.springframework.samples.petclinic.model.Pet;
|
||||
|
||||
/**
|
||||
* Subclass of Pet that carries temporary id properties which are only relevant for a JDBC implementation of the
|
||||
* PetRepository.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class JdbcPet extends Pet {
|
||||
|
||||
private int typeId;
|
||||
|
||||
private int ownerId;
|
||||
|
||||
public int getTypeId() {
|
||||
return this.typeId;
|
||||
}
|
||||
|
||||
public void setTypeId(int typeId) {
|
||||
this.typeId = typeId;
|
||||
}
|
||||
|
||||
public int getOwnerId() {
|
||||
return this.ownerId;
|
||||
}
|
||||
|
||||
public void setOwnerId(int ownerId) {
|
||||
this.ownerId = ownerId;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository.jdbc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.BeanPropertyRowMapper;
|
||||
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
|
||||
import org.springframework.orm.ObjectRetrievalFailureException;
|
||||
import org.springframework.samples.petclinic.model.Owner;
|
||||
import org.springframework.samples.petclinic.model.Pet;
|
||||
import org.springframework.samples.petclinic.model.PetType;
|
||||
import org.springframework.samples.petclinic.model.Visit;
|
||||
import org.springframework.samples.petclinic.repository.OwnerRepository;
|
||||
import org.springframework.samples.petclinic.repository.PetRepository;
|
||||
import org.springframework.samples.petclinic.repository.VisitRepository;
|
||||
import org.springframework.samples.petclinic.util.EntityUtils;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
* @author Sam Brannen
|
||||
* @author Thomas Risberg
|
||||
* @author Mark Fisher
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
@Repository
|
||||
@Profile("jdbc")
|
||||
public class JdbcPetRepositoryImpl implements PetRepository {
|
||||
|
||||
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
|
||||
|
||||
private SimpleJdbcInsert insertPet;
|
||||
|
||||
private OwnerRepository ownerRepository;
|
||||
|
||||
private VisitRepository visitRepository;
|
||||
|
||||
|
||||
@Autowired
|
||||
public JdbcPetRepositoryImpl(DataSource dataSource,
|
||||
OwnerRepository ownerRepository,
|
||||
VisitRepository visitRepository) {
|
||||
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
|
||||
|
||||
this.insertPet = new SimpleJdbcInsert(dataSource)
|
||||
.withTableName("pets")
|
||||
.usingGeneratedKeyColumns("id");
|
||||
|
||||
this.ownerRepository = ownerRepository;
|
||||
this.visitRepository = visitRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PetType> findPetTypes() throws DataAccessException {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
return this.namedParameterJdbcTemplate.query(
|
||||
"SELECT id, name FROM types ORDER BY name",
|
||||
params,
|
||||
BeanPropertyRowMapper.newInstance(PetType.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pet findById(int id) throws DataAccessException {
|
||||
Integer ownerId;
|
||||
try {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("id", id);
|
||||
ownerId = this.namedParameterJdbcTemplate.queryForObject("SELECT owner_id FROM pets WHERE id=:id", params, Integer.class);
|
||||
} catch (EmptyResultDataAccessException ex) {
|
||||
throw new ObjectRetrievalFailureException(Pet.class, id);
|
||||
}
|
||||
Owner owner = this.ownerRepository.findById(ownerId);
|
||||
return EntityUtils.getById(owner.getPets(), Pet.class, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Pet pet) throws DataAccessException {
|
||||
if (pet.isNew()) {
|
||||
Number newKey = this.insertPet.executeAndReturnKey(
|
||||
createPetParameterSource(pet));
|
||||
pet.setId(newKey.intValue());
|
||||
} else {
|
||||
this.namedParameterJdbcTemplate.update(
|
||||
"UPDATE pets SET name=:name, birth_date=:birth_date, type_id=:type_id, " +
|
||||
"owner_id=:owner_id WHERE id=:id",
|
||||
createPetParameterSource(pet));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link MapSqlParameterSource} based on data values from the supplied {@link Pet} instance.
|
||||
*/
|
||||
private MapSqlParameterSource createPetParameterSource(Pet pet) {
|
||||
return new MapSqlParameterSource()
|
||||
.addValue("id", pet.getId())
|
||||
.addValue("name", pet.getName())
|
||||
.addValue("birth_date", pet.getBirthDate())
|
||||
.addValue("type_id", pet.getType().getId())
|
||||
.addValue("owner_id", pet.getOwner().getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Pet> findAll() throws DataAccessException {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
Collection<Pet> pets = new ArrayList<Pet>();
|
||||
Collection<JdbcPet> jdbcPets = new ArrayList<JdbcPet>();
|
||||
jdbcPets = this.namedParameterJdbcTemplate
|
||||
.query("SELECT pets.id as pets_id, name, birth_date, type_id, owner_id FROM pets",
|
||||
params,
|
||||
new JdbcPetRowMapper());
|
||||
Collection<PetType> petTypes = this.namedParameterJdbcTemplate.query("SELECT id, name FROM types ORDER BY name",
|
||||
new HashMap<String,
|
||||
Object>(), BeanPropertyRowMapper.newInstance(PetType.class));
|
||||
Collection<Owner> owners = this.namedParameterJdbcTemplate.query(
|
||||
"SELECT id, first_name, last_name, address, city, telephone FROM owners ORDER BY last_name",
|
||||
new HashMap<String, Object>(),
|
||||
BeanPropertyRowMapper.newInstance(Owner.class));
|
||||
for (JdbcPet jdbcPet : jdbcPets) {
|
||||
jdbcPet.setType(EntityUtils.getById(petTypes, PetType.class, jdbcPet.getTypeId()));
|
||||
jdbcPet.setOwner(EntityUtils.getById(owners, Owner.class, jdbcPet.getOwnerId()));
|
||||
// TODO add visits
|
||||
pets.add(jdbcPet);
|
||||
}
|
||||
return pets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Pet pet) throws DataAccessException {
|
||||
Map<String, Object> pet_params = new HashMap<>();
|
||||
pet_params.put("id", pet.getId());
|
||||
List<Visit> visits = pet.getVisits();
|
||||
// cascade delete visits
|
||||
for (Visit visit : visits) {
|
||||
Map<String, Object> visit_params = new HashMap<>();
|
||||
visit_params.put("id", visit.getId());
|
||||
this.namedParameterJdbcTemplate.update("DELETE FROM visits WHERE id=:id", visit_params);
|
||||
}
|
||||
this.namedParameterJdbcTemplate.update("DELETE FROM pets WHERE id=:id", pet_params);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository.jdbc;
|
||||
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* {@link RowMapper} implementation mapping data from a {@link ResultSet} to the corresponding properties
|
||||
* of the {@link JdbcPet} class.
|
||||
*/
|
||||
public class JdbcPetRowMapper implements RowMapper<JdbcPet> {
|
||||
|
||||
@Override
|
||||
public JdbcPet mapRow(ResultSet rs, int rownum) throws SQLException {
|
||||
JdbcPet pet = new JdbcPet();
|
||||
pet.setId(rs.getInt("pets_id"));
|
||||
pet.setName(rs.getString("name"));
|
||||
pet.setBirthDate(rs.getObject("birth_date", LocalDate.class));
|
||||
pet.setTypeId(rs.getInt("type_id"));
|
||||
pet.setOwnerId(rs.getInt("owner_id"));
|
||||
return pet;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.repository.jdbc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.BeanPropertyRowMapper;
|
||||
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
|
||||
import org.springframework.orm.ObjectRetrievalFailureException;
|
||||
import org.springframework.samples.petclinic.model.Pet;
|
||||
import org.springframework.samples.petclinic.model.PetType;
|
||||
import org.springframework.samples.petclinic.model.Visit;
|
||||
import org.springframework.samples.petclinic.repository.PetTypeRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*
|
||||
*/
|
||||
|
||||
@Repository
|
||||
@Profile("jdbc")
|
||||
public class JdbcPetTypeRepositoryImpl implements PetTypeRepository {
|
||||
|
||||
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
|
||||
|
||||
private SimpleJdbcInsert insertPetType;
|
||||
|
||||
@Autowired
|
||||
public JdbcPetTypeRepositoryImpl(DataSource dataSource) {
|
||||
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
|
||||
this.insertPetType = new SimpleJdbcInsert(dataSource)
|
||||
.withTableName("types")
|
||||
.usingGeneratedKeyColumns("id");
|
||||
}
|
||||
|
||||
@Override
|
||||
public PetType findById(int id) {
|
||||
PetType petType;
|
||||
try {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("id", id);
|
||||
petType = this.namedParameterJdbcTemplate.queryForObject(
|
||||
"SELECT id, name FROM types WHERE id= :id",
|
||||
params,
|
||||
BeanPropertyRowMapper.newInstance(PetType.class));
|
||||
} catch (EmptyResultDataAccessException ex) {
|
||||
throw new ObjectRetrievalFailureException(PetType.class, id);
|
||||
}
|
||||
return petType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PetType findByName(String name) throws DataAccessException {
|
||||
PetType petType;
|
||||
try {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("name", name);
|
||||
petType = this.namedParameterJdbcTemplate.queryForObject(
|
||||
"SELECT id, name FROM types WHERE name= :name",
|
||||
params,
|
||||
BeanPropertyRowMapper.newInstance(PetType.class));
|
||||
} catch (EmptyResultDataAccessException ex) {
|
||||
throw new ObjectRetrievalFailureException(PetType.class, name);
|
||||
}
|
||||
return petType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<PetType> findAll() throws DataAccessException {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
return this.namedParameterJdbcTemplate.query(
|
||||
"SELECT id, name FROM types",
|
||||
params,
|
||||
BeanPropertyRowMapper.newInstance(PetType.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(PetType petType) throws DataAccessException {
|
||||
BeanPropertySqlParameterSource parameterSource = new BeanPropertySqlParameterSource(petType);
|
||||
if (petType.isNew()) {
|
||||
Number newKey = this.insertPetType.executeAndReturnKey(parameterSource);
|
||||
petType.setId(newKey.intValue());
|
||||
} else {
|
||||
this.namedParameterJdbcTemplate.update("UPDATE types SET name=:name WHERE id=:id",
|
||||
parameterSource);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(PetType petType) throws DataAccessException {
|
||||
Map<String, Object> pettype_params = new HashMap<>();
|
||||
pettype_params.put("id", petType.getId());
|
||||
List<Pet> pets = new ArrayList<Pet>();
|
||||
pets = this.namedParameterJdbcTemplate.
|
||||
query("SELECT pets.id, name, birth_date, type_id, owner_id FROM pets WHERE type_id=:id",
|
||||
pettype_params,
|
||||
BeanPropertyRowMapper.newInstance(Pet.class));
|
||||
// cascade delete pets
|
||||
for (Pet pet : pets){
|
||||
Map<String, Object> pet_params = new HashMap<>();
|
||||
pet_params.put("id", pet.getId());
|
||||
List<Visit> visits = new ArrayList<Visit>();
|
||||
visits = this.namedParameterJdbcTemplate.query(
|
||||
"SELECT id, pet_id, visit_date, description FROM visits WHERE pet_id = :id",
|
||||
pet_params,
|
||||
BeanPropertyRowMapper.newInstance(Visit.class));
|
||||
// cascade delete visits
|
||||
for (Visit visit : visits){
|
||||
Map<String, Object> visit_params = new HashMap<>();
|
||||
visit_params.put("id", visit.getId());
|
||||
this.namedParameterJdbcTemplate.update("DELETE FROM visits WHERE id=:id", visit_params);
|
||||
}
|
||||
this.namedParameterJdbcTemplate.update("DELETE FROM pets WHERE id=:id", pet_params);
|
||||
}
|
||||
this.namedParameterJdbcTemplate.update("DELETE FROM types WHERE id=:id", pettype_params);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository.jdbc;
|
||||
|
||||
import org.springframework.data.jdbc.core.OneToManyResultSetExtractor;
|
||||
import org.springframework.jdbc.core.ResultSetExtractor;
|
||||
import org.springframework.samples.petclinic.model.Visit;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* {@link ResultSetExtractor} implementation by using the
|
||||
* {@link OneToManyResultSetExtractor} of Spring Data Core JDBC Extensions.
|
||||
*/
|
||||
public class JdbcPetVisitExtractor extends
|
||||
OneToManyResultSetExtractor<JdbcPet, Visit, Integer> {
|
||||
|
||||
public JdbcPetVisitExtractor() {
|
||||
super(new JdbcPetRowMapper(), new JdbcVisitRowMapper());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Integer mapPrimaryKey(ResultSet rs) throws SQLException {
|
||||
return rs.getInt("pets_id");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Integer mapForeignKey(ResultSet rs) throws SQLException {
|
||||
if (rs.getObject("visits_pet_id") == null) {
|
||||
return null;
|
||||
} else {
|
||||
return rs.getInt("visits_pet_id");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addChild(JdbcPet root, Visit child) {
|
||||
root.addVisit(child);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.repository.jdbc;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.BeanPropertyRowMapper;
|
||||
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
|
||||
import org.springframework.orm.ObjectRetrievalFailureException;
|
||||
import org.springframework.samples.petclinic.model.Specialty;
|
||||
import org.springframework.samples.petclinic.repository.SpecialtyRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*
|
||||
*/
|
||||
|
||||
@Repository
|
||||
@Profile("jdbc")
|
||||
public class JdbcSpecialtyRepositoryImpl implements SpecialtyRepository {
|
||||
|
||||
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
|
||||
|
||||
private SimpleJdbcInsert insertSpecialty;
|
||||
|
||||
@Autowired
|
||||
public JdbcSpecialtyRepositoryImpl(DataSource dataSource) {
|
||||
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
|
||||
this.insertSpecialty = new SimpleJdbcInsert(dataSource)
|
||||
.withTableName("specialties")
|
||||
.usingGeneratedKeyColumns("id");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Specialty findById(int id) {
|
||||
Specialty specialty;
|
||||
try {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("id", id);
|
||||
specialty = this.namedParameterJdbcTemplate.queryForObject(
|
||||
"SELECT id, name FROM specialties WHERE id= :id",
|
||||
params,
|
||||
BeanPropertyRowMapper.newInstance(Specialty.class));
|
||||
} catch (EmptyResultDataAccessException ex) {
|
||||
throw new ObjectRetrievalFailureException(Specialty.class, id);
|
||||
}
|
||||
return specialty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Specialty> findSpecialtiesByNameIn(Set<String> names) {
|
||||
List<Specialty> specialties;
|
||||
try{
|
||||
String sql = "SELECT id, name FROM specialties WHERE specialties.name IN (:names)";
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("names", names);
|
||||
specialties = this.namedParameterJdbcTemplate.query(
|
||||
sql,
|
||||
params,
|
||||
new BeanPropertyRowMapper<>(Specialty.class));
|
||||
} catch (EmptyResultDataAccessException ex){
|
||||
throw new ObjectRetrievalFailureException(Specialty.class, names);
|
||||
}
|
||||
|
||||
return specialties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Specialty> findAll() throws DataAccessException {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
return this.namedParameterJdbcTemplate.query(
|
||||
"SELECT id, name FROM specialties",
|
||||
params,
|
||||
BeanPropertyRowMapper.newInstance(Specialty.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Specialty specialty) throws DataAccessException {
|
||||
BeanPropertySqlParameterSource parameterSource = new BeanPropertySqlParameterSource(specialty);
|
||||
if (specialty.isNew()) {
|
||||
Number newKey = this.insertSpecialty.executeAndReturnKey(parameterSource);
|
||||
specialty.setId(newKey.intValue());
|
||||
} else {
|
||||
this.namedParameterJdbcTemplate.update("UPDATE specialties SET name=:name WHERE id=:id",
|
||||
parameterSource);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Specialty specialty) throws DataAccessException {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("id", specialty.getId());
|
||||
this.namedParameterJdbcTemplate.update("DELETE FROM vet_specialties WHERE specialty_id=:id", params);
|
||||
this.namedParameterJdbcTemplate.update("DELETE FROM specialties WHERE id=:id", params);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package org.springframework.samples.petclinic.repository.jdbc;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.BeanPropertyRowMapper;
|
||||
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
|
||||
import org.springframework.samples.petclinic.model.Role;
|
||||
import org.springframework.samples.petclinic.model.User;
|
||||
import org.springframework.samples.petclinic.repository.UserRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
@Profile("jdbc")
|
||||
public class JdbcUserRepositoryImpl implements UserRepository {
|
||||
|
||||
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
|
||||
private SimpleJdbcInsert insertUser;
|
||||
|
||||
@Autowired
|
||||
public JdbcUserRepositoryImpl(DataSource dataSource) {
|
||||
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
|
||||
this.insertUser = new SimpleJdbcInsert(dataSource).withTableName("users");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(User user) throws DataAccessException {
|
||||
|
||||
BeanPropertySqlParameterSource parameterSource = new BeanPropertySqlParameterSource(user);
|
||||
|
||||
try {
|
||||
getByUsername(user.getUsername());
|
||||
this.namedParameterJdbcTemplate.update("UPDATE users SET password=:password, enabled=:enabled WHERE username=:username", parameterSource);
|
||||
} catch (EmptyResultDataAccessException e) {
|
||||
this.insertUser.execute(parameterSource);
|
||||
} finally {
|
||||
updateUserRoles(user);
|
||||
}
|
||||
}
|
||||
|
||||
private User getByUsername(String username) {
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("username", username);
|
||||
return this.namedParameterJdbcTemplate.queryForObject("SELECT * FROM users WHERE username=:username",
|
||||
params, BeanPropertyRowMapper.newInstance(User.class));
|
||||
}
|
||||
|
||||
private void updateUserRoles(User user) {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("username", user.getUsername());
|
||||
this.namedParameterJdbcTemplate.update("DELETE FROM roles WHERE username=:username", params);
|
||||
for (Role role : user.getRoles()) {
|
||||
params.put("role", role.getName());
|
||||
if (role.getName() != null) {
|
||||
this.namedParameterJdbcTemplate.update("INSERT INTO roles(username, role) VALUES (:username, :role)", params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository.jdbc;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.BeanPropertyRowMapper;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
|
||||
import org.springframework.orm.ObjectRetrievalFailureException;
|
||||
import org.springframework.samples.petclinic.model.Specialty;
|
||||
import org.springframework.samples.petclinic.model.Vet;
|
||||
import org.springframework.samples.petclinic.repository.VetRepository;
|
||||
import org.springframework.samples.petclinic.util.EntityUtils;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* A simple JDBC-based implementation of the {@link VetRepository} interface.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
* @author Sam Brannen
|
||||
* @author Thomas Risberg
|
||||
* @author Mark Fisher
|
||||
* @author Michael Isvy
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
@Repository
|
||||
@Profile("jdbc")
|
||||
public class JdbcVetRepositoryImpl implements VetRepository {
|
||||
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
|
||||
private SimpleJdbcInsert insertVet;
|
||||
|
||||
@Autowired
|
||||
public JdbcVetRepositoryImpl(DataSource dataSource, JdbcTemplate jdbcTemplate) {
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
this.insertVet = new SimpleJdbcInsert(dataSource).withTableName("vets").usingGeneratedKeyColumns("id");
|
||||
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the cache of Vets that the ClinicService is holding.
|
||||
*/
|
||||
@Override
|
||||
public Collection<Vet> findAll() throws DataAccessException {
|
||||
List<Vet> vets = new ArrayList<>();
|
||||
// Retrieve the list of all vets.
|
||||
vets.addAll(this.jdbcTemplate.query(
|
||||
"SELECT id, first_name, last_name FROM vets ORDER BY last_name,first_name",
|
||||
BeanPropertyRowMapper.newInstance(Vet.class)));
|
||||
|
||||
// Retrieve the list of all possible specialties.
|
||||
final List<Specialty> specialties = this.jdbcTemplate.query(
|
||||
"SELECT id, name FROM specialties",
|
||||
BeanPropertyRowMapper.newInstance(Specialty.class));
|
||||
|
||||
// Build each vet's list of specialties.
|
||||
for (Vet vet : vets) {
|
||||
final List<Integer> vetSpecialtiesIds = this.jdbcTemplate.query(
|
||||
"SELECT specialty_id FROM vet_specialties WHERE vet_id=?",
|
||||
new BeanPropertyRowMapper<Integer>() {
|
||||
@Override
|
||||
public Integer mapRow(ResultSet rs, int row) throws SQLException {
|
||||
return rs.getInt(1);
|
||||
}
|
||||
},
|
||||
vet.getId());
|
||||
for (int specialtyId : vetSpecialtiesIds) {
|
||||
Specialty specialty = EntityUtils.getById(specialties, Specialty.class, specialtyId);
|
||||
vet.addSpecialty(specialty);
|
||||
}
|
||||
}
|
||||
return vets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vet findById(int id) throws DataAccessException {
|
||||
Vet vet;
|
||||
try {
|
||||
Map<String, Object> vet_params = new HashMap<>();
|
||||
vet_params.put("id", id);
|
||||
vet = this.namedParameterJdbcTemplate.queryForObject(
|
||||
"SELECT id, first_name, last_name FROM vets WHERE id= :id",
|
||||
vet_params,
|
||||
BeanPropertyRowMapper.newInstance(Vet.class));
|
||||
|
||||
final List<Specialty> specialties = this.namedParameterJdbcTemplate.query(
|
||||
"SELECT id, name FROM specialties", vet_params, BeanPropertyRowMapper.newInstance(Specialty.class));
|
||||
|
||||
final List<Integer> vetSpecialtiesIds = this.namedParameterJdbcTemplate.query(
|
||||
"SELECT specialty_id FROM vet_specialties WHERE vet_id=:id",
|
||||
vet_params,
|
||||
new BeanPropertyRowMapper<Integer>() {
|
||||
@Override
|
||||
public Integer mapRow(ResultSet rs, int row) throws SQLException {
|
||||
return rs.getInt(1);
|
||||
}
|
||||
});
|
||||
for (int specialtyId : vetSpecialtiesIds) {
|
||||
Specialty specialty = EntityUtils.getById(specialties, Specialty.class, specialtyId);
|
||||
vet.addSpecialty(specialty);
|
||||
}
|
||||
|
||||
} catch (EmptyResultDataAccessException ex) {
|
||||
throw new ObjectRetrievalFailureException(Vet.class, id);
|
||||
}
|
||||
return vet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Vet vet) throws DataAccessException {
|
||||
BeanPropertySqlParameterSource parameterSource = new BeanPropertySqlParameterSource(vet);
|
||||
if (vet.isNew()) {
|
||||
Number newKey = this.insertVet.executeAndReturnKey(parameterSource);
|
||||
vet.setId(newKey.intValue());
|
||||
updateVetSpecialties(vet);
|
||||
} else {
|
||||
this.namedParameterJdbcTemplate
|
||||
.update("UPDATE vets SET first_name=:firstName, last_name=:lastName WHERE id=:id", parameterSource);
|
||||
updateVetSpecialties(vet);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Vet vet) throws DataAccessException {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("id", vet.getId());
|
||||
this.namedParameterJdbcTemplate.update("DELETE FROM vet_specialties WHERE vet_id=:id", params);
|
||||
this.namedParameterJdbcTemplate.update("DELETE FROM vets WHERE id=:id", params);
|
||||
}
|
||||
|
||||
private void updateVetSpecialties(Vet vet) throws DataAccessException {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("id", vet.getId());
|
||||
this.namedParameterJdbcTemplate.update("DELETE FROM vet_specialties WHERE vet_id=:id", params);
|
||||
for (Specialty spec : vet.getSpecialties()) {
|
||||
params.put("spec_id", spec.getId());
|
||||
if(!(spec.getId() == null)) {
|
||||
this.namedParameterJdbcTemplate.update("INSERT INTO vet_specialties VALUES (:id, :spec_id)", params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository.jdbc;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.BeanPropertyRowMapper;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
|
||||
import org.springframework.orm.ObjectRetrievalFailureException;
|
||||
import org.springframework.samples.petclinic.model.Owner;
|
||||
import org.springframework.samples.petclinic.model.PetType;
|
||||
import org.springframework.samples.petclinic.model.Visit;
|
||||
import org.springframework.samples.petclinic.repository.VisitRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A simple JDBC-based implementation of the {@link VisitRepository} interface.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
* @author Sam Brannen
|
||||
* @author Thomas Risberg
|
||||
* @author Mark Fisher
|
||||
* @author Michael Isvy
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
@Repository
|
||||
@Profile("jdbc")
|
||||
public class JdbcVisitRepositoryImpl implements VisitRepository {
|
||||
|
||||
protected SimpleJdbcInsert insertVisit;
|
||||
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
|
||||
|
||||
@Autowired
|
||||
public JdbcVisitRepositoryImpl(DataSource dataSource) {
|
||||
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
|
||||
|
||||
this.insertVisit = new SimpleJdbcInsert(dataSource)
|
||||
.withTableName("visits")
|
||||
.usingGeneratedKeyColumns("id");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a {@link MapSqlParameterSource} based on data values from the supplied {@link Visit} instance.
|
||||
*/
|
||||
protected MapSqlParameterSource createVisitParameterSource(Visit visit) {
|
||||
return new MapSqlParameterSource()
|
||||
.addValue("id", visit.getId())
|
||||
.addValue("visit_date", visit.getDate())
|
||||
.addValue("description", visit.getDescription())
|
||||
.addValue("pet_id", visit.getPet().getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Visit> findByPetId(Integer petId) {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("id", petId);
|
||||
JdbcPet pet = this.namedParameterJdbcTemplate.queryForObject(
|
||||
"SELECT id as pets_id, name, birth_date, type_id, owner_id FROM pets WHERE id=:id",
|
||||
params,
|
||||
new JdbcPetRowMapper());
|
||||
|
||||
List<Visit> visits = this.namedParameterJdbcTemplate.query(
|
||||
"SELECT id as visit_id, visit_date, description FROM visits WHERE pet_id=:id",
|
||||
params, new JdbcVisitRowMapper());
|
||||
|
||||
for (Visit visit : visits) {
|
||||
visit.setPet(pet);
|
||||
}
|
||||
|
||||
return visits;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Visit findById(int id) throws DataAccessException {
|
||||
Visit visit;
|
||||
try {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("id", id);
|
||||
visit = this.namedParameterJdbcTemplate.queryForObject(
|
||||
"SELECT id as visit_id, visits.pet_id as pets_id, visit_date, description FROM visits WHERE id= :id",
|
||||
params,
|
||||
new JdbcVisitRowMapperExt());
|
||||
} catch (EmptyResultDataAccessException ex) {
|
||||
throw new ObjectRetrievalFailureException(Visit.class, id);
|
||||
}
|
||||
return visit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Visit> findAll() throws DataAccessException {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
return this.namedParameterJdbcTemplate.query(
|
||||
"SELECT id as visit_id, pets.id as pets_id, visit_date, description FROM visits LEFT JOIN pets ON visits.pet_id = pets.id",
|
||||
params, new JdbcVisitRowMapperExt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Visit visit) throws DataAccessException {
|
||||
if (visit.isNew()) {
|
||||
Number newKey = this.insertVisit.executeAndReturnKey(createVisitParameterSource(visit));
|
||||
visit.setId(newKey.intValue());
|
||||
} else {
|
||||
this.namedParameterJdbcTemplate.update(
|
||||
"UPDATE visits SET visit_date=:visit_date, description=:description, pet_id=:pet_id WHERE id=:id ",
|
||||
createVisitParameterSource(visit));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Visit visit) throws DataAccessException {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("id", visit.getId());
|
||||
this.namedParameterJdbcTemplate.update("DELETE FROM visits WHERE id=:id", params);
|
||||
}
|
||||
|
||||
protected class JdbcVisitRowMapperExt implements RowMapper<Visit> {
|
||||
|
||||
@Override
|
||||
public Visit mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
Visit visit = new Visit();
|
||||
JdbcPet pet = new JdbcPet();
|
||||
PetType petType = new PetType();
|
||||
Owner owner = new Owner();
|
||||
visit.setId(rs.getInt("visit_id"));
|
||||
Date visitDate = rs.getDate("visit_date");
|
||||
visit.setDate(new java.sql.Date(visitDate.getTime()).toLocalDate());
|
||||
visit.setDescription(rs.getString("description"));
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("id", rs.getInt("pets_id"));
|
||||
pet = JdbcVisitRepositoryImpl.this.namedParameterJdbcTemplate.queryForObject(
|
||||
"SELECT pets.id as pets_id, name, birth_date, type_id, owner_id FROM pets WHERE pets.id=:id",
|
||||
params,
|
||||
new JdbcPetRowMapper());
|
||||
params.put("type_id", pet.getTypeId());
|
||||
petType = JdbcVisitRepositoryImpl.this.namedParameterJdbcTemplate.queryForObject(
|
||||
"SELECT id, name FROM types WHERE id= :type_id",
|
||||
params,
|
||||
BeanPropertyRowMapper.newInstance(PetType.class));
|
||||
pet.setType(petType);
|
||||
params.put("owner_id", pet.getOwnerId());
|
||||
owner = JdbcVisitRepositoryImpl.this.namedParameterJdbcTemplate.queryForObject(
|
||||
"SELECT id, first_name, last_name, address, city, telephone FROM owners WHERE id= :owner_id",
|
||||
params,
|
||||
BeanPropertyRowMapper.newInstance(Owner.class));
|
||||
pet.setOwner(owner);
|
||||
visit.setPet(pet);
|
||||
return visit;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository.jdbc;
|
||||
|
||||
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.samples.petclinic.model.Visit;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* {@link RowMapper} implementation mapping data from a {@link ResultSet} to the corresponding properties
|
||||
* of the {@link Visit} class.
|
||||
*/
|
||||
class JdbcVisitRowMapper implements RowMapper<Visit> {
|
||||
|
||||
@Override
|
||||
public Visit mapRow(ResultSet rs, int row) throws SQLException {
|
||||
Visit visit = new Visit();
|
||||
visit.setId(rs.getInt("visit_id"));
|
||||
visit.setDate(rs.getObject("visit_date", LocalDate.class));
|
||||
visit.setDescription(rs.getString("description"));
|
||||
return visit;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
/**
|
||||
* The classes in this package represent the JDBC implementation
|
||||
* of PetClinic's persistence layer.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository.jdbc;
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository.jpa;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import jakarta.persistence.Query;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.orm.hibernate5.support.OpenSessionInViewFilter;
|
||||
import org.springframework.samples.petclinic.model.Owner;
|
||||
import org.springframework.samples.petclinic.repository.OwnerRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* JPA implementation of the {@link OwnerRepository} interface.
|
||||
*
|
||||
* @author Mike Keith
|
||||
* @author Rod Johnson
|
||||
* @author Sam Brannen
|
||||
* @author Michael Isvy
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
@Repository
|
||||
@Profile("jpa")
|
||||
public class JpaOwnerRepositoryImpl implements OwnerRepository {
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager em;
|
||||
|
||||
|
||||
/**
|
||||
* Important: in the current version of this method, we load Owners with all their Pets and Visits while
|
||||
* we do not need Visits at all and we only need one property from the Pet objects (the 'name' property).
|
||||
* There are some ways to improve it such as:
|
||||
* - creating a Ligtweight class (example here: https://community.jboss.org/wiki/LightweightClass)
|
||||
* - Turning on lazy-loading and using {@link OpenSessionInViewFilter}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Collection<Owner> findByLastName(String lastName) {
|
||||
// using 'join fetch' because a single query should load both owners and pets
|
||||
// using 'left join fetch' because it might happen that an owner does not have pets yet
|
||||
Query query = this.em.createQuery("SELECT DISTINCT owner FROM Owner owner left join fetch owner.pets WHERE owner.lastName LIKE :lastName");
|
||||
query.setParameter("lastName", lastName + "%");
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Owner findById(int id) {
|
||||
// using 'join fetch' because a single query should load both owners and pets
|
||||
// using 'left join fetch' because it might happen that an owner does not have pets yet
|
||||
Query query = this.em.createQuery("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:id");
|
||||
query.setParameter("id", id);
|
||||
return (Owner) query.getSingleResult();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save(Owner owner) {
|
||||
if (owner.getId() == null) {
|
||||
this.em.persist(owner);
|
||||
} else {
|
||||
this.em.merge(owner);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Collection<Owner> findAll() throws DataAccessException {
|
||||
Query query = this.em.createQuery("SELECT owner FROM Owner owner");
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Owner owner) throws DataAccessException {
|
||||
this.em.remove(this.em.contains(owner) ? owner : this.em.merge(owner));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository.jpa;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.samples.petclinic.model.Pet;
|
||||
import org.springframework.samples.petclinic.model.PetType;
|
||||
import org.springframework.samples.petclinic.repository.PetRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* JPA implementation of the {@link PetRepository} interface.
|
||||
*
|
||||
* @author Mike Keith
|
||||
* @author Rod Johnson
|
||||
* @author Sam Brannen
|
||||
* @author Michael Isvy
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
@Repository
|
||||
@Profile("jpa")
|
||||
public class JpaPetRepositoryImpl implements PetRepository {
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager em;
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<PetType> findPetTypes() {
|
||||
return this.em.createQuery("SELECT ptype FROM PetType ptype ORDER BY ptype.name").getResultList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pet findById(int id) {
|
||||
return this.em.find(Pet.class, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Pet pet) {
|
||||
if (pet.getId() == null) {
|
||||
this.em.persist(pet);
|
||||
} else {
|
||||
this.em.merge(pet);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Collection<Pet> findAll() throws DataAccessException {
|
||||
return this.em.createQuery("SELECT pet FROM Pet pet").getResultList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Pet pet) throws DataAccessException {
|
||||
//this.em.remove(this.em.contains(pet) ? pet : this.em.merge(pet));
|
||||
String petId = pet.getId().toString();
|
||||
this.em.createQuery("DELETE FROM Visit visit WHERE pet.id=" + petId).executeUpdate();
|
||||
this.em.createQuery("DELETE FROM Pet pet WHERE id=" + petId).executeUpdate();
|
||||
if (em.contains(pet)) {
|
||||
em.remove(pet);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.repository.jpa;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.samples.petclinic.model.Pet;
|
||||
import org.springframework.samples.petclinic.model.PetType;
|
||||
import org.springframework.samples.petclinic.model.Visit;
|
||||
import org.springframework.samples.petclinic.repository.PetTypeRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*
|
||||
*/
|
||||
|
||||
@Repository
|
||||
@Profile("jpa")
|
||||
public class JpaPetTypeRepositoryImpl implements PetTypeRepository {
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager em;
|
||||
|
||||
@Override
|
||||
public PetType findById(int id) {
|
||||
return this.em.find(PetType.class, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PetType findByName(String name) throws DataAccessException {
|
||||
return this.em.createQuery("SELECT p FROM PetType p WHERE p.name = :name", PetType.class)
|
||||
.setParameter("name", name)
|
||||
.getSingleResult();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Collection<PetType> findAll() throws DataAccessException {
|
||||
return this.em.createQuery("SELECT ptype FROM PetType ptype").getResultList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(PetType petType) throws DataAccessException {
|
||||
if (petType.getId() == null) {
|
||||
this.em.persist(petType);
|
||||
} else {
|
||||
this.em.merge(petType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void delete(PetType petType) throws DataAccessException {
|
||||
this.em.remove(this.em.contains(petType) ? petType : this.em.merge(petType));
|
||||
Integer petTypeId = petType.getId();
|
||||
|
||||
List<Pet> pets = this.em.createQuery("SELECT pet FROM Pet pet WHERE type.id=" + petTypeId).getResultList();
|
||||
for (Pet pet : pets){
|
||||
List<Visit> visits = pet.getVisits();
|
||||
for (Visit visit : visits){
|
||||
this.em.createQuery("DELETE FROM Visit visit WHERE id=" + visit.getId()).executeUpdate();
|
||||
}
|
||||
this.em.createQuery("DELETE FROM Pet pet WHERE id=" + pet.getId()).executeUpdate();
|
||||
}
|
||||
this.em.createQuery("DELETE FROM PetType pettype WHERE id=" + petTypeId).executeUpdate();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.repository.jpa;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.samples.petclinic.model.Specialty;
|
||||
import org.springframework.samples.petclinic.repository.SpecialtyRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*
|
||||
*/
|
||||
|
||||
@Repository
|
||||
@Profile("jpa")
|
||||
public class JpaSpecialtyRepositoryImpl implements SpecialtyRepository {
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager em;
|
||||
|
||||
@Override
|
||||
public Specialty findById(int id) {
|
||||
return this.em.find(Specialty.class, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Specialty> findSpecialtiesByNameIn(Set<String> names) {
|
||||
final String jpql = "SELECT s FROM Specialty s WHERE s.name IN :names";
|
||||
return em.createQuery(jpql, Specialty.class)
|
||||
.setParameter("names", names)
|
||||
.getResultList();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Collection<Specialty> findAll() throws DataAccessException {
|
||||
return this.em.createQuery("SELECT s FROM Specialty s").getResultList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Specialty specialty) throws DataAccessException {
|
||||
if (specialty.getId() == null) {
|
||||
this.em.persist(specialty);
|
||||
} else {
|
||||
this.em.merge(specialty);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Specialty specialty) throws DataAccessException {
|
||||
this.em.remove(this.em.contains(specialty) ? specialty : this.em.merge(specialty));
|
||||
Integer specId = specialty.getId();
|
||||
this.em.createNativeQuery("DELETE FROM vet_specialties WHERE specialty_id=" + specId).executeUpdate();
|
||||
this.em.createQuery("DELETE FROM Specialty specialty WHERE id=" + specId).executeUpdate();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package org.springframework.samples.petclinic.repository.jpa;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.samples.petclinic.model.User;
|
||||
import org.springframework.samples.petclinic.repository.UserRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
@Profile("jpa")
|
||||
public class JpaUserRepositoryImpl implements UserRepository {
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager em;
|
||||
|
||||
@Override
|
||||
public void save(User user) throws DataAccessException {
|
||||
if (this.em.find(User.class, user.getUsername()) == null) {
|
||||
this.em.persist(user);
|
||||
} else {
|
||||
this.em.merge(user);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository.jpa;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.samples.petclinic.model.Vet;
|
||||
import org.springframework.samples.petclinic.repository.VetRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* JPA implementation of the {@link VetRepository} interface.
|
||||
*
|
||||
* @author Mike Keith
|
||||
* @author Rod Johnson
|
||||
* @author Sam Brannen
|
||||
* @author Michael Isvy
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
@Repository
|
||||
@Profile("jpa")
|
||||
public class JpaVetRepositoryImpl implements VetRepository {
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager em;
|
||||
|
||||
|
||||
@Override
|
||||
public Vet findById(int id) throws DataAccessException {
|
||||
return this.em.find(Vet.class, id);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Collection<Vet> findAll() throws DataAccessException {
|
||||
return this.em.createQuery("SELECT vet FROM Vet vet").getResultList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Vet vet) throws DataAccessException {
|
||||
if (vet.getId() == null) {
|
||||
this.em.persist(vet);
|
||||
} else {
|
||||
this.em.merge(vet);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Vet vet) throws DataAccessException {
|
||||
this.em.remove(this.em.contains(vet) ? vet : this.em.merge(vet));
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository.jpa;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import jakarta.persistence.Query;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.samples.petclinic.model.Visit;
|
||||
import org.springframework.samples.petclinic.repository.VisitRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* JPA implementation of the ClinicService interface using EntityManager.
|
||||
* <p/>
|
||||
* <p>The mappings are defined in "orm.xml" located in the META-INF directory.
|
||||
*
|
||||
* @author Mike Keith
|
||||
* @author Rod Johnson
|
||||
* @author Sam Brannen
|
||||
* @author Michael Isvy
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
@Repository
|
||||
@Profile("jpa")
|
||||
public class JpaVisitRepositoryImpl implements VisitRepository {
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager em;
|
||||
|
||||
|
||||
@Override
|
||||
public void save(Visit visit) {
|
||||
if (visit.getId() == null) {
|
||||
this.em.persist(visit);
|
||||
} else {
|
||||
this.em.merge(visit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Visit> findByPetId(Integer petId) {
|
||||
Query query = this.em.createQuery("SELECT v FROM Visit v where v.pet.id= :id");
|
||||
query.setParameter("id", petId);
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Visit findById(int id) throws DataAccessException {
|
||||
return this.em.find(Visit.class, id);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Collection<Visit> findAll() throws DataAccessException {
|
||||
return this.em.createQuery("SELECT v FROM Visit v").getResultList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Visit visit) throws DataAccessException {
|
||||
this.em.remove(this.em.contains(visit) ? visit : this.em.merge(visit));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
/**
|
||||
* The classes in this package represent the JPA implementation
|
||||
* of PetClinic's persistence layer.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository.jpa;
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.repository.springdatajpa;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.samples.petclinic.model.Pet;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*
|
||||
*/
|
||||
|
||||
@Profile("spring-data-jpa")
|
||||
public interface PetRepositoryOverride {
|
||||
|
||||
void delete(Pet pet);
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.repository.springdatajpa;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.samples.petclinic.model.PetType;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*
|
||||
*/
|
||||
|
||||
@Profile("spring-data-jpa")
|
||||
public interface PetTypeRepositoryOverride {
|
||||
|
||||
void delete(PetType petType);
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.repository.springdatajpa;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.samples.petclinic.model.Specialty;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*
|
||||
*/
|
||||
|
||||
@Profile("spring-data-jpa")
|
||||
public interface SpecialtyRepositoryOverride {
|
||||
|
||||
void delete(Specialty specialty);
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository.springdatajpa;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.samples.petclinic.model.Owner;
|
||||
import org.springframework.samples.petclinic.repository.OwnerRepository;
|
||||
|
||||
/**
|
||||
* Spring Data JPA specialization of the {@link OwnerRepository} interface
|
||||
*
|
||||
* @author Michael Isvy
|
||||
* @since 15.1.2013
|
||||
*/
|
||||
|
||||
@Profile("spring-data-jpa")
|
||||
public interface SpringDataOwnerRepository extends OwnerRepository, Repository<Owner, Integer> {
|
||||
|
||||
@Override
|
||||
@Query("SELECT DISTINCT owner FROM Owner owner left join fetch owner.pets WHERE owner.lastName LIKE :lastName%")
|
||||
Collection<Owner> findByLastName(@Param("lastName") String lastName);
|
||||
|
||||
@Override
|
||||
@Query("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:id")
|
||||
Owner findById(@Param("id") int id);
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository.springdatajpa;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.samples.petclinic.model.Pet;
|
||||
import org.springframework.samples.petclinic.model.PetType;
|
||||
import org.springframework.samples.petclinic.repository.PetRepository;
|
||||
|
||||
/**
|
||||
* Spring Data JPA specialization of the {@link PetRepository} interface
|
||||
*
|
||||
* @author Michael Isvy
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
|
||||
@Profile("spring-data-jpa")
|
||||
public interface SpringDataPetRepository extends PetRepository, Repository<Pet, Integer>, PetRepositoryOverride {
|
||||
|
||||
@Override
|
||||
@Query("SELECT ptype FROM PetType ptype ORDER BY ptype.name")
|
||||
List<PetType> findPetTypes() throws DataAccessException;
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.repository.springdatajpa;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.samples.petclinic.model.Pet;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*
|
||||
*/
|
||||
|
||||
@Profile("spring-data-jpa")
|
||||
public class SpringDataPetRepositoryImpl implements PetRepositoryOverride {
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager em;
|
||||
|
||||
@Override
|
||||
public void delete(Pet pet) {
|
||||
String petId = pet.getId().toString();
|
||||
this.em.createQuery("DELETE FROM Visit visit WHERE pet.id=" + petId).executeUpdate();
|
||||
this.em.createQuery("DELETE FROM Pet pet WHERE id=" + petId).executeUpdate();
|
||||
if (em.contains(pet)) {
|
||||
em.remove(pet);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.repository.springdatajpa;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.samples.petclinic.model.PetType;
|
||||
import org.springframework.samples.petclinic.repository.PetTypeRepository;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*
|
||||
*/
|
||||
|
||||
@Profile("spring-data-jpa")
|
||||
public interface SpringDataPetTypeRepository extends PetTypeRepository, Repository<PetType, Integer>, PetTypeRepositoryOverride {
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.repository.springdatajpa;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.samples.petclinic.model.Pet;
|
||||
import org.springframework.samples.petclinic.model.PetType;
|
||||
import org.springframework.samples.petclinic.model.Visit;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*
|
||||
*/
|
||||
|
||||
@Profile("spring-data-jpa")
|
||||
public class SpringDataPetTypeRepositoryImpl implements PetTypeRepositoryOverride {
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager em;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void delete(PetType petType) {
|
||||
this.em.remove(this.em.contains(petType) ? petType : this.em.merge(petType));
|
||||
Integer petTypeId = petType.getId();
|
||||
|
||||
List<Pet> pets = this.em.createQuery("SELECT pet FROM Pet pet WHERE type.id=" + petTypeId).getResultList();
|
||||
for (Pet pet : pets){
|
||||
List<Visit> visits = pet.getVisits();
|
||||
for (Visit visit : visits){
|
||||
this.em.createQuery("DELETE FROM Visit visit WHERE id=" + visit.getId()).executeUpdate();
|
||||
}
|
||||
this.em.createQuery("DELETE FROM Pet pet WHERE id=" + pet.getId()).executeUpdate();
|
||||
}
|
||||
this.em.createQuery("DELETE FROM PetType pettype WHERE id=" + petTypeId).executeUpdate();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.repository.springdatajpa;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.samples.petclinic.model.Specialty;
|
||||
import org.springframework.samples.petclinic.repository.SpecialtyRepository;
|
||||
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*
|
||||
*/
|
||||
|
||||
@Profile("spring-data-jpa")
|
||||
public interface SpringDataSpecialtyRepository extends SpecialtyRepository, Repository<Specialty, Integer>, SpecialtyRepositoryOverride {
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.repository.springdatajpa;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.samples.petclinic.model.Specialty;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*
|
||||
*/
|
||||
|
||||
@Profile("spring-data-jpa")
|
||||
public class SpringDataSpecialtyRepositoryImpl implements SpecialtyRepositoryOverride {
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager em;
|
||||
|
||||
@Override
|
||||
public void delete(Specialty specialty) {
|
||||
this.em.remove(this.em.contains(specialty) ? specialty : this.em.merge(specialty));
|
||||
Integer specId = specialty.getId();
|
||||
this.em.createNativeQuery("DELETE FROM vet_specialties WHERE specialty_id=" + specId).executeUpdate();
|
||||
this.em.createQuery("DELETE FROM Specialty specialty WHERE id=" + specId).executeUpdate();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package org.springframework.samples.petclinic.repository.springdatajpa;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.samples.petclinic.model.User;
|
||||
import org.springframework.samples.petclinic.repository.UserRepository;
|
||||
|
||||
@Profile("spring-data-jpa")
|
||||
public interface SpringDataUserRepository extends UserRepository, Repository<User, String> {
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository.springdatajpa;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.samples.petclinic.model.Vet;
|
||||
import org.springframework.samples.petclinic.repository.VetRepository;
|
||||
|
||||
/**
|
||||
* Spring Data JPA specialization of the {@link VetRepository} interface
|
||||
*
|
||||
* @author Michael Isvy
|
||||
* @since 15.1.2013
|
||||
*/
|
||||
|
||||
@Profile("spring-data-jpa")
|
||||
public interface SpringDataVetRepository extends VetRepository, Repository<Vet, Integer> {
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.repository.springdatajpa;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.samples.petclinic.model.Visit;
|
||||
import org.springframework.samples.petclinic.repository.VisitRepository;
|
||||
|
||||
/**
|
||||
* Spring Data JPA specialization of the {@link VisitRepository} interface
|
||||
*
|
||||
* @author Michael Isvy
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
|
||||
@Profile("spring-data-jpa")
|
||||
public interface SpringDataVisitRepository extends VisitRepository, Repository<Visit, Integer>, VisitRepositoryOverride {
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.repository.springdatajpa;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.samples.petclinic.model.Visit;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*
|
||||
*/
|
||||
|
||||
@Profile("spring-data-jpa")
|
||||
public class SpringDataVisitRepositoryImpl implements VisitRepositoryOverride {
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager em;
|
||||
|
||||
@Override
|
||||
public void delete(Visit visit) throws DataAccessException {
|
||||
String visitId = visit.getId().toString();
|
||||
this.em.createQuery("DELETE FROM Visit visit WHERE id=" + visitId).executeUpdate();
|
||||
if (em.contains(visit)) {
|
||||
em.remove(visit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.repository.springdatajpa;
|
||||
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.samples.petclinic.model.Visit;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*
|
||||
*/
|
||||
|
||||
@Profile("spring-data-jpa")
|
||||
public interface VisitRepositoryOverride {
|
||||
|
||||
void delete(Visit visit);
|
||||
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.rest.advice;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.samples.petclinic.rest.controller.BindingErrorsResponse;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
|
||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||
|
||||
/**
|
||||
* Global Exception handler for REST controllers.
|
||||
* <p>
|
||||
* This class handles exceptions thrown by REST controllers and returns
|
||||
* appropriate HTTP responses to the client.
|
||||
*
|
||||
* @author Vitaliy Fedoriv
|
||||
* @author Alexander Dudkin
|
||||
*/
|
||||
@ControllerAdvice
|
||||
public class ExceptionControllerAdvice {
|
||||
|
||||
/**
|
||||
* Record for storing error information.
|
||||
* <p>
|
||||
* This record encapsulates the class name and message of the exception.
|
||||
*
|
||||
* @param className The name of the exception class
|
||||
* @param exMessage The message of the exception
|
||||
*/
|
||||
private record ErrorInfo(String className, String exMessage) {
|
||||
public ErrorInfo(Exception ex) {
|
||||
this(ex.getClass().getName(), ex.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles all general exceptions by returning a 500 Internal Server Error status with error details.
|
||||
*
|
||||
* @param e The exception to be handled
|
||||
* @return A {@link ResponseEntity} containing the error information and a 500 Internal Server Error status
|
||||
*/
|
||||
@ExceptionHandler(Exception.class)
|
||||
public ResponseEntity<ErrorInfo> handleGeneralException(Exception e) {
|
||||
ErrorInfo info = new ErrorInfo(e);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(info);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles {@link DataIntegrityViolationException} which typically indicates database constraint violations.
|
||||
* This method returns a 404 Not Found status if an entity does not exist.
|
||||
*
|
||||
* @param ex The {@link DataIntegrityViolationException} to be handled
|
||||
* @return A {@link ResponseEntity} containing the error information and a 404 Not Found status
|
||||
*/
|
||||
@ExceptionHandler(DataIntegrityViolationException.class)
|
||||
@ResponseStatus(code = HttpStatus.NOT_FOUND)
|
||||
@ResponseBody
|
||||
public ResponseEntity<ErrorInfo> handleDataIntegrityViolationException(DataIntegrityViolationException ex) {
|
||||
ErrorInfo errorInfo = new ErrorInfo(ex);
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(errorInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles exception thrown by Bean Validation on controller methods parameters
|
||||
*
|
||||
* @param ex The thrown exception
|
||||
*
|
||||
* @return an empty response entity
|
||||
*/
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
@ResponseStatus(BAD_REQUEST)
|
||||
@ResponseBody
|
||||
public ResponseEntity<ErrorInfo> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
|
||||
BindingErrorsResponse errors = new BindingErrorsResponse();
|
||||
BindingResult bindingResult = ex.getBindingResult();
|
||||
if (bindingResult.hasErrors()) {
|
||||
errors.addAllErrors(bindingResult);
|
||||
return ResponseEntity.badRequest().body(new ErrorInfo("MethodArgumentNotValidException", "Validation failed"));
|
||||
}
|
||||
return ResponseEntity.badRequest().build();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.rest.controller;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.FieldError;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*
|
||||
*/
|
||||
|
||||
public class BindingErrorsResponse {
|
||||
|
||||
public BindingErrorsResponse() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public BindingErrorsResponse(Integer id) {
|
||||
this(null, id);
|
||||
}
|
||||
|
||||
public BindingErrorsResponse(Integer pathId, Integer bodyId) {
|
||||
boolean onlyBodyIdSpecified = pathId == null && bodyId != null;
|
||||
if (onlyBodyIdSpecified) {
|
||||
addBodyIdError(bodyId, "must not be specified");
|
||||
}
|
||||
boolean bothIdsSpecified = pathId != null && bodyId != null;
|
||||
if (bothIdsSpecified && !pathId.equals(bodyId)) {
|
||||
addBodyIdError(bodyId, String.format("does not match pathId: %d", pathId));
|
||||
}
|
||||
}
|
||||
|
||||
private void addBodyIdError(Integer bodyId, String message) {
|
||||
BindingError error = new BindingError();
|
||||
error.setObjectName("body");
|
||||
error.setFieldName("id");
|
||||
error.setFieldValue(bodyId.toString());
|
||||
error.setErrorMessage(message);
|
||||
addError(error);
|
||||
}
|
||||
|
||||
private final List<BindingError> bindingErrors = new ArrayList<BindingError>();
|
||||
|
||||
public void addError(BindingError bindingError) {
|
||||
this.bindingErrors.add(bindingError);
|
||||
}
|
||||
|
||||
public void addAllErrors(BindingResult bindingResult) {
|
||||
for (FieldError fieldError : bindingResult.getFieldErrors()) {
|
||||
BindingError error = new BindingError();
|
||||
error.setObjectName(fieldError.getObjectName());
|
||||
error.setFieldName(fieldError.getField());
|
||||
error.setFieldValue(String.valueOf(fieldError.getRejectedValue()));
|
||||
error.setErrorMessage(fieldError.getDefaultMessage());
|
||||
addError(error);
|
||||
}
|
||||
}
|
||||
|
||||
public String toJSON() {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
|
||||
String errorsAsJSON = "";
|
||||
try {
|
||||
errorsAsJSON = mapper.writeValueAsString(bindingErrors);
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return errorsAsJSON;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BindingErrorsResponse [bindingErrors=" + bindingErrors + "]";
|
||||
}
|
||||
|
||||
protected static class BindingError {
|
||||
|
||||
private String objectName;
|
||||
private String fieldName;
|
||||
private String fieldValue;
|
||||
private String errorMessage;
|
||||
|
||||
public BindingError() {
|
||||
this.objectName = "";
|
||||
this.fieldName = "";
|
||||
this.fieldValue = "";
|
||||
this.errorMessage = "";
|
||||
}
|
||||
|
||||
protected void setObjectName(String objectName) {
|
||||
this.objectName = objectName;
|
||||
}
|
||||
|
||||
protected void setFieldName(String fieldName) {
|
||||
this.fieldName = fieldName;
|
||||
}
|
||||
|
||||
protected void setFieldValue(String fieldValue) {
|
||||
this.fieldValue = fieldValue;
|
||||
}
|
||||
|
||||
protected void setErrorMessage(String error_message) {
|
||||
this.errorMessage = error_message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BindingError [objectName=" + objectName + ", fieldName=" + fieldName + ", fieldValue=" + fieldValue
|
||||
+ ", errorMessage=" + errorMessage + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.rest.controller;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.samples.petclinic.mapper.OwnerMapper;
|
||||
import org.springframework.samples.petclinic.mapper.PetMapper;
|
||||
import org.springframework.samples.petclinic.mapper.VisitMapper;
|
||||
import org.springframework.samples.petclinic.model.Owner;
|
||||
import org.springframework.samples.petclinic.model.Pet;
|
||||
import org.springframework.samples.petclinic.model.Visit;
|
||||
import org.springframework.samples.petclinic.rest.api.OwnersApi;
|
||||
import org.springframework.samples.petclinic.rest.dto.*;
|
||||
import org.springframework.samples.petclinic.service.ClinicService;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import jakarta.transaction.Transactional;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@CrossOrigin(exposedHeaders = "errors, content-type")
|
||||
@RequestMapping("/api")
|
||||
public class OwnerRestController implements OwnersApi {
|
||||
|
||||
private final ClinicService clinicService;
|
||||
|
||||
private final OwnerMapper ownerMapper;
|
||||
|
||||
private final PetMapper petMapper;
|
||||
|
||||
private final VisitMapper visitMapper;
|
||||
|
||||
public OwnerRestController(ClinicService clinicService,
|
||||
OwnerMapper ownerMapper,
|
||||
PetMapper petMapper,
|
||||
VisitMapper visitMapper) {
|
||||
this.clinicService = clinicService;
|
||||
this.ownerMapper = ownerMapper;
|
||||
this.petMapper = petMapper;
|
||||
this.visitMapper = visitMapper;
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<List<OwnerDto>> listOwners(String lastName) {
|
||||
Collection<Owner> owners;
|
||||
if (lastName != null) {
|
||||
owners = this.clinicService.findOwnerByLastName(lastName);
|
||||
} else {
|
||||
owners = this.clinicService.findAllOwners();
|
||||
}
|
||||
if (owners.isEmpty()) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return new ResponseEntity<>(ownerMapper.toOwnerDtoCollection(owners), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<OwnerDto> getOwner(Integer ownerId) {
|
||||
Owner owner = this.clinicService.findOwnerById(ownerId);
|
||||
if (owner == null) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return new ResponseEntity<>(ownerMapper.toOwnerDto(owner), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<OwnerDto> addOwner(OwnerFieldsDto ownerFieldsDto) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
Owner owner = ownerMapper.toOwner(ownerFieldsDto);
|
||||
this.clinicService.saveOwner(owner);
|
||||
OwnerDto ownerDto = ownerMapper.toOwnerDto(owner);
|
||||
headers.setLocation(UriComponentsBuilder.newInstance()
|
||||
.path("/api/owners/{id}").buildAndExpand(owner.getId()).toUri());
|
||||
return new ResponseEntity<>(ownerDto, headers, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<OwnerDto> updateOwner(Integer ownerId, OwnerFieldsDto ownerFieldsDto) {
|
||||
Owner currentOwner = this.clinicService.findOwnerById(ownerId);
|
||||
if (currentOwner == null) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
currentOwner.setAddress(ownerFieldsDto.getAddress());
|
||||
currentOwner.setCity(ownerFieldsDto.getCity());
|
||||
currentOwner.setFirstName(ownerFieldsDto.getFirstName());
|
||||
currentOwner.setLastName(ownerFieldsDto.getLastName());
|
||||
currentOwner.setTelephone(ownerFieldsDto.getTelephone());
|
||||
this.clinicService.saveOwner(currentOwner);
|
||||
return new ResponseEntity<>(ownerMapper.toOwnerDto(currentOwner), HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
|
||||
@Transactional
|
||||
@Override
|
||||
public ResponseEntity<OwnerDto> deleteOwner(Integer ownerId) {
|
||||
Owner owner = this.clinicService.findOwnerById(ownerId);
|
||||
if (owner == null) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
this.clinicService.deleteOwner(owner);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<PetDto> addPetToOwner(Integer ownerId, PetFieldsDto petFieldsDto) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
Pet pet = petMapper.toPet(petFieldsDto);
|
||||
Owner owner = new Owner();
|
||||
owner.setId(ownerId);
|
||||
pet.setOwner(owner);
|
||||
this.clinicService.savePet(pet);
|
||||
PetDto petDto = petMapper.toPetDto(pet);
|
||||
headers.setLocation(UriComponentsBuilder.newInstance().path("/api/pets/{id}")
|
||||
.buildAndExpand(pet.getId()).toUri());
|
||||
return new ResponseEntity<>(petDto, headers, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<VisitDto> addVisitToOwner(Integer ownerId, Integer petId, VisitFieldsDto visitFieldsDto) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
Visit visit = visitMapper.toVisit(visitFieldsDto);
|
||||
Pet pet = new Pet();
|
||||
pet.setId(petId);
|
||||
visit.setPet(pet);
|
||||
this.clinicService.saveVisit(visit);
|
||||
VisitDto visitDto = visitMapper.toVisitDto(visit);
|
||||
headers.setLocation(UriComponentsBuilder.newInstance().path("/api/visits/{id}")
|
||||
.buildAndExpand(visit.getId()).toUri());
|
||||
return new ResponseEntity<>(visitDto, headers, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
|
||||
@PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<PetDto> getOwnersPet(Integer ownerId, Integer petId) {
|
||||
Owner owner = this.clinicService.findOwnerById(ownerId);
|
||||
if (owner != null) {
|
||||
Pet pet = owner.getPet(petId);
|
||||
if (pet != null) {
|
||||
return new ResponseEntity<>(petMapper.toPetDto(pet), HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.rest.controller;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.samples.petclinic.mapper.PetMapper;
|
||||
import org.springframework.samples.petclinic.model.Pet;
|
||||
import org.springframework.samples.petclinic.rest.api.PetsApi;
|
||||
import org.springframework.samples.petclinic.rest.dto.PetDto;
|
||||
import org.springframework.samples.petclinic.service.ClinicService;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@CrossOrigin(exposedHeaders = "errors, content-type")
|
||||
@RequestMapping("api")
|
||||
public class PetRestController implements PetsApi {
|
||||
|
||||
private final ClinicService clinicService;
|
||||
|
||||
private final PetMapper petMapper;
|
||||
|
||||
public PetRestController(ClinicService clinicService, PetMapper petMapper) {
|
||||
this.clinicService = clinicService;
|
||||
this.petMapper = petMapper;
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<PetDto> getPet(Integer petId) {
|
||||
PetDto pet = petMapper.toPetDto(this.clinicService.findPetById(petId));
|
||||
if (pet == null) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return new ResponseEntity<>(pet, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<List<PetDto>> listPets() {
|
||||
List<PetDto> pets = new ArrayList<>(petMapper.toPetsDto(this.clinicService.findAllPets()));
|
||||
if (pets.isEmpty()) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return new ResponseEntity<>(pets, HttpStatus.OK);
|
||||
}
|
||||
|
||||
|
||||
@PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<PetDto> updatePet(Integer petId, PetDto petDto) {
|
||||
Pet currentPet = this.clinicService.findPetById(petId);
|
||||
if (currentPet == null) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
currentPet.setBirthDate(petDto.getBirthDate());
|
||||
currentPet.setName(petDto.getName());
|
||||
currentPet.setType(petMapper.toPetType(petDto.getType()));
|
||||
this.clinicService.savePet(currentPet);
|
||||
return new ResponseEntity<>(petMapper.toPetDto(currentPet), HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<PetDto> deletePet(Integer petId) {
|
||||
Pet pet = this.clinicService.findPetById(petId);
|
||||
if (pet == null) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
this.clinicService.deletePet(pet);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<PetDto> addPet(PetDto petDto) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
Pet pet = petMapper.toPet(petDto);
|
||||
this.clinicService.savePet(pet);
|
||||
headers.setLocation(UriComponentsBuilder.newInstance().path("/api/pets/{id}").buildAndExpand(pet.getId()).toUri());
|
||||
return new ResponseEntity<>(petMapper.toPetDto(pet), headers, HttpStatus.CREATED);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.rest.controller;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.samples.petclinic.mapper.PetTypeMapper;
|
||||
import org.springframework.samples.petclinic.model.PetType;
|
||||
import org.springframework.samples.petclinic.rest.api.PettypesApi;
|
||||
import org.springframework.samples.petclinic.rest.dto.PetTypeDto;
|
||||
import org.springframework.samples.petclinic.rest.dto.PetTypeFieldsDto;
|
||||
import org.springframework.samples.petclinic.service.ClinicService;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import jakarta.transaction.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@CrossOrigin(exposedHeaders = "errors, content-type")
|
||||
@RequestMapping("api")
|
||||
public class PetTypeRestController implements PettypesApi {
|
||||
|
||||
private final ClinicService clinicService;
|
||||
private final PetTypeMapper petTypeMapper;
|
||||
|
||||
|
||||
public PetTypeRestController(ClinicService clinicService, PetTypeMapper petTypeMapper) {
|
||||
this.clinicService = clinicService;
|
||||
this.petTypeMapper = petTypeMapper;
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyRole(@roles.OWNER_ADMIN, @roles.VET_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<List<PetTypeDto>> listPetTypes() {
|
||||
List<PetType> petTypes = new ArrayList<>(this.clinicService.findAllPetTypes());
|
||||
if (petTypes.isEmpty()) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return new ResponseEntity<>(petTypeMapper.toPetTypeDtos(petTypes), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyRole(@roles.OWNER_ADMIN, @roles.VET_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<PetTypeDto> getPetType(Integer petTypeId) {
|
||||
PetType petType = this.clinicService.findPetTypeById(petTypeId);
|
||||
if (petType == null) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return new ResponseEntity<>(petTypeMapper.toPetTypeDto(petType), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.VET_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<PetTypeDto> addPetType(PetTypeFieldsDto petTypeFieldsDto) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
final PetType type = petTypeMapper.toPetType(petTypeFieldsDto);
|
||||
this.clinicService.savePetType(type);
|
||||
headers.setLocation(UriComponentsBuilder.newInstance().path("/api/pettypes/{id}").buildAndExpand(type.getId()).toUri());
|
||||
return new ResponseEntity<>(petTypeMapper.toPetTypeDto(type), headers, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.VET_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<PetTypeDto> updatePetType(Integer petTypeId, PetTypeDto petTypeDto) {
|
||||
PetType currentPetType = this.clinicService.findPetTypeById(petTypeId);
|
||||
if (currentPetType == null) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
currentPetType.setName(petTypeDto.getName());
|
||||
this.clinicService.savePetType(currentPetType);
|
||||
return new ResponseEntity<>(petTypeMapper.toPetTypeDto(currentPetType), HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.VET_ADMIN)")
|
||||
@Transactional
|
||||
@Override
|
||||
public ResponseEntity<PetTypeDto> deletePetType(Integer petTypeId) {
|
||||
PetType petType = this.clinicService.findPetTypeById(petTypeId);
|
||||
if (petType == null) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
this.clinicService.deletePetType(petType);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright 2016-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.rest.controller;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@CrossOrigin(exposedHeaders = "errors, content-type")
|
||||
@RequestMapping("/")
|
||||
public class RootRestController {
|
||||
|
||||
@Value("#{servletContext.contextPath}")
|
||||
private String servletContextPath;
|
||||
|
||||
@RequestMapping(value = "/")
|
||||
public void redirectToSwagger(HttpServletResponse response) throws IOException {
|
||||
response.sendRedirect(this.servletContextPath + "/swagger-ui/index.html");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.rest.controller;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.samples.petclinic.mapper.SpecialtyMapper;
|
||||
import org.springframework.samples.petclinic.model.Specialty;
|
||||
import org.springframework.samples.petclinic.rest.api.SpecialtiesApi;
|
||||
import org.springframework.samples.petclinic.rest.dto.SpecialtyDto;
|
||||
import org.springframework.samples.petclinic.service.ClinicService;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import jakarta.transaction.Transactional;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@CrossOrigin(exposedHeaders = "errors, content-type")
|
||||
@RequestMapping("api")
|
||||
public class SpecialtyRestController implements SpecialtiesApi {
|
||||
|
||||
private final ClinicService clinicService;
|
||||
|
||||
private final SpecialtyMapper specialtyMapper;
|
||||
|
||||
public SpecialtyRestController(ClinicService clinicService, SpecialtyMapper specialtyMapper) {
|
||||
this.clinicService = clinicService;
|
||||
this.specialtyMapper = specialtyMapper;
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.VET_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<List<SpecialtyDto>> listSpecialties() {
|
||||
List<SpecialtyDto> specialties = new ArrayList<>();
|
||||
specialties.addAll(specialtyMapper.toSpecialtyDtos(this.clinicService.findAllSpecialties()));
|
||||
if (specialties.isEmpty()) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return new ResponseEntity<>(specialties, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.VET_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<SpecialtyDto> getSpecialty(Integer specialtyId) {
|
||||
Specialty specialty = this.clinicService.findSpecialtyById(specialtyId);
|
||||
if (specialty == null) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return new ResponseEntity<>(specialtyMapper.toSpecialtyDto(specialty), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.VET_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<SpecialtyDto> addSpecialty(SpecialtyDto specialtyDto) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
Specialty specialty = specialtyMapper.toSpecialty(specialtyDto);
|
||||
this.clinicService.saveSpecialty(specialty);
|
||||
headers.setLocation(UriComponentsBuilder.newInstance().path("/api/specialties/{id}").buildAndExpand(specialty.getId()).toUri());
|
||||
return new ResponseEntity<>(specialtyMapper.toSpecialtyDto(specialty), headers, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.VET_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<SpecialtyDto> updateSpecialty(Integer specialtyId, SpecialtyDto specialtyDto) {
|
||||
Specialty currentSpecialty = this.clinicService.findSpecialtyById(specialtyId);
|
||||
if (currentSpecialty == null) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
currentSpecialty.setName(specialtyDto.getName());
|
||||
this.clinicService.saveSpecialty(currentSpecialty);
|
||||
return new ResponseEntity<>(specialtyMapper.toSpecialtyDto(currentSpecialty), HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.VET_ADMIN)")
|
||||
@Transactional
|
||||
@Override
|
||||
public ResponseEntity<SpecialtyDto> deleteSpecialty(Integer specialtyId) {
|
||||
Specialty specialty = this.clinicService.findSpecialtyById(specialtyId);
|
||||
if (specialty == null) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
this.clinicService.deleteSpecialty(specialty);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.rest.controller;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.samples.petclinic.mapper.UserMapper;
|
||||
import org.springframework.samples.petclinic.model.User;
|
||||
import org.springframework.samples.petclinic.rest.api.UsersApi;
|
||||
import org.springframework.samples.petclinic.rest.dto.UserDto;
|
||||
import org.springframework.samples.petclinic.service.UserService;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
@RestController
|
||||
@CrossOrigin(exposedHeaders = "errors, content-type")
|
||||
@RequestMapping("api")
|
||||
public class UserRestController implements UsersApi {
|
||||
|
||||
private final UserService userService;
|
||||
private final UserMapper userMapper;
|
||||
|
||||
public UserRestController(UserService userService, UserMapper userMapper) {
|
||||
this.userService = userService;
|
||||
this.userMapper = userMapper;
|
||||
}
|
||||
|
||||
|
||||
@PreAuthorize( "hasRole(@roles.ADMIN)" )
|
||||
@Override
|
||||
public ResponseEntity<UserDto> addUser(UserDto userDto) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
User user = userMapper.toUser(userDto);
|
||||
this.userService.saveUser(user);
|
||||
return new ResponseEntity<>(userMapper.toUserDto(user), headers, HttpStatus.CREATED);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright 2016-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.rest.controller;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.samples.petclinic.mapper.SpecialtyMapper;
|
||||
import org.springframework.samples.petclinic.mapper.VetMapper;
|
||||
import org.springframework.samples.petclinic.model.Specialty;
|
||||
import org.springframework.samples.petclinic.model.Vet;
|
||||
import org.springframework.samples.petclinic.rest.api.VetsApi;
|
||||
import org.springframework.samples.petclinic.rest.dto.VetDto;
|
||||
import org.springframework.samples.petclinic.service.ClinicService;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import jakarta.transaction.Transactional;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@CrossOrigin(exposedHeaders = "errors, content-type")
|
||||
@RequestMapping("api")
|
||||
public class VetRestController implements VetsApi {
|
||||
|
||||
private final ClinicService clinicService;
|
||||
private final VetMapper vetMapper;
|
||||
private final SpecialtyMapper specialtyMapper;
|
||||
|
||||
public VetRestController(ClinicService clinicService, VetMapper vetMapper, SpecialtyMapper specialtyMapper) {
|
||||
this.clinicService = clinicService;
|
||||
this.vetMapper = vetMapper;
|
||||
this.specialtyMapper = specialtyMapper;
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.VET_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<List<VetDto>> listVets() {
|
||||
List<VetDto> vets = new ArrayList<>();
|
||||
vets.addAll(vetMapper.toVetDtos(this.clinicService.findAllVets()));
|
||||
if (vets.isEmpty()) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return new ResponseEntity<>(vets, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.VET_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<VetDto> getVet(Integer vetId) {
|
||||
Vet vet = this.clinicService.findVetById(vetId);
|
||||
if (vet == null) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return new ResponseEntity<>(vetMapper.toVetDto(vet), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.VET_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<VetDto> addVet(VetDto vetDto) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
Vet vet = vetMapper.toVet(vetDto);
|
||||
if(vet.getNrOfSpecialties() > 0){
|
||||
List<Specialty> vetSpecialities = this.clinicService.findSpecialtiesByNameIn(vet.getSpecialties().stream().map(Specialty::getName).collect(Collectors.toSet()));
|
||||
vet.setSpecialties(vetSpecialities);
|
||||
}
|
||||
this.clinicService.saveVet(vet);
|
||||
headers.setLocation(UriComponentsBuilder.newInstance().path("/api/vets/{id}").buildAndExpand(vet.getId()).toUri());
|
||||
return new ResponseEntity<>(vetMapper.toVetDto(vet), headers, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.VET_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<VetDto> updateVet(Integer vetId,VetDto vetDto) {
|
||||
Vet currentVet = this.clinicService.findVetById(vetId);
|
||||
if (currentVet == null) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
currentVet.setFirstName(vetDto.getFirstName());
|
||||
currentVet.setLastName(vetDto.getLastName());
|
||||
currentVet.clearSpecialties();
|
||||
for (Specialty spec : specialtyMapper.toSpecialtys(vetDto.getSpecialties())) {
|
||||
currentVet.addSpecialty(spec);
|
||||
}
|
||||
if(currentVet.getNrOfSpecialties() > 0){
|
||||
List<Specialty> vetSpecialities = this.clinicService.findSpecialtiesByNameIn(currentVet.getSpecialties().stream().map(Specialty::getName).collect(Collectors.toSet()));
|
||||
currentVet.setSpecialties(vetSpecialities);
|
||||
}
|
||||
this.clinicService.saveVet(currentVet);
|
||||
return new ResponseEntity<>(vetMapper.toVetDto(currentVet), HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.VET_ADMIN)")
|
||||
@Transactional
|
||||
@Override
|
||||
public ResponseEntity<VetDto> deleteVet(Integer vetId) {
|
||||
Vet vet = this.clinicService.findVetById(vetId);
|
||||
if (vet == null) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
this.clinicService.deleteVet(vet);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.rest.controller;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.samples.petclinic.mapper.VisitMapper;
|
||||
import org.springframework.samples.petclinic.model.Visit;
|
||||
import org.springframework.samples.petclinic.rest.api.VisitsApi;
|
||||
import org.springframework.samples.petclinic.rest.dto.VisitDto;
|
||||
import org.springframework.samples.petclinic.service.ClinicService;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import jakarta.transaction.Transactional;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@CrossOrigin(exposedHeaders = "errors, content-type")
|
||||
@RequestMapping("api")
|
||||
public class VisitRestController implements VisitsApi {
|
||||
|
||||
private final ClinicService clinicService;
|
||||
|
||||
private final VisitMapper visitMapper;
|
||||
|
||||
public VisitRestController(ClinicService clinicService, VisitMapper visitMapper) {
|
||||
this.clinicService = clinicService;
|
||||
this.visitMapper = visitMapper;
|
||||
}
|
||||
|
||||
|
||||
@PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<List<VisitDto>> listVisits() {
|
||||
List<Visit> visits = new ArrayList<>(this.clinicService.findAllVisits());
|
||||
if (visits.isEmpty()) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return new ResponseEntity<>(new ArrayList<>(visitMapper.toVisitsDto(visits)), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<VisitDto> getVisit( Integer visitId) {
|
||||
Visit visit = this.clinicService.findVisitById(visitId);
|
||||
if (visit == null) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return new ResponseEntity<>(visitMapper.toVisitDto(visit), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<VisitDto> addVisit(VisitDto visitDto) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
Visit visit = visitMapper.toVisit(visitDto);
|
||||
this.clinicService.saveVisit(visit);
|
||||
visitDto = visitMapper.toVisitDto(visit);
|
||||
headers.setLocation(UriComponentsBuilder.newInstance().path("/api/visits/{id}").buildAndExpand(visit.getId()).toUri());
|
||||
return new ResponseEntity<>(visitDto, headers, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
|
||||
@Override
|
||||
public ResponseEntity<VisitDto> updateVisit(Integer visitId, VisitDto visitDto) {
|
||||
Visit currentVisit = this.clinicService.findVisitById(visitId);
|
||||
if (currentVisit == null) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
currentVisit.setDate(visitDto.getDate());
|
||||
currentVisit.setDescription(visitDto.getDescription());
|
||||
this.clinicService.saveVisit(currentVisit);
|
||||
return new ResponseEntity<>(visitMapper.toVisitDto(currentVisit), HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole(@roles.OWNER_ADMIN)")
|
||||
@Transactional
|
||||
@Override
|
||||
public ResponseEntity<VisitDto> deleteVisit(Integer visitId) {
|
||||
Visit visit = this.clinicService.findVisitById(visitId);
|
||||
if (visit == null) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
this.clinicService.deleteVisit(visit);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
/**
|
||||
* The classes in this package represent PetClinic's REST API.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.rest;
|
|
@ -0,0 +1,58 @@
|
|||
package org.springframework.samples.petclinic.security;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Map;
|
||||
|
||||
@Configuration
|
||||
@EnableMethodSecurity(prePostEnabled = true) // Enable @PreAuthorize method-level security
|
||||
@ConditionalOnProperty(name = "petclinic.security.enable", havingValue = "true")
|
||||
public class BasicAuthenticationConfig {
|
||||
|
||||
@Autowired
|
||||
private DataSource dataSource;
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
var encoders = Map.of("noop", NoOpPasswordEncoder.getInstance());
|
||||
var passwordEncoder = new DelegatingPasswordEncoder("noop", encoders);
|
||||
passwordEncoder.setDefaultPasswordEncoderForMatches(NoOpPasswordEncoder.getInstance());
|
||||
return passwordEncoder;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
.authorizeHttpRequests((authz) -> authz
|
||||
.anyRequest().authenticated())
|
||||
.httpBasic(Customizer.withDefaults());
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// @formatter:off
|
||||
auth
|
||||
.jdbcAuthentication()
|
||||
.dataSource(dataSource)
|
||||
.usersByUsernameQuery("select username,password,enabled from users where username=?")
|
||||
.authoritiesByUsernameQuery("select username,role from roles where username=?");
|
||||
// @formatter:on
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package org.springframework.samples.petclinic.security;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
|
||||
/**
|
||||
* Starting from Spring Boot 2, if Spring Security is present, endpoints are secured by default
|
||||
* using Spring Security’s content-negotiation strategy.
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(name = "petclinic.security.enable", havingValue = "false")
|
||||
public class DisableSecurityConfig {
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
.authorizeHttpRequests((authz) -> authz
|
||||
.anyRequest().permitAll()
|
||||
);
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package org.springframework.samples.petclinic.security;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class Roles {
|
||||
|
||||
public final String OWNER_ADMIN = "ROLE_OWNER_ADMIN";
|
||||
public final String VET_ADMIN = "ROLE_VET_ADMIN";
|
||||
public final String ADMIN = "ROLE_ADMIN";
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.service;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.samples.petclinic.model.Owner;
|
||||
import org.springframework.samples.petclinic.model.Pet;
|
||||
import org.springframework.samples.petclinic.model.PetType;
|
||||
import org.springframework.samples.petclinic.model.Specialty;
|
||||
import org.springframework.samples.petclinic.model.Vet;
|
||||
import org.springframework.samples.petclinic.model.Visit;
|
||||
|
||||
/**
|
||||
* Mostly used as a facade so all controllers have a single point of entry
|
||||
*
|
||||
* @author Michael Isvy
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
public interface ClinicService {
|
||||
|
||||
Pet findPetById(int id) throws DataAccessException;
|
||||
Collection<Pet> findAllPets() throws DataAccessException;
|
||||
void savePet(Pet pet) throws DataAccessException;
|
||||
void deletePet(Pet pet) throws DataAccessException;
|
||||
|
||||
Collection<Visit> findVisitsByPetId(int petId);
|
||||
Visit findVisitById(int visitId) throws DataAccessException;
|
||||
Collection<Visit> findAllVisits() throws DataAccessException;
|
||||
void saveVisit(Visit visit) throws DataAccessException;
|
||||
void deleteVisit(Visit visit) throws DataAccessException;
|
||||
Vet findVetById(int id) throws DataAccessException;
|
||||
Collection<Vet> findVets() throws DataAccessException;
|
||||
Collection<Vet> findAllVets() throws DataAccessException;
|
||||
void saveVet(Vet vet) throws DataAccessException;
|
||||
void deleteVet(Vet vet) throws DataAccessException;
|
||||
Owner findOwnerById(int id) throws DataAccessException;
|
||||
Collection<Owner> findAllOwners() throws DataAccessException;
|
||||
void saveOwner(Owner owner) throws DataAccessException;
|
||||
void deleteOwner(Owner owner) throws DataAccessException;
|
||||
Collection<Owner> findOwnerByLastName(String lastName) throws DataAccessException;
|
||||
|
||||
PetType findPetTypeById(int petTypeId);
|
||||
Collection<PetType> findAllPetTypes() throws DataAccessException;
|
||||
Collection<PetType> findPetTypes() throws DataAccessException;
|
||||
void savePetType(PetType petType) throws DataAccessException;
|
||||
void deletePetType(PetType petType) throws DataAccessException;
|
||||
Specialty findSpecialtyById(int specialtyId);
|
||||
Collection<Specialty> findAllSpecialties() throws DataAccessException;
|
||||
void saveSpecialty(Specialty specialty) throws DataAccessException;
|
||||
void deleteSpecialty(Specialty specialty) throws DataAccessException;
|
||||
|
||||
List<Specialty> findSpecialtiesByNameIn(Set<String> names) throws DataAccessException;
|
||||
}
|
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.service;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.orm.ObjectRetrievalFailureException;
|
||||
import org.springframework.samples.petclinic.model.*;
|
||||
import org.springframework.samples.petclinic.repository.*;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Mostly used as a facade for all Petclinic controllers
|
||||
* Also a placeholder for @Transactional and @Cacheable annotations
|
||||
*
|
||||
* @author Michael Isvy
|
||||
* @author Vitaliy Fedoriv
|
||||
*/
|
||||
@Service
|
||||
public class ClinicServiceImpl implements ClinicService {
|
||||
|
||||
private final PetRepository petRepository;
|
||||
private final VetRepository vetRepository;
|
||||
private final OwnerRepository ownerRepository;
|
||||
private final VisitRepository visitRepository;
|
||||
private final SpecialtyRepository specialtyRepository;
|
||||
private final PetTypeRepository petTypeRepository;
|
||||
|
||||
@Autowired
|
||||
public ClinicServiceImpl(
|
||||
PetRepository petRepository,
|
||||
VetRepository vetRepository,
|
||||
OwnerRepository ownerRepository,
|
||||
VisitRepository visitRepository,
|
||||
SpecialtyRepository specialtyRepository,
|
||||
PetTypeRepository petTypeRepository) {
|
||||
this.petRepository = petRepository;
|
||||
this.vetRepository = vetRepository;
|
||||
this.ownerRepository = ownerRepository;
|
||||
this.visitRepository = visitRepository;
|
||||
this.specialtyRepository = specialtyRepository;
|
||||
this.petTypeRepository = petTypeRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Collection<Pet> findAllPets() throws DataAccessException {
|
||||
return petRepository.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void deletePet(Pet pet) throws DataAccessException {
|
||||
petRepository.delete(pet);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Visit findVisitById(int visitId) throws DataAccessException {
|
||||
return findEntityById(() -> visitRepository.findById(visitId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Collection<Visit> findAllVisits() throws DataAccessException {
|
||||
return visitRepository.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteVisit(Visit visit) throws DataAccessException {
|
||||
visitRepository.delete(visit);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Vet findVetById(int id) throws DataAccessException {
|
||||
return findEntityById(() -> vetRepository.findById(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Collection<Vet> findAllVets() throws DataAccessException {
|
||||
return vetRepository.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void saveVet(Vet vet) throws DataAccessException {
|
||||
vetRepository.save(vet);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteVet(Vet vet) throws DataAccessException {
|
||||
vetRepository.delete(vet);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Collection<Owner> findAllOwners() throws DataAccessException {
|
||||
return ownerRepository.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteOwner(Owner owner) throws DataAccessException {
|
||||
ownerRepository.delete(owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public PetType findPetTypeById(int petTypeId) {
|
||||
return findEntityById(() -> petTypeRepository.findById(petTypeId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Collection<PetType> findAllPetTypes() throws DataAccessException {
|
||||
return petTypeRepository.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void savePetType(PetType petType) throws DataAccessException {
|
||||
petTypeRepository.save(petType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void deletePetType(PetType petType) throws DataAccessException {
|
||||
petTypeRepository.delete(petType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Specialty findSpecialtyById(int specialtyId) {
|
||||
return findEntityById(() -> specialtyRepository.findById(specialtyId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Collection<Specialty> findAllSpecialties() throws DataAccessException {
|
||||
return specialtyRepository.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void saveSpecialty(Specialty specialty) throws DataAccessException {
|
||||
specialtyRepository.save(specialty);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteSpecialty(Specialty specialty) throws DataAccessException {
|
||||
specialtyRepository.delete(specialty);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Collection<PetType> findPetTypes() throws DataAccessException {
|
||||
return petRepository.findPetTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Owner findOwnerById(int id) throws DataAccessException {
|
||||
return findEntityById(() -> ownerRepository.findById(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Pet findPetById(int id) throws DataAccessException {
|
||||
return findEntityById(() -> petRepository.findById(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void savePet(Pet pet) throws DataAccessException {
|
||||
petRepository.save(pet);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void saveVisit(Visit visit) throws DataAccessException {
|
||||
visitRepository.save(visit);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Collection<Vet> findVets() throws DataAccessException {
|
||||
return vetRepository.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void saveOwner(Owner owner) throws DataAccessException {
|
||||
ownerRepository.save(owner);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Collection<Owner> findOwnerByLastName(String lastName) throws DataAccessException {
|
||||
return ownerRepository.findByLastName(lastName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Collection<Visit> findVisitsByPetId(int petId) {
|
||||
return visitRepository.findByPetId(petId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public List<Specialty> findSpecialtiesByNameIn(Set<String> names) {
|
||||
return findEntityById(() -> specialtyRepository.findSpecialtiesByNameIn(names));
|
||||
}
|
||||
|
||||
private <T> T findEntityById(Supplier<T> supplier) {
|
||||
try {
|
||||
return supplier.get();
|
||||
} catch (ObjectRetrievalFailureException | EmptyResultDataAccessException e) {
|
||||
// Just ignore not found exceptions for Jdbc/Jpa realization
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package org.springframework.samples.petclinic.service;
|
||||
|
||||
import org.springframework.samples.petclinic.model.User;
|
||||
|
||||
public interface UserService {
|
||||
|
||||
void saveUser(User user) ;
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package org.springframework.samples.petclinic.service;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.samples.petclinic.model.User;
|
||||
import org.springframework.samples.petclinic.model.Role;
|
||||
import org.springframework.samples.petclinic.repository.UserRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class UserServiceImpl implements UserService {
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void saveUser(User user) {
|
||||
|
||||
if(user.getRoles() == null || user.getRoles().isEmpty()) {
|
||||
throw new IllegalArgumentException("User must have at least a role set!");
|
||||
}
|
||||
|
||||
for (Role role : user.getRoles()) {
|
||||
if(!role.getName().startsWith("ROLE_")) {
|
||||
role.setName("ROLE_" + role.getName());
|
||||
}
|
||||
|
||||
if(role.getUser() == null) {
|
||||
role.setUser(user);
|
||||
}
|
||||
}
|
||||
|
||||
userRepository.save(user);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.samples.petclinic.util;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.jmx.export.annotation.ManagedAttribute;
|
||||
import org.springframework.jmx.export.annotation.ManagedOperation;
|
||||
import org.springframework.jmx.export.annotation.ManagedResource;
|
||||
import org.springframework.util.StopWatch;
|
||||
|
||||
/**
|
||||
* Simple aspect that monitors call count and call invocation time. It uses JMX annotations and therefore can be
|
||||
* monitored using any JMX console such as the jConsole
|
||||
* <p/>
|
||||
* This is only useful if you use JPA or JDBC. Spring-data-jpa doesn't have any correctly annotated classes to join on
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @author Michael Isvy
|
||||
* @since 2.5
|
||||
*/
|
||||
@ManagedResource("petclinic:type=CallMonitor")
|
||||
@Aspect
|
||||
public class CallMonitoringAspect {
|
||||
|
||||
private boolean enabled = true;
|
||||
|
||||
private int callCount = 0;
|
||||
|
||||
private long accumulatedCallTime = 0;
|
||||
|
||||
@ManagedAttribute
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
@ManagedAttribute
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
@ManagedOperation
|
||||
public void reset() {
|
||||
this.callCount = 0;
|
||||
this.accumulatedCallTime = 0;
|
||||
}
|
||||
|
||||
@ManagedAttribute
|
||||
public int getCallCount() {
|
||||
return callCount;
|
||||
}
|
||||
|
||||
@ManagedAttribute
|
||||
public long getCallTime() {
|
||||
if (this.callCount > 0)
|
||||
return this.accumulatedCallTime / this.callCount;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@Around("within(@org.springframework.stereotype.Repository *)")
|
||||
public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
if (this.enabled) {
|
||||
StopWatch sw = new StopWatch(joinPoint.toShortString());
|
||||
|
||||
sw.start("invoke");
|
||||
try {
|
||||
return joinPoint.proceed();
|
||||
} finally {
|
||||
sw.stop();
|
||||
synchronized (this) {
|
||||
this.callCount++;
|
||||
this.accumulatedCallTime += sw.getTotalTimeMillis();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return joinPoint.proceed();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.samples.petclinic.util;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.orm.ObjectRetrievalFailureException;
|
||||
import org.springframework.samples.petclinic.model.BaseEntity;
|
||||
|
||||
/**
|
||||
* Utility methods for handling entities. Separate from the BaseEntity class mainly because of dependency on the
|
||||
* ORM-associated ObjectRetrievalFailureException.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @see org.springframework.samples.petclinic.model.BaseEntity
|
||||
* @since 29.10.2003
|
||||
*/
|
||||
public abstract class EntityUtils {
|
||||
|
||||
/**
|
||||
* Look up the entity of the given class with the given id in the given collection.
|
||||
*
|
||||
* @param entities the collection to search
|
||||
* @param entityClass the entity class to look up
|
||||
* @param entityId the entity id to look up
|
||||
* @return the found entity
|
||||
* @throws ObjectRetrievalFailureException if the entity was not found
|
||||
*/
|
||||
public static <T extends BaseEntity> T getById(Collection<T> entities, Class<T> entityClass, int entityId)
|
||||
throws ObjectRetrievalFailureException {
|
||||
for (T entity : entities) {
|
||||
if (entity.getId() == entityId && entityClass.isInstance(entity)) {
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
throw new ObjectRetrievalFailureException(entityClass, entityId);
|
||||
}
|
||||
|
||||
}
|
8
backend/src/main/resources/application-hsqldb.properties
Normal file
8
backend/src/main/resources/application-hsqldb.properties
Normal file
|
@ -0,0 +1,8 @@
|
|||
# HSQLDB config start
|
||||
#----------------------------------------------------------------
|
||||
spring.datasource.url=jdbc:hsqldb:mem:petclinic
|
||||
spring.datasource.username=sa
|
||||
spring.datasource.password=
|
||||
spring.jpa.hibernate.ddl-auto=none
|
||||
#----------------------------------------------------------------
|
||||
# HSQLDB config end
|
7
backend/src/main/resources/application-mysql.properties
Normal file
7
backend/src/main/resources/application-mysql.properties
Normal file
|
@ -0,0 +1,7 @@
|
|||
# database init, supports mysql too
|
||||
database=mysql
|
||||
spring.datasource.url=${MYSQL_URL:jdbc:mysql://localhost/petclinic}
|
||||
spring.datasource.username=${MYSQL_USER:petclinic}
|
||||
spring.datasource.password=${MYSQL_PASS:petclinic}
|
||||
# SQL is written to be idempotent so this is safe
|
||||
spring.sql.init.mode=always
|
|
@ -0,0 +1,6 @@
|
|||
database=postgres
|
||||
spring.datasource.url=${POSTGRES_URL:jdbc:postgresql://localhost/petclinic}
|
||||
spring.datasource.username=${POSTGRES_USER:petclinic}
|
||||
spring.datasource.password=${POSTGRES_PASS:petclinic}
|
||||
# SQL is written to be idempotent so this is safe
|
||||
spring.sql.init.mode=always
|
44
backend/src/main/resources/application.properties
Normal file
44
backend/src/main/resources/application.properties
Normal file
|
@ -0,0 +1,44 @@
|
|||
# active profiles config
|
||||
#
|
||||
# application use two active profiles
|
||||
#
|
||||
# one - for select database
|
||||
# ------------------------------------------------
|
||||
# When using HSQL, use: hsqldb
|
||||
# When using MySQL, use: mysql
|
||||
# When using PostgeSQL, use: postgres
|
||||
# ------------------------------------------------
|
||||
#
|
||||
# one for select repository layer
|
||||
# ------------------------------------------------
|
||||
# When using Spring jpa, use: jpa
|
||||
# When using Spring JDBC, use: jdbc
|
||||
# When using Spring Data JPA, use: spring-data-jpa
|
||||
# ------------------------------------------------
|
||||
|
||||
spring.profiles.active=hsqldb,spring-data-jpa
|
||||
|
||||
# ------------------------------------------------
|
||||
|
||||
server.port=9966
|
||||
server.servlet.context-path=/petclinic/
|
||||
|
||||
# database init, supports mysql and postgres too
|
||||
database=hsqldb
|
||||
spring.sql.init.schema-locations=classpath*:db/${database}/schema.sql
|
||||
spring.sql.init.data-locations=classpath*:db/${database}/data.sql
|
||||
|
||||
|
||||
spring.messages.basename=messages/messages
|
||||
spring.jpa.open-in-view=false
|
||||
|
||||
logging.level.org.springframework=INFO
|
||||
#logging.level.org.springframework=DEBUG
|
||||
|
||||
#logging.level.org.hibernate.SQL=DEBUG
|
||||
#logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
|
||||
|
||||
# enable the desired authentication type
|
||||
# by default the authentication is disabled
|
||||
petclinic.security.enable=false
|
||||
|
59
backend/src/main/resources/db/hsqldb/data.sql
Normal file
59
backend/src/main/resources/db/hsqldb/data.sql
Normal file
|
@ -0,0 +1,59 @@
|
|||
INSERT INTO vets VALUES (1, 'James', 'Carter');
|
||||
INSERT INTO vets VALUES (2, 'Helen', 'Leary');
|
||||
INSERT INTO vets VALUES (3, 'Linda', 'Douglas');
|
||||
INSERT INTO vets VALUES (4, 'Rafael', 'Ortega');
|
||||
INSERT INTO vets VALUES (5, 'Henry', 'Stevens');
|
||||
INSERT INTO vets VALUES (6, 'Sharon', 'Jenkins');
|
||||
|
||||
INSERT INTO specialties VALUES (1, 'radiology');
|
||||
INSERT INTO specialties VALUES (2, 'surgery');
|
||||
INSERT INTO specialties VALUES (3, 'dentistry');
|
||||
|
||||
INSERT INTO vet_specialties VALUES (2, 1);
|
||||
INSERT INTO vet_specialties VALUES (3, 2);
|
||||
INSERT INTO vet_specialties VALUES (3, 3);
|
||||
INSERT INTO vet_specialties VALUES (4, 2);
|
||||
INSERT INTO vet_specialties VALUES (5, 1);
|
||||
|
||||
INSERT INTO types VALUES (1, 'cat');
|
||||
INSERT INTO types VALUES (2, 'dog');
|
||||
INSERT INTO types VALUES (3, 'lizard');
|
||||
INSERT INTO types VALUES (4, 'snake');
|
||||
INSERT INTO types VALUES (5, 'bird');
|
||||
INSERT INTO types VALUES (6, 'hamster');
|
||||
|
||||
INSERT INTO owners VALUES (1, 'George', 'Franklin', '110 W. Liberty St.', 'Madison', '6085551023');
|
||||
INSERT INTO owners VALUES (2, 'Betty', 'Davis', '638 Cardinal Ave.', 'Sun Prairie', '6085551749');
|
||||
INSERT INTO owners VALUES (3, 'Eduardo', 'Rodriquez', '2693 Commerce St.', 'McFarland', '6085558763');
|
||||
INSERT INTO owners VALUES (4, 'Harold', 'Davis', '563 Friendly St.', 'Windsor', '6085553198');
|
||||
INSERT INTO owners VALUES (5, 'Peter', 'McTavish', '2387 S. Fair Way', 'Madison', '6085552765');
|
||||
INSERT INTO owners VALUES (6, 'Jean', 'Coleman', '105 N. Lake St.', 'Monona', '6085552654');
|
||||
INSERT INTO owners VALUES (7, 'Jeff', 'Black', '1450 Oak Blvd.', 'Monona', '6085555387');
|
||||
INSERT INTO owners VALUES (8, 'Maria', 'Escobito', '345 Maple St.', 'Madison', '6085557683');
|
||||
INSERT INTO owners VALUES (9, 'David', 'Schroeder', '2749 Blackhawk Trail', 'Madison', '6085559435');
|
||||
INSERT INTO owners VALUES (10, 'Carlos', 'Estaban', '2335 Independence La.', 'Waunakee', '6085555487');
|
||||
|
||||
INSERT INTO pets VALUES (1, 'Leo', '2010-09-07', 1, 1);
|
||||
INSERT INTO pets VALUES (2, 'Basil', '2012-08-06', 6, 2);
|
||||
INSERT INTO pets VALUES (3, 'Rosy', '2011-04-17', 2, 3);
|
||||
INSERT INTO pets VALUES (4, 'Jewel', '2010-03-07', 2, 3);
|
||||
INSERT INTO pets VALUES (5, 'Iggy', '2010-11-30', 3, 4);
|
||||
INSERT INTO pets VALUES (6, 'George', '2010-01-20', 4, 5);
|
||||
INSERT INTO pets VALUES (7, 'Samantha', '2012-09-04', 1, 6);
|
||||
INSERT INTO pets VALUES (8, 'Max', '2012-09-04', 1, 6);
|
||||
INSERT INTO pets VALUES (9, 'Lucky', '2011-08-06', 5, 7);
|
||||
INSERT INTO pets VALUES (10, 'Mulligan', '2007-02-24', 2, 8);
|
||||
INSERT INTO pets VALUES (11, 'Freddy', '2010-03-09', 5, 9);
|
||||
INSERT INTO pets VALUES (12, 'Lucky', '2010-06-24', 2, 10);
|
||||
INSERT INTO pets VALUES (13, 'Sly', '2012-06-08', 1, 10);
|
||||
|
||||
INSERT INTO visits VALUES (1, 7, '2013-01-01', 'rabies shot');
|
||||
INSERT INTO visits VALUES (2, 8, '2013-01-02', 'rabies shot');
|
||||
INSERT INTO visits VALUES (3, 8, '2013-01-03', 'neutered');
|
||||
INSERT INTO visits VALUES (4, 7, '2013-01-04', 'spayed');
|
||||
|
||||
INSERT INTO users(username,password,enabled) VALUES ('admin','{noop}admin', true);
|
||||
|
||||
INSERT INTO roles (username, role) VALUES ('admin', 'ROLE_OWNER_ADMIN');
|
||||
INSERT INTO roles (username, role) VALUES ('admin', 'ROLE_VET_ADMIN');
|
||||
INSERT INTO roles (username, role) VALUES ('admin', 'ROLE_ADMIN');
|
82
backend/src/main/resources/db/hsqldb/schema.sql
Normal file
82
backend/src/main/resources/db/hsqldb/schema.sql
Normal file
|
@ -0,0 +1,82 @@
|
|||
DROP TABLE vet_specialties IF EXISTS;
|
||||
DROP TABLE vets IF EXISTS;
|
||||
DROP TABLE specialties IF EXISTS;
|
||||
DROP TABLE visits IF EXISTS;
|
||||
DROP TABLE pets IF EXISTS;
|
||||
DROP TABLE types IF EXISTS;
|
||||
DROP TABLE owners IF EXISTS;
|
||||
DROP TABLE roles IF EXISTS;
|
||||
DROP TABLE users IF EXISTS;
|
||||
|
||||
|
||||
CREATE TABLE vets (
|
||||
id INTEGER IDENTITY PRIMARY KEY,
|
||||
first_name VARCHAR(30),
|
||||
last_name VARCHAR(30)
|
||||
);
|
||||
CREATE INDEX vets_last_name ON vets (last_name);
|
||||
|
||||
CREATE TABLE specialties (
|
||||
id INTEGER IDENTITY PRIMARY KEY,
|
||||
name VARCHAR(80)
|
||||
);
|
||||
CREATE INDEX specialties_name ON specialties (name);
|
||||
|
||||
CREATE TABLE vet_specialties (
|
||||
vet_id INTEGER NOT NULL,
|
||||
specialty_id INTEGER NOT NULL
|
||||
);
|
||||
ALTER TABLE vet_specialties ADD CONSTRAINT fk_vet_specialties_vets FOREIGN KEY (vet_id) REFERENCES vets (id);
|
||||
ALTER TABLE vet_specialties ADD CONSTRAINT fk_vet_specialties_specialties FOREIGN KEY (specialty_id) REFERENCES specialties (id);
|
||||
|
||||
CREATE TABLE types (
|
||||
id INTEGER IDENTITY PRIMARY KEY,
|
||||
name VARCHAR(80)
|
||||
);
|
||||
CREATE INDEX types_name ON types (name);
|
||||
|
||||
CREATE TABLE owners (
|
||||
id INTEGER IDENTITY PRIMARY KEY,
|
||||
first_name VARCHAR(30),
|
||||
last_name VARCHAR_IGNORECASE(30),
|
||||
address VARCHAR(255),
|
||||
city VARCHAR(80),
|
||||
telephone VARCHAR(20)
|
||||
);
|
||||
CREATE INDEX owners_last_name ON owners (last_name);
|
||||
|
||||
CREATE TABLE pets (
|
||||
id INTEGER IDENTITY PRIMARY KEY,
|
||||
name VARCHAR(30),
|
||||
birth_date DATE,
|
||||
type_id INTEGER NOT NULL,
|
||||
owner_id INTEGER NOT NULL
|
||||
);
|
||||
ALTER TABLE pets ADD CONSTRAINT fk_pets_owners FOREIGN KEY (owner_id) REFERENCES owners (id);
|
||||
ALTER TABLE pets ADD CONSTRAINT fk_pets_types FOREIGN KEY (type_id) REFERENCES types (id);
|
||||
CREATE INDEX pets_name ON pets (name);
|
||||
|
||||
CREATE TABLE visits (
|
||||
id INTEGER IDENTITY PRIMARY KEY,
|
||||
pet_id INTEGER NOT NULL,
|
||||
visit_date DATE,
|
||||
description VARCHAR(255)
|
||||
);
|
||||
ALTER TABLE visits ADD CONSTRAINT fk_visits_pets FOREIGN KEY (pet_id) REFERENCES pets (id);
|
||||
CREATE INDEX visits_pet_id ON visits (pet_id);
|
||||
|
||||
CREATE TABLE users (
|
||||
username VARCHAR(20) NOT NULL ,
|
||||
password VARCHAR(20) NOT NULL ,
|
||||
enabled BOOLEAN DEFAULT TRUE NOT NULL ,
|
||||
PRIMARY KEY (username)
|
||||
);
|
||||
|
||||
CREATE TABLE roles (
|
||||
id INTEGER IDENTITY PRIMARY KEY,
|
||||
username VARCHAR(20) NOT NULL,
|
||||
role VARCHAR(20) NOT NULL
|
||||
);
|
||||
ALTER TABLE roles ADD CONSTRAINT fk_username FOREIGN KEY (username) REFERENCES users (username);
|
||||
CREATE INDEX fk_username_idx ON roles (username);
|
||||
|
59
backend/src/main/resources/db/mysql/data.sql
Normal file
59
backend/src/main/resources/db/mysql/data.sql
Normal file
|
@ -0,0 +1,59 @@
|
|||
INSERT IGNORE INTO vets VALUES (1, 'James', 'Carter');
|
||||
INSERT IGNORE INTO vets VALUES (2, 'Helen', 'Leary');
|
||||
INSERT IGNORE INTO vets VALUES (3, 'Linda', 'Douglas');
|
||||
INSERT IGNORE INTO vets VALUES (4, 'Rafael', 'Ortega');
|
||||
INSERT IGNORE INTO vets VALUES (5, 'Henry', 'Stevens');
|
||||
INSERT IGNORE INTO vets VALUES (6, 'Sharon', 'Jenkins');
|
||||
|
||||
INSERT IGNORE INTO specialties VALUES (1, 'radiology');
|
||||
INSERT IGNORE INTO specialties VALUES (2, 'surgery');
|
||||
INSERT IGNORE INTO specialties VALUES (3, 'dentistry');
|
||||
|
||||
INSERT IGNORE INTO vet_specialties VALUES (2, 1);
|
||||
INSERT IGNORE INTO vet_specialties VALUES (3, 2);
|
||||
INSERT IGNORE INTO vet_specialties VALUES (3, 3);
|
||||
INSERT IGNORE INTO vet_specialties VALUES (4, 2);
|
||||
INSERT IGNORE INTO vet_specialties VALUES (5, 1);
|
||||
|
||||
INSERT IGNORE INTO types VALUES (1, 'cat');
|
||||
INSERT IGNORE INTO types VALUES (2, 'dog');
|
||||
INSERT IGNORE INTO types VALUES (3, 'lizard');
|
||||
INSERT IGNORE INTO types VALUES (4, 'snake');
|
||||
INSERT IGNORE INTO types VALUES (5, 'bird');
|
||||
INSERT IGNORE INTO types VALUES (6, 'hamster');
|
||||
|
||||
INSERT IGNORE INTO owners VALUES (1, 'George', 'Franklin', '110 W. Liberty St.', 'Madison', '6085551023');
|
||||
INSERT IGNORE INTO owners VALUES (2, 'Betty', 'Davis', '638 Cardinal Ave.', 'Sun Prairie', '6085551749');
|
||||
INSERT IGNORE INTO owners VALUES (3, 'Eduardo', 'Rodriquez', '2693 Commerce St.', 'McFarland', '6085558763');
|
||||
INSERT IGNORE INTO owners VALUES (4, 'Harold', 'Davis', '563 Friendly St.', 'Windsor', '6085553198');
|
||||
INSERT IGNORE INTO owners VALUES (5, 'Peter', 'McTavish', '2387 S. Fair Way', 'Madison', '6085552765');
|
||||
INSERT IGNORE INTO owners VALUES (6, 'Jean', 'Coleman', '105 N. Lake St.', 'Monona', '6085552654');
|
||||
INSERT IGNORE INTO owners VALUES (7, 'Jeff', 'Black', '1450 Oak Blvd.', 'Monona', '6085555387');
|
||||
INSERT IGNORE INTO owners VALUES (8, 'Maria', 'Escobito', '345 Maple St.', 'Madison', '6085557683');
|
||||
INSERT IGNORE INTO owners VALUES (9, 'David', 'Schroeder', '2749 Blackhawk Trail', 'Madison', '6085559435');
|
||||
INSERT IGNORE INTO owners VALUES (10, 'Carlos', 'Estaban', '2335 Independence La.', 'Waunakee', '6085555487');
|
||||
|
||||
INSERT IGNORE INTO pets VALUES (1, 'Leo', '2000-09-07', 1, 1);
|
||||
INSERT IGNORE INTO pets VALUES (2, 'Basil', '2002-08-06', 6, 2);
|
||||
INSERT IGNORE INTO pets VALUES (3, 'Rosy', '2001-04-17', 2, 3);
|
||||
INSERT IGNORE INTO pets VALUES (4, 'Jewel', '2000-03-07', 2, 3);
|
||||
INSERT IGNORE INTO pets VALUES (5, 'Iggy', '2000-11-30', 3, 4);
|
||||
INSERT IGNORE INTO pets VALUES (6, 'George', '2000-01-20', 4, 5);
|
||||
INSERT IGNORE INTO pets VALUES (7, 'Samantha', '1995-09-04', 1, 6);
|
||||
INSERT IGNORE INTO pets VALUES (8, 'Max', '1995-09-04', 1, 6);
|
||||
INSERT IGNORE INTO pets VALUES (9, 'Lucky', '1999-08-06', 5, 7);
|
||||
INSERT IGNORE INTO pets VALUES (10, 'Mulligan', '1997-02-24', 2, 8);
|
||||
INSERT IGNORE INTO pets VALUES (11, 'Freddy', '2000-03-09', 5, 9);
|
||||
INSERT IGNORE INTO pets VALUES (12, 'Lucky', '2000-06-24', 2, 10);
|
||||
INSERT IGNORE INTO pets VALUES (13, 'Sly', '2002-06-08', 1, 10);
|
||||
|
||||
INSERT IGNORE INTO visits VALUES (1, 7, '2010-03-04', 'rabies shot');
|
||||
INSERT IGNORE INTO visits VALUES (2, 8, '2011-03-04', 'rabies shot');
|
||||
INSERT IGNORE INTO visits VALUES (3, 8, '2009-06-04', 'neutered');
|
||||
INSERT IGNORE INTO visits VALUES (4, 7, '2008-09-04', 'spayed');
|
||||
|
||||
INSERT IGNORE INTO users(username,password,enabled) VALUES ('admin','{noop}admin', true);
|
||||
|
||||
INSERT IGNORE INTO roles (username, role) VALUES ('admin', 'ROLE_OWNER_ADMIN');
|
||||
INSERT IGNORE INTO roles (username, role) VALUES ('admin', 'ROLE_VET_ADMIN');
|
||||
INSERT IGNORE INTO roles (username, role) VALUES ('admin', 'ROLE_ADMIN');
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue