diff --git a/ci/jpa-2.2-tck.Jenkinsfile b/ci/jpa-2.2-tck.Jenkinsfile new file mode 100644 index 0000000000..87e9aa7bab --- /dev/null +++ b/ci/jpa-2.2-tck.Jenkinsfile @@ -0,0 +1,72 @@ +@Library('hibernate-jenkins-pipeline-helpers@1.5') _ + +pipeline { + agent { + label 'LongDuration' + } + tools { + jdk 'OpenJDK 8 Latest' + } + stages { + stage('Build') { + steps { + script { + docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') { + docker.image('openjdk:8-jdk').pull() + } + } + dir('hibernate') { + checkout scm + sh """ \ + ./gradlew publishToMavenLocal + """ + script { + env.HIBERNATE_VERSION = sh ( + script: "grep hibernateVersion gradle/version.properties|cut -d'=' -f2", + returnStdout: true + ).trim() + } + } + dir('tck') { + checkout changelog: false, poll: false, scm: [$class: 'GitSCM', branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[url: 'https://github.com/hibernate/jakarta-tck-runner.git']]] + sh """ \ + cd jpa-2.2; docker build -t jakarta-tck-runner . + """ + } + } + } + stage('Run TCK') { + steps { + sh """ \ + docker rm -f tck || true + docker run -v ~/.m2/repository/org/hibernate:/root/.m2/repository/org/hibernate:z -e NO_SLEEP=true -e HIBERNATE_VERSION=$HIBERNATE_VERSION --name tck jakarta-tck-runner + docker cp tck:/tck/persistence-tck/tmp/JTreport/ ./JTreport + """ + archiveArtifacts artifacts: 'JTreport/**' + script { + failures = sh ( + script: """ \ + while read line; do + if [[ "\$line" != *"Passed." ]]; then + echo "\$line" + fi + done - - - - image/svg+xml - - - - - - + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + fill-opacity="1" + stroke="black" + stroke-linecap="square" + width="885" + stroke-miterlimit="10" + stroke-opacity="1" + fill="black" + stroke-dasharray="none" + stroke-width="1" + height="438" + font-family="'Dialog'" + font-size="12" + stroke-dashoffset="0" + version="1.1" + id="svg699" +> + id="genericDefs"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + id="g697"> + id="defs1"> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient5"> + stop-opacity="1" + stop-color="rgb(255,255,240)" + offset="0" + id="stop23"/> + stop-opacity="1" + stop-color="rgb(255,255,168)" + offset="1" + id="stop25"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient6"> + stop-opacity="1" + stop-color="rgb(255,255,240)" + offset="0" + id="stop28"/> + stop-opacity="1" + stop-color="rgb(255,255,168)" + offset="1" + id="stop30"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient7"> + stop-opacity="1" + stop-color="rgb(255,255,245)" + offset="0" + id="stop33"/> + stop-opacity="1" + stop-color="rgb(215,213,172)" + offset="1" + id="stop35"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient8"> + stop-opacity="1" + stop-color="rgb(255,255,245)" + offset="0" + id="stop38"/> + stop-opacity="1" + stop-color="rgb(215,213,172)" + offset="1" + id="stop40"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient9"> + stop-opacity="1" + stop-color="rgb(255,255,245)" + offset="0" + id="stop43"/> + stop-opacity="1" + stop-color="rgb(215,213,172)" + offset="1" + id="stop45"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient10"> + stop-opacity="1" + stop-color="rgb(255,255,245)" + offset="0" + id="stop48"/> + stop-opacity="1" + stop-color="rgb(215,213,172)" + offset="1" + id="stop50"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient13"> + stop-opacity="1" + stop-color="rgb(255,255,240)" + offset="0" + id="stop63"/> + stop-opacity="1" + stop-color="rgb(255,255,168)" + offset="1" + id="stop65"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient14"> + stop-opacity="1" + stop-color="rgb(255,255,240)" + offset="0" + id="stop68"/> + stop-opacity="1" + stop-color="rgb(255,255,168)" + offset="1" + id="stop70"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient15"> + stop-opacity="1" + stop-color="rgb(255,255,245)" + offset="0" + id="stop73"/> + stop-opacity="1" + stop-color="rgb(215,213,172)" + offset="1" + id="stop75"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient16"> + stop-opacity="1" + stop-color="rgb(255,255,245)" + offset="0" + id="stop78"/> + stop-opacity="1" + stop-color="rgb(215,213,172)" + offset="1" + id="stop80"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient17"> + stop-opacity="1" + stop-color="rgb(255,255,245)" + offset="0" + id="stop83"/> + stop-opacity="1" + stop-color="rgb(215,213,172)" + offset="1" + id="stop85"/> + x1="0" + gradientUnits="userSpaceOnUse" + x2="0" + y1="0" + y2="33" + id="linearGradient18"> + stop-opacity="1" + stop-color="rgb(255,255,245)" + offset="0" + id="stop88"/> + stop-opacity="1" + stop-color="rgb(215,213,172)" + offset="1" + id="stop90"/> - - - - - - - - - - - - - - - - - - - - - - - - - + + d="M-649 -37 L236 -37 L236 401 L-649 401 L-649 -37 Z" + id="path96"/> - + + d="M0 0 L0 37 L207 37 L207 0 Z" + id="path132"/> - + + d="M0 0 L0 35 L205 35 L205 0 Z" + id="path135"/> - + + d="M0 0 L0 33 L203 33 L203 0 Z" + id="path138"/> - + + d="M0 0 L0 25 L195 25 L195 0 Z" + id="path141"/> - + + d="M0 0 L0 37 L160 37 L160 0 Z" + id="path147"/> - + + d="M0 0 L0 35 L158 35 L158 0 Z" + id="path150"/> - + + d="M0 0 L0 33 L156 33 L156 0 Z" + id="path153"/> - + + d="M0 0 L0 25 L148 25 L148 0 Z" + id="path156"/> - + + d="M0 0 L0 37 L190 37 L190 0 Z" + id="path162"/> - + + d="M0 0 L0 35 L188 35 L188 0 Z" + id="path165"/> - + + d="M0 0 L0 33 L186 33 L186 0 Z" + id="path168"/> - + + d="M0 0 L0 25 L178 25 L178 0 Z" + id="path171"/> - + + d="M0 0 L0 37 L176 37 L176 0 Z" + id="path192"/> - + + d="M0 0 L0 35 L174 35 L174 0 Z" + id="path195"/> - + + d="M0 0 L0 33 L172 33 L172 0 Z" + id="path198"/> - + + d="M0 0 L0 25 L164 25 L164 0 Z" + id="path201"/> - + + d="M0 0 L0 37 L139 37 L139 0 Z" + id="path207"/> - + + d="M0 0 L0 35 L137 35 L137 0 Z" + id="path210"/> - + + d="M0 0 L0 33 L135 33 L135 0 Z" + id="path213"/> - + + d="M0 0 L0 25 L127 25 L127 0 Z" + id="path216"/> - + + d="M0 0 L0 37 L169 37 L169 0 Z" + id="path222"/> - + + d="M0 0 L0 35 L167 35 L167 0 Z" + id="path225"/> - + + d="M0 0 L0 33 L165 33 L165 0 Z" + id="path228"/> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + d="M0 0 L0 25 L157 25 L157 0 Z" + id="path231"/> + fill="white" + transform="translate(649,37)" + stroke="white" + id="g237"/> + + x="2" + width="205" + height="1" + y="36" + clip-path="url(#clipPath14)" + stroke="none" + id="rect335"/> + + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-627.5,104.5)" + stroke="rgb(232,232,232)" + id="g343"> - + x="0" + width="205" + height="35" + y="0" + clip-path="url(#clipPath15)" + stroke="none" + id="rect341"/> - - - + fill="silver" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-627.5,104.5)" + stroke="silver" + id="g347"> + d="M0 0 L205 0 L205 35 L0 35 L0 0 ZM1 1 L204 1 L204 34 L1 34 L1 1 Z" + fill-rule="evenodd" + clip-path="url(#clipPath15)" + stroke="none" + id="path345"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-626.5,105.5)" + stroke="rgb(232,232,232)" + id="g351"> + x="0" + width="203" + height="33" + y="0" + clip-path="url(#clipPath16)" + stroke="none" + id="rect349"/> + fill="url(#linearGradient5)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-626.5,105.5)" + stroke="url(#linearGradient5)" + id="g355"> + x="0" + width="203" + height="33" + y="0" + clip-path="url(#clipPath16)" + stroke="none" + id="rect353"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-622.5,109.5)" + id="g363"> + x="3" + y="3" + clip-path="url(#clipPath17)" + width="20" + height="20" + preserveAspectRatio="none" + id="image357" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> + x="23" + y="3" + clip-path="url(#clipPath17)" + width="20" + height="20" + preserveAspectRatio="none" + id="image359" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> EntityManager + x="47" + y="19" + clip-path="url(#clipPath17)" + stroke="none" + id="text361" + style="white-space: pre;">EntityManagerFactory + + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-626.5,105.5)" + stroke="rgb(232,232,232)" + id="g367"> + x="0" + width="203" + height="33" + y="0" + clip-path="url(#clipPath16)" + stroke="none" + id="rect365"/> + fill="url(#linearGradient6)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-626.5,105.5)" + stroke="url(#linearGradient6)" + id="g371"> + x="0" + width="203" + height="33" + y="0" + clip-path="url(#clipPath16)" + stroke="none" + id="rect369"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-622.5,109.5)" + id="g379"> + x="3" + y="3" + clip-path="url(#clipPath17)" + width="20" + height="20" + preserveAspectRatio="none" + id="image373" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> + x="23" + y="3" + clip-path="url(#clipPath17)" + width="20" + height="20" + preserveAspectRatio="none" + id="image375" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> EntityManager + x="47" + y="19" + clip-path="url(#clipPath17)" + stroke="none" + id="text377" + style="white-space: pre;">EntityManagerFactory + + fill="gray" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-605,-16.5)" + stroke="gray" + id="g385"> + x="2" + width="158" + height="1" + y="36" + clip-path="url(#clipPath19)" + stroke="none" + id="rect381"/> + x="159" + width="1" + height="35" + y="2" + clip-path="url(#clipPath19)" + stroke="none" + id="rect383"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-604,-15.5)" + stroke="rgb(232,232,232)" + id="g389"> + x="0" + width="158" + height="35" + y="0" + clip-path="url(#clipPath20)" + stroke="none" + id="rect387"/> + fill="silver" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-604,-15.5)" + stroke="silver" + id="g393"> + d="M0 0 L158 0 L158 35 L0 35 L0 0 ZM1 1 L157 1 L157 34 L1 34 L1 1 Z" + fill-rule="evenodd" + clip-path="url(#clipPath20)" + stroke="none" + id="path391"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-603,-14.5)" + stroke="rgb(232,232,232)" + id="g397"> + x="0" + width="156" + height="33" + y="0" + clip-path="url(#clipPath21)" + stroke="none" + id="rect395"/> + fill="url(#linearGradient7)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-603,-14.5)" + stroke="url(#linearGradient7)" + id="g401"> + x="0" + width="156" + height="33" + y="0" + clip-path="url(#clipPath21)" + stroke="none" + id="rect399"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-599,-10.5)" + id="g409"> + x="3" + y="3" + clip-path="url(#clipPath22)" + width="20" + height="20" + preserveAspectRatio="none" + id="image403" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> + x="23" + y="3" + clip-path="url(#clipPath22)" + width="20" + height="20" + preserveAspectRatio="none" + id="image405" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> Session + x="47" + y="19" + clip-path="url(#clipPath22)" + stroke="none" + id="text407" + style="white-space: pre;">SessionFactory + + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-603,-14.5)" + stroke="rgb(232,232,232)" + id="g413"> + x="0" + width="156" + height="33" + y="0" + clip-path="url(#clipPath21)" + stroke="none" + id="rect411"/> + fill="url(#linearGradient8)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-603,-14.5)" + stroke="url(#linearGradient8)" + id="g417"> + x="0" + width="156" + height="33" + y="0" + clip-path="url(#clipPath21)" + stroke="none" + id="rect415"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-599,-10.5)" + id="g425"> + x="3" + y="3" + clip-path="url(#clipPath22)" + width="20" + height="20" + preserveAspectRatio="none" + id="image419" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> + x="23" + y="3" + clip-path="url(#clipPath22)" + width="20" + height="20" + preserveAspectRatio="none" + id="image421" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> Session + x="47" + y="19" + clip-path="url(#clipPath22)" + stroke="none" + id="text423" + style="white-space: pre;">SessionFactory + + fill="gray" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-380,-16.5)" + stroke="gray" + id="g431"> + x="2" + width="188" + height="1" + y="36" + clip-path="url(#clipPath24)" + stroke="none" + id="rect427"/> + x="189" + width="1" + height="35" + y="2" + clip-path="url(#clipPath24)" + stroke="none" + id="rect429"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-379,-15.5)" + stroke="rgb(232,232,232)" + id="g435"> + x="0" + width="188" + height="35" + y="0" + clip-path="url(#clipPath25)" + stroke="none" + id="rect433"/> + fill="silver" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-379,-15.5)" + stroke="silver" + id="g439"> + d="M0 0 L188 0 L188 35 L0 35 L0 0 ZM1 1 L187 1 L187 34 L1 34 L1 1 Z" + fill-rule="evenodd" + clip-path="url(#clipPath25)" + stroke="none" + id="path437"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-378,-14.5)" + stroke="rgb(232,232,232)" + id="g443"> + x="0" + width="186" + height="33" + y="0" + clip-path="url(#clipPath26)" + stroke="none" + id="rect441"/> + fill="url(#linearGradient9)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-378,-14.5)" + stroke="url(#linearGradient9)" + id="g447"> + x="0" + width="186" + height="33" + y="0" + clip-path="url(#clipPath26)" + stroke="none" + id="rect445"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-374,-10.5)" + id="g457"> + x="3" + y="3" + clip-path="url(#clipPath27)" + width="20" + height="20" + preserveAspectRatio="none" + id="image449" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACrElEQVR42q1UXUgU URS+587sn4qZ6RZIqGSrYmRQSUVFKCT4UEFED5UUQfQQRI+SPQhFL0GJ9FAvldhD hKSGgZHarmRFUEQPKlmrlWgi5t+62+7ce7p3Z3eb62Kt4IVh7pw78813zne+Q8gq L1juABGh8tnIISR0FwHuNIM0BIS/6akp6AAATAnwwD2/k7rpMQ68CgkwgWIs+UQH ghpF2s0n+eOXZwpDywIe7PqYHjYyryEQV4rpBe2a6/Lz6g2BeEyzMmMux3UESFtB xeycR/aXnrzQO/ywickIjR/JNE1mqNQGNA3B5uCJCzRUK01cIWI/rjCU4fvDvy6J LVMIMITZ1ttlc50Ptgb6nm5a/ODN07Pc81q2O6QShSJ/y82OhoYGE9BXcfqwSNUj ttwKNnW3fo8x5s9N21n12eEpnxDs2ILvyRZX+b5v4HByC1No/jpDRloah/Too2wN wg1rmjOtTWVsajxr3dkrXlte0TwikwKOrzl6fgAjv+mSYhrI6W5xbzcP4n2WKKiO 4dGh9bp747Qtv2QuBmZySQaLHZgY9N8qclipU2jcASqOAfb84p/G5NjayOhgplVZ DCzoqtLxOpkYUVEKT1zMEKKUJkQRqjuLd0yFBt7lLr7t2syDAWTTE87ge2/ebNud irTtlX6w2y2iEJ1S7JaiRBlGvSnspPxRA8w5d7Xf4dn2PfSpvyDgbSsL/xjOya6t 80F6hrHEMVpPdUGHYr3KztFTDPjepEyE4lKkv3pGAFGtLSX0VW9NfrMiijS69Kbs UkU8xkAqm7gUMJAvB50k/CjJyyPtjYantq5PelPwtqU6HMjCYv2LIyXBJEC5vrTc iEijM6JnSjtJByjuiQkggjaRps9FIresYP8fsF1iwEoHxJpWtgZQ/loKsNyAXfX1 BxclLeZjw8WpAAAAAElFTkSuQmCC"/> + x="3" + y="3" + clip-path="url(#clipPath27)" + width="20" + height="20" + preserveAspectRatio="none" + id="image451" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAA2klEQVR42mNkgILa 3hn6/xkYJzIxMdn/+//v5CtuBttZ6em/GUgELCCiumdmGgMj40yG//8Z/v37x8DA yCDN/fUrSI50A0EuAxn2H2gYHPz//5D/86efDGQAJpA3kQ1jZmFh+P/9f3hDQ8M/ sgwEhRmyYf/+/tVh5GTUT5s5k5UsA0ERAAyzJ0B/Hv3z+ZfM////5Dm5eLaKfWbo J8dAZo0g34UMv79O5fr8dk5zXeknjWDfB+xffguxsLFlO7gFLDywc+MHBmqAhv75 CrUTZpozjIJRMApGJAAA4itU2q7mkFUAAAAASUVORK5CYII="/> + EntityManagerFactory + x="47" + y="19" + clip-path="url(#clipPath27)" + stroke="none" + id="text455" + style="white-space: pre;">SessionFactoryImpl + + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-378,-14.5)" + stroke="rgb(232,232,232)" + id="g461"> + x="0" + width="186" + height="33" + y="0" + clip-path="url(#clipPath26)" + stroke="none" + id="rect459"/> + fill="url(#linearGradient10)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-378,-14.5)" + stroke="url(#linearGradient10)" + id="g465"> + x="0" + width="186" + height="33" + y="0" + clip-path="url(#clipPath26)" + stroke="none" + id="rect463"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-374,-10.5)" + id="g475"> + x="3" + y="3" + clip-path="url(#clipPath27)" + width="20" + height="20" + preserveAspectRatio="none" + id="image467" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACrElEQVR42q1UXUgU URS+587sn4qZ6RZIqGSrYmRQSUVFKCT4UEFED5UUQfQQRI+SPQhFL0GJ9FAvldhD hKSGgZHarmRFUEQPKlmrlWgi5t+62+7ce7p3Z3eb62Kt4IVh7pw78813zne+Q8gq L1juABGh8tnIISR0FwHuNIM0BIS/6akp6AAATAnwwD2/k7rpMQ68CgkwgWIs+UQH ghpF2s0n+eOXZwpDywIe7PqYHjYyryEQV4rpBe2a6/Lz6g2BeEyzMmMux3UESFtB xeycR/aXnrzQO/ywickIjR/JNE1mqNQGNA3B5uCJCzRUK01cIWI/rjCU4fvDvy6J LVMIMITZ1ttlc50Ptgb6nm5a/ODN07Pc81q2O6QShSJ/y82OhoYGE9BXcfqwSNUj ttwKNnW3fo8x5s9N21n12eEpnxDs2ILvyRZX+b5v4HByC1No/jpDRloah/Too2wN wg1rmjOtTWVsajxr3dkrXlte0TwikwKOrzl6fgAjv+mSYhrI6W5xbzcP4n2WKKiO 4dGh9bp747Qtv2QuBmZySQaLHZgY9N8qclipU2jcASqOAfb84p/G5NjayOhgplVZ DCzoqtLxOpkYUVEKT1zMEKKUJkQRqjuLd0yFBt7lLr7t2syDAWTTE87ge2/ebNud irTtlX6w2y2iEJ1S7JaiRBlGvSnspPxRA8w5d7Xf4dn2PfSpvyDgbSsL/xjOya6t 80F6hrHEMVpPdUGHYr3KztFTDPjepEyE4lKkv3pGAFGtLSX0VW9NfrMiijS69Kbs UkU8xkAqm7gUMJAvB50k/CjJyyPtjYantq5PelPwtqU6HMjCYv2LIyXBJEC5vrTc iEijM6JnSjtJByjuiQkggjaRps9FIresYP8fsF1iwEoHxJpWtgZQ/loKsNyAXfX1 BxclLeZjw8WpAAAAAElFTkSuQmCC"/> + x="3" + y="3" + clip-path="url(#clipPath27)" + width="20" + height="20" + preserveAspectRatio="none" + id="image469" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAA2klEQVR42mNkgILa 3hn6/xkYJzIxMdn/+//v5CtuBttZ6em/GUgELCCiumdmGgMj40yG//8Z/v37x8DA yCDN/fUrSI50A0EuAxn2H2gYHPz//5D/86efDGQAJpA3kQ1jZmFh+P/9f3hDQ8M/ sgwEhRmyYf/+/tVh5GTUT5s5k5UsA0ERAAyzJ0B/Hv3z+ZfM////5Dm5eLaKfWbo J8dAZo0g34UMv79O5fr8dk5zXeknjWDfB+xffguxsLFlO7gFLDywc+MHBmqAhv75 CrUTZpozjIJRMApGJAAA4itU2q7mkFUAAAAASUVORK5CYII="/> + EntityManagerFactory + x="47" + y="19" + clip-path="url(#clipPath27)" + stroke="none" + id="text473" + style="white-space: pre;">SessionFactoryImpl + + fill="gray" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-613,343.5)" + stroke="gray" + id="g531"> + x="2" + width="174" + height="1" + y="36" + clip-path="url(#clipPath34)" + stroke="none" + id="rect527"/> + x="175" + width="1" + height="35" + y="2" + clip-path="url(#clipPath34)" + stroke="none" + id="rect529"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-612,344.5)" + stroke="rgb(232,232,232)" + id="g535"> + x="0" + width="174" + height="35" + y="0" + clip-path="url(#clipPath35)" + stroke="none" + id="rect533"/> + fill="silver" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-612,344.5)" + stroke="silver" + id="g539"> + d="M0 0 L174 0 L174 35 L0 35 L0 0 ZM1 1 L173 1 L173 34 L1 34 L1 1 Z" + fill-rule="evenodd" + clip-path="url(#clipPath35)" + stroke="none" + id="path537"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-611,345.5)" + stroke="rgb(232,232,232)" + id="g543"> + x="0" + width="172" + height="33" + y="0" + clip-path="url(#clipPath36)" + stroke="none" + id="rect541"/> + fill="url(#linearGradient13)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-611,345.5)" + stroke="url(#linearGradient13)" + id="g547"> + x="0" + width="172" + height="33" + y="0" + clip-path="url(#clipPath36)" + stroke="none" + id="rect545"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-607,349.5)" + id="g555"> + x="3" + y="3" + clip-path="url(#clipPath37)" + width="20" + height="20" + preserveAspectRatio="none" + id="image549" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> + x="23" + y="3" + clip-path="url(#clipPath37)" + width="20" + height="20" + preserveAspectRatio="none" + id="image551" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> SessionFactory + x="47" + y="19" + clip-path="url(#clipPath37)" + stroke="none" + id="text553" + style="white-space: pre;">EntityTransaction + + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-611,345.5)" + stroke="rgb(232,232,232)" + id="g559"> + x="0" + width="172" + height="33" + y="0" + clip-path="url(#clipPath36)" + stroke="none" + id="rect557"/> + fill="url(#linearGradient14)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-611,345.5)" + stroke="url(#linearGradient14)" + id="g563"> + x="0" + width="172" + height="33" + y="0" + clip-path="url(#clipPath36)" + stroke="none" + id="rect561"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-607,349.5)" + id="g571"> + x="3" + y="3" + clip-path="url(#clipPath37)" + width="20" + height="20" + preserveAspectRatio="none" + id="image565" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> + x="23" + y="3" + clip-path="url(#clipPath37)" + width="20" + height="20" + preserveAspectRatio="none" + id="image567" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> SessionFactory + x="47" + y="19" + clip-path="url(#clipPath37)" + stroke="none" + id="text569" + style="white-space: pre;">EntityTransaction + + fill="gray" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-594.5,223.5)" + stroke="gray" + id="g577"> + x="2" + width="137" + height="1" + y="36" + clip-path="url(#clipPath39)" + stroke="none" + id="rect573"/> + x="138" + width="1" + height="35" + y="2" + clip-path="url(#clipPath39)" + stroke="none" + id="rect575"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-593.5,224.5)" + stroke="rgb(232,232,232)" + id="g581"> + x="0" + width="137" + height="35" + y="0" + clip-path="url(#clipPath40)" + stroke="none" + id="rect579"/> + fill="silver" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-593.5,224.5)" + stroke="silver" + id="g585"> + d="M0 0 L137 0 L137 35 L0 35 L0 0 ZM1 1 L136 1 L136 34 L1 34 L1 1 Z" + fill-rule="evenodd" + clip-path="url(#clipPath40)" + stroke="none" + id="path583"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-592.5,225.5)" + stroke="rgb(232,232,232)" + id="g589"> + x="0" + width="135" + height="33" + y="0" + clip-path="url(#clipPath41)" + stroke="none" + id="rect587"/> + fill="url(#linearGradient15)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-592.5,225.5)" + stroke="url(#linearGradient15)" + id="g593"> + x="0" + width="135" + height="33" + y="0" + clip-path="url(#clipPath41)" + stroke="none" + id="rect591"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-588.5,229.5)" + id="g601"> + x="3" + y="3" + clip-path="url(#clipPath42)" + width="20" + height="20" + preserveAspectRatio="none" + id="image595" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> - + x="23" + y="3" + clip-path="url(#clipPath42)" + width="20" + height="20" + preserveAspectRatio="none" + id="image597" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> SessionFactoryImpl + x="47" + y="19" + clip-path="url(#clipPath42)" + stroke="none" + id="text599" + style="white-space: pre;">Transaction + + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-592.5,225.5)" + stroke="rgb(232,232,232)" + id="g605"> + x="0" + width="135" + height="33" + y="0" + clip-path="url(#clipPath41)" + stroke="none" + id="rect603"/> + fill="url(#linearGradient16)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-592.5,225.5)" + stroke="url(#linearGradient16)" + id="g609"> + x="0" + width="135" + height="33" + y="0" + clip-path="url(#clipPath41)" + stroke="none" + id="rect607"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-588.5,229.5)" + id="g617"> + x="3" + y="3" + clip-path="url(#clipPath42)" + width="20" + height="20" + preserveAspectRatio="none" + id="image611" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> - + x="23" + y="3" + clip-path="url(#clipPath42)" + width="20" + height="20" + preserveAspectRatio="none" + id="image613" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> SessionFactoryImpl + x="47" + y="19" + clip-path="url(#clipPath42)" + stroke="none" + id="text615" + style="white-space: pre;">Transaction + + fill="gray" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-369.5,223.5)" + stroke="gray" + id="g623"> + x="2" + width="167" + height="1" + y="36" + clip-path="url(#clipPath44)" + stroke="none" + id="rect619"/> + x="168" + width="1" + height="35" + y="2" + clip-path="url(#clipPath44)" + stroke="none" + id="rect621"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-368.5,224.5)" + stroke="rgb(232,232,232)" + id="g627"> + x="0" + width="167" + height="35" + y="0" + clip-path="url(#clipPath45)" + stroke="none" + id="rect625"/> + fill="silver" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-368.5,224.5)" + stroke="silver" + id="g631"> + d="M0 0 L167 0 L167 35 L0 35 L0 0 ZM1 1 L166 1 L166 34 L1 34 L1 1 Z" + fill-rule="evenodd" + clip-path="url(#clipPath45)" + stroke="none" + id="path629"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-367.5,225.5)" + stroke="rgb(232,232,232)" + id="g635"> + x="0" + width="165" + height="33" + y="0" + clip-path="url(#clipPath46)" + stroke="none" + id="rect633"/> + fill="url(#linearGradient17)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-367.5,225.5)" + stroke="url(#linearGradient17)" + id="g639"> + x="0" + width="165" + height="33" + y="0" + clip-path="url(#clipPath46)" + stroke="none" + id="rect637"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-363.5,229.5)" + id="g647"> + x="3" + y="3" + clip-path="url(#clipPath47)" + width="20" + height="20" + preserveAspectRatio="none" + id="image641" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACrElEQVR42q1UXUgU URS+587sn4qZ6RZIqGSrYmRQSUVFKCT4UEFED5UUQfQQRI+SPQhFL0GJ9FAvldhD hKSGgZHarmRFUEQPKlmrlWgi5t+62+7ce7p3Z3eb62Kt4IVh7pw78813zne+Q8gq L1juABGh8tnIISR0FwHuNIM0BIS/6akp6AAATAnwwD2/k7rpMQ68CgkwgWIs+UQH ghpF2s0n+eOXZwpDywIe7PqYHjYyryEQV4rpBe2a6/Lz6g2BeEyzMmMux3UESFtB xeycR/aXnrzQO/ywickIjR/JNE1mqNQGNA3B5uCJCzRUK01cIWI/rjCU4fvDvy6J LVMIMITZ1ttlc50Ptgb6nm5a/ODN07Pc81q2O6QShSJ/y82OhoYGE9BXcfqwSNUj ttwKNnW3fo8x5s9N21n12eEpnxDs2ILvyRZX+b5v4HByC1No/jpDRloah/Too2wN wg1rmjOtTWVsajxr3dkrXlte0TwikwKOrzl6fgAjv+mSYhrI6W5xbzcP4n2WKKiO 4dGh9bp747Qtv2QuBmZySQaLHZgY9N8qclipU2jcASqOAfb84p/G5NjayOhgplVZ DCzoqtLxOpkYUVEKT1zMEKKUJkQRqjuLd0yFBt7lLr7t2syDAWTTE87ge2/ebNud irTtlX6w2y2iEJ1S7JaiRBlGvSnspPxRA8w5d7Xf4dn2PfSpvyDgbSsL/xjOya6t 80F6hrHEMVpPdUGHYr3KztFTDPjepEyE4lKkv3pGAFGtLSX0VW9NfrMiijS69Kbs UkU8xkAqm7gUMJAvB50k/CjJyyPtjYantq5PelPwtqU6HMjCYv2LIyXBJEC5vrTc iEijM6JnSjtJByjuiQkggjaRps9FIresYP8fsF1iwEoHxJpWtgZQ/loKsNyAXfX1 BxclLeZjw8WpAAAAAElFTkSuQmCC"/> - + x="23" + y="3" + clip-path="url(#clipPath47)" + width="20" + height="20" + preserveAspectRatio="none" + id="image643" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> SessionImpl + x="47" + y="19" + clip-path="url(#clipPath47)" + stroke="none" + id="text645" + style="white-space: pre;">TransactionImpl + + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-367.5,225.5)" + stroke="rgb(232,232,232)" + id="g651"> + x="0" + width="165" + height="33" + y="0" + clip-path="url(#clipPath46)" + stroke="none" + id="rect649"/> + fill="url(#linearGradient18)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1,0,0,1,649,37) translate(-367.5,225.5)" + stroke="url(#linearGradient18)" + id="g655"> + x="0" + width="165" + height="33" + y="0" + clip-path="url(#clipPath46)" + stroke="none" + id="rect653"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1,0,0,1,649,37) translate(-363.5,229.5)" + id="g663"> + x="3" + y="3" + clip-path="url(#clipPath47)" + width="20" + height="20" + preserveAspectRatio="none" + id="image657" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACrElEQVR42q1UXUgU URS+587sn4qZ6RZIqGSrYmRQSUVFKCT4UEFED5UUQfQQRI+SPQhFL0GJ9FAvldhD hKSGgZHarmRFUEQPKlmrlWgi5t+62+7ce7p3Z3eb62Kt4IVh7pw78813zne+Q8gq L1juABGh8tnIISR0FwHuNIM0BIS/6akp6AAATAnwwD2/k7rpMQ68CgkwgWIs+UQH ghpF2s0n+eOXZwpDywIe7PqYHjYyryEQV4rpBe2a6/Lz6g2BeEyzMmMux3UESFtB xeycR/aXnrzQO/ywickIjR/JNE1mqNQGNA3B5uCJCzRUK01cIWI/rjCU4fvDvy6J LVMIMITZ1ttlc50Ptgb6nm5a/ODN07Pc81q2O6QShSJ/y82OhoYGE9BXcfqwSNUj ttwKNnW3fo8x5s9N21n12eEpnxDs2ILvyRZX+b5v4HByC1No/jpDRloah/Too2wN wg1rmjOtTWVsajxr3dkrXlte0TwikwKOrzl6fgAjv+mSYhrI6W5xbzcP4n2WKKiO 4dGh9bp747Qtv2QuBmZySQaLHZgY9N8qclipU2jcASqOAfb84p/G5NjayOhgplVZ DCzoqtLxOpkYUVEKT1zMEKKUJkQRqjuLd0yFBt7lLr7t2syDAWTTE87ge2/ebNud irTtlX6w2y2iEJ1S7JaiRBlGvSnspPxRA8w5d7Xf4dn2PfSpvyDgbSsL/xjOya6t 80F6hrHEMVpPdUGHYr3KztFTDPjepEyE4lKkv3pGAFGtLSX0VW9NfrMiijS69Kbs UkU8xkAqm7gUMJAvB50k/CjJyyPtjYantq5PelPwtqU6HMjCYv2LIyXBJEC5vrTc iEijM6JnSjtJByjuiQkggjaRps9FIresYP8fsF1iwEoHxJpWtgZQ/loKsNyAXfX1 BxclLeZjw8WpAAAAAElFTkSuQmCC"/> - + x="23" + y="3" + clip-path="url(#clipPath47)" + width="20" + height="20" + preserveAspectRatio="none" + id="image659" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> SessionImpl + x="47" + y="19" + clip-path="url(#clipPath47)" + stroke="none" + id="text661" + style="white-space: pre;">TransactionImpl + - - - - - - - + fill="rgb(0,130,0)" + stroke-miterlimit="1.45" + transform="matrix(1,0,0,1,649,37)" + stroke="rgb(0,130,0)" + id="g695"> + fill="none" + d="M-525 20.5405 L-525 92.4595" + clip-path="url(#clipPath2)" + id="path679"/> + + + + + + + + + + + + fill="gray" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 482.048981, 144.549438)" + stroke="gray" + id="g-1"> - - + x="2" + width="205" + height="1" + y="36" + clip-path="url(#clip-1)" + stroke="none" + id="rect-1"/> + x="206" + width="1" + height="35" + y="2" + clip-path="url(#clip-1)" + stroke="none" + id="rect-2"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 483.048981, 145.549438)" + stroke="rgb(232,232,232)" + id="g-2"> + + + + + + + + + + + + + x="3" + y="3" + clip-path="url(#clip-4)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-1" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> + x="23" + y="3" + clip-path="url(#clip-4)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-2" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> EntityTransaction + x="47" + y="19" + clip-path="url(#clip-4)" + stroke="none" + id="text-1" + style="white-space: pre;">EntityManagerFactory + + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 484.048981, 146.549438)" + stroke="rgb(232,232,232)" + id="g-7"> + x="0" + width="203" + height="33" + y="0" + clip-path="url(#clip-3)" + stroke="none" + id="rect-6"/> + fill="url(#gradient-2)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 484.048981, 146.549438)" + stroke="url(#gradient-2)" + id="g-8"> + x="0" + width="203" + height="33" + y="0" + clip-path="url(#clip-3)" + stroke="none" + id="rect-7"/> + font-family="'Segoe UI'" + font-size="15px" + transform="translate(504.04898,150.54944)" + id="g-9"> + x="3" + y="3" + clip-path="url(#clip-4)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-3" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> + x="23" + y="3" + clip-path="url(#clip-4)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-4" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> EntityTransaction + x="47" + y="19" + clip-path="url(#clip-4)" + stroke="none" + id="text-2" + style="white-space:pre">EntityManager + + fill="gray" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 505.548981, 24.549469)" + stroke="gray" + id="g-10"> + x="2" + width="158" + height="1" + y="36" + clip-path="url(#clip-5)" + stroke="none" + id="rect-8"/> + x="159" + width="1" + height="35" + y="2" + clip-path="url(#clip-5)" + stroke="none" + id="rect-9"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 506.548981, 25.549469)" + stroke="rgb(232,232,232)" + id="g-11"> + x="0" + width="158" + height="35" + y="0" + clip-path="url(#clip-6)" + stroke="none" + id="rect-10"/> + fill="silver" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 506.548981, 25.549469)" + stroke="silver" + id="g-12"> + d="M0 0 L158 0 L158 35 L0 35 L0 0 ZM1 1 L157 1 L157 34 L1 34 L1 1 Z" + fill-rule="evenodd" + clip-path="url(#clip-6)" + stroke="none" + id="path-14"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 507.548981, 26.549469)" + stroke="rgb(232,232,232)" + id="g-13"> + x="0" + width="156" + height="33" + y="0" + clip-path="url(#clip-7)" + stroke="none" + id="rect-11"/> + fill="url(#gradient-3)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 507.548981, 26.549469)" + stroke="url(#gradient-3)" + id="g-14"> + x="0" + width="156" + height="33" + y="0" + clip-path="url(#clip-7)" + stroke="none" + id="rect-12"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1, 0, 0, 1, 511.548981, 30.549469)" + id="g-15"> + x="3" + y="3" + clip-path="url(#clip-8)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-5" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> + x="23" + y="3" + clip-path="url(#clip-8)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-6" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> Transaction + x="47" + y="19" + clip-path="url(#clip-8)" + stroke="none" + id="text-3" + style="white-space: pre;">SessionFactory + + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 507.548981, 26.549469)" + stroke="rgb(232,232,232)" + id="g-16"> + x="0" + width="156" + height="33" + y="0" + clip-path="url(#clip-7)" + stroke="none" + id="rect-13"/> + fill="url(#gradient-4)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 507.548981, 26.549469)" + stroke="url(#gradient-4)" + id="g-17"> + x="0" + width="156" + height="33" + y="0" + clip-path="url(#clip-7)" + stroke="none" + id="rect-14"/> + font-family="'Segoe UI'" + font-size="15px" + transform="translate(531.54898,30.549469)" + id="g-18"> + x="3" + y="3" + clip-path="url(#clip-8)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-7" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACCklEQVR42q1UMUsc QRSeN7N72VOiBINwTbSQdJrCQgMpvAQJWMQqKIJwf8BOA0EDacRCCxttk3hBCHYW ghEVhGhCqmghIkgQgjaKYJZd73bnOW91l53bU068gQe7b95+++Z73zeMVXnBTRuo 9kbWBt4gYqdgzKKcz5gLAD8nX84vQlBSAWBuPWc1SvetRPYKAgzmlZQYyEBwwNUa bi18zH52bwQcXh6sBeGNq5+nKzygg74xOvU6b4cZHu+MwBCwplK+qJa+GdofepAA pGNSZ4A6NyLFZTy0/oJaTFt/T/oiPqIBXHF2Ef/ArDW8lfd/eoTJAx79ojS6J54t FW3P0FrlMqsw8jQoQe/22kAvID5Vj1oHUiLwFHfO/zmPQIBs7mrcrc+kbcTEMOF7 ro1tftnZC45M0igzTdUSwpOOhqPUQ8OhoGepcmXo9BjK5xGHoc7uJWgESxtKtRYP HXBfICUhNwIkO4UT15YAPPx9mimce2mKw18nGa5yZfAMBnwrAiRvkp1Kq0xL+AfL R62y4JsUByvHrULlyvheEIZmvXer/YNKDi8STZaI2S/IJO/If0x2z89pQyGjB94E XWMEEA+dN1UL4LjNDd+qczkoMJt7Y7PZhf/RieL7m1+3i+0fsuvGmVvHOLZc/1Am ry9mAvINt+nx9Ez7J+dOFyw5IBRtIA01zdsu2KqvS/ZN5gVE2Ks6AAAAAElFTkSu QmCC"/> + x="23" + y="3" + clip-path="url(#clip-8)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-8" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42u2Uv0oD QRDGZ3Y9Q/6ghdhZ26RMKVhoEYxaay8GrHyFe4lUIUlhr4WKEomgD+Az+ABWipFc LvM5e96ByIWsnUIGjtmbvfn43TfLEs3jzwXnFY+utzbB3CQgIOYxyLR7jbsHH0GT V3Rihum227g/dJlJjn0JcwUd2cjYC+WHiUvnCalnLEzbKEYFuBxV3hbt0Cbr5uV+ yeXyyguW+/VRGIbi5+HN9lVk7EEg4zUGn4LYKnZASJuYAdBTd3fQmv3L2t3ZGeyd 1fvvKrb+JZYYKylCrLqxFjb8POSMg0jA6RoBs/TKXDjRD55TTPmVhz/GLjCmOkS0 qi9LU5yaLWiUMIFkmuika/hmu9oo/scmA5t8PILwqrIVN9zsUbGiwHbm98I/iU+D oGuHyXAGnwAAAABJRU5ErkJggg=="/> Transaction + x="47" + y="19" + clip-path="url(#clip-8)" + stroke="none" + id="text-4" + style="white-space:pre">Session + + fill="gray" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 730.54895, 24.549469)" + stroke="gray" + id="g-19"> + x="2" + width="188" + height="1" + y="36" + clip-path="url(#clip-9)" + stroke="none" + id="rect-15"/> + x="189" + width="1" + height="35" + y="2" + clip-path="url(#clip-9)" + stroke="none" + id="rect-16"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 731.54895, 25.549469)" + stroke="rgb(232,232,232)" + id="g-20"> + x="0" + width="188" + height="35" + y="0" + clip-path="url(#clip-10)" + stroke="none" + id="rect-17"/> + fill="silver" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 731.54895, 25.549469)" + stroke="silver" + id="g-21"> + d="M0 0 L188 0 L188 35 L0 35 L0 0 ZM1 1 L187 1 L187 34 L1 34 L1 1 Z" + fill-rule="evenodd" + clip-path="url(#clip-10)" + stroke="none" + id="path-15"/> + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 732.54895, 26.549469)" + stroke="rgb(232,232,232)" + id="g-22"> + x="0" + width="186" + height="33" + y="0" + clip-path="url(#clip-11)" + stroke="none" + id="rect-18"/> + fill="url(#gradient-5)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 732.54895, 26.549469)" + stroke="url(#gradient-5)" + id="g-23"> + x="0" + width="186" + height="33" + y="0" + clip-path="url(#clip-11)" + stroke="none" + id="rect-19"/> + font-family="'Segoe UI'" + font-size="15" + transform="matrix(1, 0, 0, 1, 736.54895, 30.549469)" + id="g-24"> + x="3" + y="3" + clip-path="url(#clip-12)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-9" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACrElEQVR42q1UXUgU URS+587sn4qZ6RZIqGSrYmRQSUVFKCT4UEFED5UUQfQQRI+SPQhFL0GJ9FAvldhD hKSGgZHarmRFUEQPKlmrlWgi5t+62+7ce7p3Z3eb62Kt4IVh7pw78813zne+Q8gq L1juABGh8tnIISR0FwHuNIM0BIS/6akp6AAATAnwwD2/k7rpMQ68CgkwgWIs+UQH ghpF2s0n+eOXZwpDywIe7PqYHjYyryEQV4rpBe2a6/Lz6g2BeEyzMmMux3UESFtB xeycR/aXnrzQO/ywickIjR/JNE1mqNQGNA3B5uCJCzRUK01cIWI/rjCU4fvDvy6J LVMIMITZ1ttlc50Ptgb6nm5a/ODN07Pc81q2O6QShSJ/y82OhoYGE9BXcfqwSNUj ttwKNnW3fo8x5s9N21n12eEpnxDs2ILvyRZX+b5v4HByC1No/jpDRloah/Too2wN wg1rmjOtTWVsajxr3dkrXlte0TwikwKOrzl6fgAjv+mSYhrI6W5xbzcP4n2WKKiO 4dGh9bp747Qtv2QuBmZySQaLHZgY9N8qclipU2jcASqOAfb84p/G5NjayOhgplVZ DCzoqtLxOpkYUVEKT1zMEKKUJkQRqjuLd0yFBt7lLr7t2syDAWTTE87ge2/ebNud irTtlX6w2y2iEJ1S7JaiRBlGvSnspPxRA8w5d7Xf4dn2PfSpvyDgbSsL/xjOya6t 80F6hrHEMVpPdUGHYr3KztFTDPjepEyE4lKkv3pGAFGtLSX0VW9NfrMiijS69Kbs UkU8xkAqm7gUMJAvB50k/CjJyyPtjYantq5PelPwtqU6HMjCYv2LIyXBJEC5vrTc iEijM6JnSjtJByjuiQkggjaRps9FIresYP8fsF1iwEoHxJpWtgZQ/loKsNyAXfX1 BxclLeZjw8WpAAAAAElFTkSuQmCC"/> + x="3" + y="3" + clip-path="url(#clip-12)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-10" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAA2klEQVR42mNkgILa 3hn6/xkYJzIxMdn/+//v5CtuBttZ6em/GUgELCCiumdmGgMj40yG//8Z/v37x8DA yCDN/fUrSI50A0EuAxn2H2gYHPz//5D/86efDGQAJpA3kQ1jZmFh+P/9f3hDQ8M/ sgwEhRmyYf/+/tVh5GTUT5s5k5UsA0ERAAyzJ0B/Hv3z+ZfM////5Dm5eLaKfWbo J8dAZo0g34UMv79O5fr8dk5zXeknjWDfB+xffguxsLFlO7gFLDywc+MHBmqAhv75 CrUTZpozjIJRMApGJAAA4itU2q7mkFUAAAAASUVORK5CYII="/> + TransactionImpl + x="47" + y="19" + clip-path="url(#clip-12)" + stroke="none" + id="text-5" + style="white-space: pre;">SessionFactoryImpl + + fill="rgb(232,232,232)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 732.54895, 26.549469)" + stroke="rgb(232,232,232)" + id="g-25"> + x="0" + width="186" + height="33" + y="0" + clip-path="url(#clip-11)" + stroke="none" + id="rect-20"/> + fill="url(#gradient-6)" + font-size="15" + font-family="'Segoe UI'" + transform="matrix(1, 0, 0, 1, 732.54895, 26.549469)" + stroke="url(#gradient-6)" + id="g-26"> + x="0" + width="186" + height="33" + y="0" + clip-path="url(#clip-11)" + stroke="none" + id="rect-21"/> + font-family="'Segoe UI'" + font-size="15px" + transform="translate(745.54895,30.549469)" + id="g-27"> + x="3" + y="3" + clip-path="url(#clip-12)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-12" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACrElEQVR42q1UXUgU URS+587sn4qZ6RZIqGSrYmRQSUVFKCT4UEFED5UUQfQQRI+SPQhFL0GJ9FAvldhD hKSGgZHarmRFUEQPKlmrlWgi5t+62+7ce7p3Z3eb62Kt4IVh7pw78813zne+Q8gq L1juABGh8tnIISR0FwHuNIM0BIS/6akp6AAATAnwwD2/k7rpMQ68CgkwgWIs+UQH ghpF2s0n+eOXZwpDywIe7PqYHjYyryEQV4rpBe2a6/Lz6g2BeEyzMmMux3UESFtB xeycR/aXnrzQO/ywickIjR/JNE1mqNQGNA3B5uCJCzRUK01cIWI/rjCU4fvDvy6J LVMIMITZ1ttlc50Ptgb6nm5a/ODN07Pc81q2O6QShSJ/y82OhoYGE9BXcfqwSNUj ttwKNnW3fo8x5s9N21n12eEpnxDs2ILvyRZX+b5v4HByC1No/jpDRloah/Too2wN wg1rmjOtTWVsajxr3dkrXlte0TwikwKOrzl6fgAjv+mSYhrI6W5xbzcP4n2WKKiO 4dGh9bp747Qtv2QuBmZySQaLHZgY9N8qclipU2jcASqOAfb84p/G5NjayOhgplVZ DCzoqtLxOpkYUVEKT1zMEKKUJkQRqjuLd0yFBt7lLr7t2syDAWTTE87ge2/ebNud irTtlX6w2y2iEJ1S7JaiRBlGvSnspPxRA8w5d7Xf4dn2PfSpvyDgbSsL/xjOya6t 80F6hrHEMVpPdUGHYr3KztFTDPjepEyE4lKkv3pGAFGtLSX0VW9NfrMiijS69Kbs UkU8xkAqm7gUMJAvB50k/CjJyyPtjYantq5PelPwtqU6HMjCYv2LIyXBJEC5vrTc iEijM6JnSjtJByjuiQkggjaRps9FIresYP8fsF1iwEoHxJpWtgZQ/loKsNyAXfX1 BxclLeZjw8WpAAAAAElFTkSuQmCC"/> + x="3" + y="3" + clip-path="url(#clip-12)" + width="20" + height="20" + preserveAspectRatio="none" + id="image-13" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAA2klEQVR42mNkgILa 3hn6/xkYJzIxMdn/+//v5CtuBttZ6em/GUgELCCiumdmGgMj40yG//8Z/v37x8DA yCDN/fUrSI50A0EuAxn2H2gYHPz//5D/86efDGQAJpA3kQ1jZmFh+P/9f3hDQ8M/ sgwEhRmyYf/+/tVh5GTUT5s5k5UsA0ERAAyzJ0B/Hv3z+ZfM////5Dm5eLaKfWbo J8dAZo0g34UMv79O5fr8dk5zXeknjWDfB+xffguxsLFlO7gFLDywc+MHBmqAhv75 CrUTZpozjIJRMApGJAAA4itU2q7mkFUAAAAASUVORK5CYII="/> + TransactionImpl - - - - - - - - - - - - - - - - - - + x="47" + y="19" + clip-path="url(#clip-12)" + stroke="none" + id="text-6" + style="white-space:pre">SessionImpl + diff --git a/documentation/src/test/java/org/hibernate/userguide/inheritance/DiscriminatorNotNullSingleTableTest.java b/documentation/src/test/java/org/hibernate/userguide/inheritance/DiscriminatorNotNullSingleTableTest.java index 2c3bbf9ef3..16a503ef57 100644 --- a/documentation/src/test/java/org/hibernate/userguide/inheritance/DiscriminatorNotNullSingleTableTest.java +++ b/documentation/src/test/java/org/hibernate/userguide/inheritance/DiscriminatorNotNullSingleTableTest.java @@ -45,12 +45,6 @@ public class DiscriminatorNotNullSingleTableTest extends BaseEntityManagerFuncti @Test public void test() { doInJPA( this::entityManagerFactory, entityManager -> { - entityManager.unwrap( Session.class ).doWork( connection -> { - try(Statement statement = connection.createStatement()) { - statement.executeUpdate( "ALTER TABLE Account ALTER COLUMN DTYPE SET NULL" ); - } - } ); - //tag::entity-inheritance-single-table-discriminator-value-persist-example[] DebitAccount debitAccount = new DebitAccount(); debitAccount.setId( 1L ); diff --git a/gradle.properties b/gradle.properties index b8ec248b50..a20f3a1cb4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,6 @@ # Keep all these properties in sync unless you know what you are doing! org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=256m -XX:+HeapDumpOnOutOfMemoryError -Duser.language=en -Duser.country=US -Duser.timezone=UTC -Dfile.encoding=UTF-8 -# Needs add-opens because of https://github.com/gradle/gradle/issues/15538 -toolchain.compiler.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=256m -XX:+HeapDumpOnOutOfMemoryError -Duser.language=en -Duser.country=US -Duser.timezone=UTC -Dfile.encoding=UTF-8 --add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED +toolchain.compiler.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=256m -XX:+HeapDumpOnOutOfMemoryError -Duser.language=en -Duser.country=US -Duser.timezone=UTC -Dfile.encoding=UTF-8 toolchain.javadoc.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=256m -XX:+HeapDumpOnOutOfMemoryError -Duser.language=en -Duser.country=US -Duser.timezone=UTC -Dfile.encoding=UTF-8 toolchain.launcher.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=256m -XX:+HeapDumpOnOutOfMemoryError -Duser.language=en -Duser.country=US -Duser.timezone=UTC -Dfile.encoding=UTF-8 diff --git a/gradle/base-information.gradle b/gradle/base-information.gradle index b2e2aade03..ca5f459cb2 100644 --- a/gradle/base-information.gradle +++ b/gradle/base-information.gradle @@ -19,6 +19,7 @@ ext { } jpaVersion = new JpaVersion('2.2') + jakartaJpaVersion = new JpaVersion('3.0.0') } group = 'org.hibernate.orm' diff --git a/gradle/java-module.gradle b/gradle/java-module.gradle index 828d450a1e..83efde0991 100644 --- a/gradle/java-module.gradle +++ b/gradle/java-module.gradle @@ -158,6 +158,8 @@ else { options.compilerArgs << gradle.ext.javaVersions.main.release.toString() } else { options.release = gradle.ext.javaVersions.main.release.asInt() + // Needs add-opens because of https://github.com/gradle/gradle/issues/15538 + options.forkOptions.jvmArgs.addAll( ["--add-opens", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED"] ) } } tasks.compileTestJava.configure { @@ -168,6 +170,8 @@ else { options.compilerArgs << gradle.ext.javaVersions.test.release.toString() } else { options.release = gradle.ext.javaVersions.test.release.asInt() + // Needs add-opens because of https://github.com/gradle/gradle/issues/15538 + options.forkOptions.jvmArgs.addAll( ["--add-opens", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED"] ) } } diff --git a/gradle/libraries.gradle b/gradle/libraries.gradle index 0d1267d78c..d38b5abc4d 100644 --- a/gradle/libraries.gradle +++ b/gradle/libraries.gradle @@ -21,12 +21,14 @@ ext { hibernateValidatorVersion = '6.1.6.Final' validationApiVersion = '2.0.1.Final' elVersion = '3.0.1-b09' + hibernateValidatorJakartaVersion = '7.0.1.Final' cdiVersion = '2.0' weldVersion = '3.1.5.Final' + jakartaWeldVersion = '4.0.1.SP1' javassistVersion = '3.27.0-GA' - byteBuddyVersion = '1.10.21' + byteBuddyVersion = '1.10.22' agroalVersion = '1.9' @@ -43,6 +45,7 @@ ext { // We can't upgrade JAXB in Karaf (yet), but fortunately everything works fine with the version built in Karaf jaxbApiVersionOsgiRange = "[2.2,3)" jaxbRuntimeVersion = '2.3.1' + jakartaJaxbRuntimeVersion = '3.0.0' //GraalVM graalvmVersion = '19.3.1' @@ -82,6 +85,18 @@ ext { // required by JAXB from JDK 9 as it is not available anymore in JDK 9 activation: 'javax.activation:javax.activation-api:1.2.0', + // jakarta + jakarta_jpa: "jakarta.persistence:jakarta.persistence-api:${project.jakartaJpaVersion}", + jakarta_jta: 'jakarta.transaction:jakarta.transaction-api:2.0.0', + jakarta_validation: 'jakarta.validation:jakarta.validation-api:3.0.0', + jakarta_jacc: 'jakarta.authorization:jakarta.authorization-api:2.0.0', + jakarta_interceptor: 'jakarta.interceptor:jakarta.interceptor-api:2.0.0', + jakarta_activation: 'jakarta.activation:jakarta.activation-api:2.0.1', + jakarta_resource: 'jakarta.resource:jakarta.resource-api:2.0.0', + jakarta_jaxb_api: 'jakarta.xml.bind:jakarta.xml.bind-api:3.0.0', + jakarta_jaxb_runtime: "org.glassfish.jaxb:jaxb-runtime:${jakartaJaxbRuntimeVersion}", + jakarta_cdi: 'jakarta.enterprise:jakarta.enterprise.cdi-api:3.0.0', + // logging logging: 'org.jboss.logging:jboss-logging:3.4.1.Final', logging_annotations: 'org.jboss.logging:jboss-logging-annotations:2.1.0.Final', @@ -140,7 +155,10 @@ ext { informix: 'com.ibm.informix:jdbc:4.10.12', firebird: 'org.firebirdsql.jdbc:jaybird:4.0.3.java8', - jboss_jta: "org.jboss.jbossts:jbossjta:4.16.4.Final", + jboss_jta: "org.jboss.narayana.jta:narayana-jta:5.11.2.Final", + jboss_tx_spi: "org.jboss:jboss-transaction-spi:7.6.1.Final", + jboss_jta_jakarta: "org.jboss.narayana.jta:narayana-jta-jakarta:5.11.2.Final", + jboss_tx_spi_jakarta: "org.jboss:jboss-transaction-spi-jakarta:7.6.1.Final", xapool: "com.experlog:xapool:1.5.0", mockito: 'org.mockito:mockito-core:2.19.1', mockito_inline: 'org.mockito:mockito-inline:2.19.1', @@ -149,6 +167,10 @@ ext { // EL required by Hibernate Validator at test runtime expression_language: "org.glassfish:javax.el:${elVersion}", + jakarta_validator:"org.hibernate.validator:hibernate-validator:${hibernateValidatorJakartaVersion}", + // EL required by Hibernate Validator at test runtime + jakarta_el: 'org.glassfish:jakarta.el:4.0.1', + c3p0: "com.mchange:c3p0:0.9.5.5", ehcache: "net.sf.ehcache:ehcache:2.10.6", ehcache3: "org.ehcache:ehcache:3.6.1", @@ -165,6 +187,7 @@ ext { cdi: "javax.enterprise:cdi-api:${cdiVersion}", weld: "org.jboss.weld.se:weld-se-shaded:${weldVersion}", + jakarta_weld: "org.jboss.weld.se:weld-se-shaded:${jakartaWeldVersion}", assertj: "org.assertj:assertj-core:${assertjVersion}", @@ -177,6 +200,8 @@ ext { jboss_vfs: "org.jboss:jboss-vfs:3.2.11.Final", wildfly_transaction_client : 'org.wildfly.transaction:wildfly-transaction-client:1.1.7.Final', + // todo (jakarta): update the version when it is released + wildfly_transaction_client_jakarta : 'org.wildfly.transaction:wildfly-transaction-client-jakarta:1.2.0.Final-SNAPSHOT', jboss_ejb_spec_jar : 'org.jboss.spec.javax.ejb:jboss-ejb-api_3.2_spec:1.0.0.Final', jboss_annotation_spec_jar : 'org.jboss.spec.javax.annotation:jboss-annotations-api_1.2_spec:1.0.0.Final', diff --git a/hibernate-core-jakarta/hibernate-core-jakarta.gradle b/hibernate-core-jakarta/hibernate-core-jakarta.gradle new file mode 100644 index 0000000000..6dbe272e27 --- /dev/null +++ b/hibernate-core-jakarta/hibernate-core-jakarta.gradle @@ -0,0 +1,183 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ + +import org.apache.tools.ant.filters.ReplaceTokens + +description = 'Hibernate O/RM implementation of the Jakarta Persistence specification' + +apply from: rootProject.file( 'gradle/published-java-module.gradle' ) + +configurations { + tests { + description = 'Configuration for the produced test jar' + } + jakartaeeTransformJars +} + +dependencies { + compile( libraries.jakarta_jpa ) + // This can now be made provided + compile( libraries.javassist ) + // Could be made optional? + compile( libraries.byteBuddy ) + compile( libraries.antlr ) + compile( libraries.jakarta_jta ) + compile( libraries.jandex ) + compile( libraries.classmate ) + compile( libraries.jakarta_activation ) + + provided( libraries.jakarta_jacc ) + provided( libraries.jakarta_validation ) + provided( libraries.ant ) + provided( libraries.jakarta_cdi ) + + compile( libraries.dom4j ) + compile( libraries.commons_annotations ) + + compile( libraries.jakarta_jaxb_api ) + compile( libraries.jakarta_jaxb_runtime ) + + jakartaeeTransformJars 'biz.aQute.bnd:biz.aQute.bnd.transform:5.1.1', + 'commons-cli:commons-cli:1.4', + 'org.slf4j:slf4j-simple:1.7.30', + 'org.slf4j:slf4j-api:1.7.26', + 'org.eclipse.transformer:org.eclipse.transformer:0.2.0', + 'org.eclipse.transformer:org.eclipse.transformer.cli:0.2.0' + + testCompile( project(':hibernate-testing-jakarta') ) + testCompile fileTree(dir: 'libs', include: '*.jar') + + testCompile( libraries.shrinkwrap_api ) + testCompile( libraries.shrinkwrap ) + testCompile( libraries.jakarta_jacc ) + testCompile( libraries.jakarta_validation ) + testCompile( libraries.jandex ) + testCompile( libraries.classmate ) + testCompile( libraries.mockito ) + testCompile( libraries.mockito_inline ) + testCompile( libraries.jodaTime ) + testCompile( libraries.assertj ) + + testCompile( libraries.jakarta_cdi ) + + testCompile( libraries.jakarta_validator ) { + // for test runtime + transitive = true + } + + // for testing stored procedure support + testCompile( libraries.derby ) + + testRuntime( "org.jboss.spec.javax.ejb:jboss-ejb-api_3.2_spec:1.0.0.Final" ) + testRuntime( libraries.jakarta_el ) + testRuntime( 'jaxen:jaxen:1.1' ) + testRuntime( libraries.javassist ) + testRuntime( libraries.byteBuddy ) + testRuntime( libraries.jakarta_weld ) + testRuntime( libraries.atomikos ) + testRuntime( libraries.atomikos_jta ) +// todo (jakarta): replace this when the jakarta artifact is released + testRuntime( project(':hibernate-transaction-client') ) +// testRuntime( libraries.wildfly_transaction_client_jakarta ) + + testCompile libraries.shrinkwrap_descriptors_api_javaee + testCompile libraries.shrinkwrap_descriptors_impl_javaee + + testCompile libraries.jboss_ejb_spec_jar + testCompile libraries.jboss_annotation_spec_jar +} + +jar { + mustRunAfter project(':hibernate-core').tasks.jar + mustRunAfter project(':hibernate-core').tasks.testJar + dependsOn project(':hibernate-core').tasks.jar + dependsOn project(':hibernate-core').tasks.testJar + def baseDir = project(':hibernate-core').buildDir + def baseJars = fileTree(baseDir).matching {include 'libs/*.jar' } + inputs.files(baseJars).skipWhenEmpty() + outputs.dir project.buildDir + doLast { + new File(project.buildDir, "libs").mkdirs() + fileTree(project.buildDir).matching { include 'libs/*.jar' }.each { delete it } + + baseJars.each { bundleJar -> + def sourceJarPath = baseDir.path + '/libs/' + bundleJar.name + println 'Initial bundle jar name [ ' + sourceJarPath + ' ]' + + def finalBundleJarName = project.buildDir.path + '/libs/' + bundleJar.name.replaceAll( 'hibernate-core', 'hibernate-core-jakarta' ) + println 'Default jakarta final bundle jar name [ ' + finalBundleJarName + ' ]' + + def transformerArgs = [ + sourceJarPath, finalBundleJarName, + '-q', // quiet output + '-tr', new File(getProjectDir().getParentFile(), 'rules/jakarta-renames.properties').path, + '-tv', new File(getProjectDir().getParentFile(), 'rules/jakarta-versions.properties').path, + '-td', new File(getProjectDir().getParentFile(), 'rules/jakarta-direct.properties').path, + ] + + println 'Transformer options:' + transformerArgs.each { + println ' [ ' + it + ' ]' + } + + javaexec { + classpath configurations.jakartaeeTransformJars + main = 'org.eclipse.transformer.jakarta.JakartaTransformer' + args = transformerArgs + } + } + } +} + +task unpackTestJar(type: Copy) { + dependsOn jar + fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { + def outputDir = file("${buildDir}/unpacked/" + it.name) + from zipTree(it) + into outputDir + } +} + +task copyBundleResources (type: Copy) { + dependsOn unpackTestJar + File unpackedDir = new File(project.buildDir, "libs/hibernate-core-jakarta-${project.version}-test.jar") + ext { + bundlesTargetDir = file( "${buildDir}/bundles" ) + bundleTokens = dbBundle[db] + ext.bundleTokens['buildDirName'] = buildDir.absolutePath + } + + from file("${buildDir}/unpacked/${unpackedDir.name}/templates") + into ext.bundlesTargetDir + filter( ReplaceTokens, tokens: ext.bundleTokens) + doFirst { + ext.bundlesTargetDir.mkdirs() + } +} + +processTestResources.dependsOn copyBundleResources + +artifacts { + tests new File(project.buildDir, "libs/hibernate-core-jakarta-${project.version}-test.jar") +} + +test { + fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { + def outputDir = file("${buildDir}/unpacked/" + it.name) + testClassesDirs += files(outputDir) + classpath += files(outputDir) + } + systemProperty 'file.encoding', 'utf-8' + + if ( gradle.ext.javaVersions.test.launcher.asInt() >= 9 ) { + // See org.hibernate.boot.model.naming.NamingHelperTest.DefaultCharset.set + jvmArgs( ['--add-opens', 'java.base/java.nio.charset=ALL-UNNAMED'] ) + // Weld needs this to generate proxies + jvmArgs( ['--add-opens', 'java.base/java.security=ALL-UNNAMED'] ) + jvmArgs( ['--add-opens', 'java.base/java.lang=ALL-UNNAMED'] ) + } +} \ No newline at end of file diff --git a/hibernate-core/hibernate-core.gradle b/hibernate-core/hibernate-core.gradle index 80bd236a7c..ed9ac25bb7 100644 --- a/hibernate-core/hibernate-core.gradle +++ b/hibernate-core/hibernate-core.gradle @@ -39,7 +39,7 @@ sourceSets { // resources inherently exclude sources test { resources { - setSrcDirs( ['src/test/java','src/test/resources'] ) + setSrcDirs( ['src/test/java','src/test/resources','src/test/bundles'] ) } } @@ -136,6 +136,7 @@ jar { // For JPA, we don't want to target the automatically generated range, but a specific version "javax.persistence;version=\"${project.jpaVersion.osgiName}\"", // optionals + 'jakarta.persistence.spi;resolution:=optional', 'javax.management;resolution:=optional', 'javax.naming.event;resolution:=optional', 'javax.naming.spi;resolution:=optional', @@ -219,7 +220,7 @@ task copyBundleResources (type: Copy) { ext.bundleTokens['buildDirName'] = buildDir.absolutePath } - from file('src/test/bundles') + from file('src/test/bundles/templates') into ext.bundlesTargetDir filter( ReplaceTokens, tokens: ext.bundleTokens) @@ -230,6 +231,7 @@ task copyBundleResources (type: Copy) { processTestResources.dependsOn copyBundleResources task testJar(type: Jar, dependsOn: testClasses) { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE archiveClassifier.set( 'test' ) from sourceSets.test.output } diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/QueryHints.java b/hibernate-core/src/main/java/org/hibernate/annotations/QueryHints.java index 22748b3e3b..39166baa23 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/QueryHints.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/QueryHints.java @@ -93,6 +93,11 @@ public class QueryHints { */ public static final String TIMEOUT_JPA = "javax.persistence.query.timeout"; + /** + * Apply a JPA query timeout, which is defined in milliseconds. + */ + public static final String TIMEOUT_JAKARTA_JPA = "jakarta.persistence.query.timeout"; + /** * Available to apply lock mode to a native SQL query since JPA requires that * {@link javax.persistence.Query#setLockMode} throw an IllegalStateException if called for a native query. diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/ClassLoaderAccessImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/ClassLoaderAccessImpl.java index 6797a0298c..0234da6193 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/ClassLoaderAccessImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/ClassLoaderAccessImpl.java @@ -85,6 +85,7 @@ public class ClassLoaderAccessImpl implements ClassLoaderAccess { // classes in any of these packages are safe to load through the "live" ClassLoader return name.startsWith( "java." ) || name.startsWith( "javax." ) + || name.startsWith( "jakarta." ) || name.startsWith( "org.hibernate." ); } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java index 098d16db12..e5b87b4fd4 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java @@ -591,7 +591,7 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont ); this.sharedCacheMode = configService.getSetting( - "javax.persistence.sharedCache.mode", + AvailableSettings.JPA_SHARED_CACHE_MODE, new ConfigurationService.Converter() { @Override public SharedCacheMode convert(Object value) { @@ -606,7 +606,24 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont return SharedCacheMode.valueOf( value.toString() ); } }, - SharedCacheMode.UNSPECIFIED + configService.getSetting( + AvailableSettings.JAKARTA_JPA_SHARED_CACHE_MODE, + new ConfigurationService.Converter() { + @Override + public SharedCacheMode convert(Object value) { + if ( value == null ) { + return null; + } + + if ( SharedCacheMode.class.isInstance( value ) ) { + return (SharedCacheMode) value; + } + + return SharedCacheMode.valueOf( value.toString() ); + } + }, + SharedCacheMode.UNSPECIFIED + ) ); this.defaultCacheAccessType = configService.getSetting( diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java index 02eadbe47d..3a09bc4c37 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java @@ -279,8 +279,14 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions { ( (ConfigurationServiceImpl) cfgService ).injectServices( (ServiceRegistryImplementor) serviceRegistry ); } - this.beanManagerReference = configurationSettings.get( "javax.persistence.bean.manager" ); - this.validatorFactoryReference = configurationSettings.get( "javax.persistence.validation.factory" ); + this.beanManagerReference = configurationSettings.getOrDefault( + AvailableSettings.CDI_BEAN_MANAGER, + configurationSettings.get( AvailableSettings.JAKARTA_CDI_BEAN_MANAGER ) + ); + this.validatorFactoryReference = configurationSettings.getOrDefault( + AvailableSettings.JPA_VALIDATION_FACTORY, + configurationSettings.get( AvailableSettings.JAKARTA_JPA_VALIDATION_FACTORY ) + ); this.sessionFactoryName = (String) configurationSettings.get( SESSION_FACTORY_NAME ); this.sessionFactoryNameAlsoJndiName = cfgService.getSetting( diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/interceptor/LazyAttributeLoadingInterceptor.java b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/interceptor/LazyAttributeLoadingInterceptor.java index 48390125e3..9a3613cf9f 100644 --- a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/interceptor/LazyAttributeLoadingInterceptor.java +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/interceptor/LazyAttributeLoadingInterceptor.java @@ -15,6 +15,7 @@ import java.util.Set; import org.hibernate.LockMode; import org.hibernate.bytecode.enhance.spi.CollectionTracker; import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer; +import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.engine.spi.SelfDirtinessTracker; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.Status; @@ -151,11 +152,18 @@ public class LazyAttributeLoadingInterceptor extends AbstractLazyLoadInterceptor private void takeCollectionSizeSnapshot(Object target, String fieldName, Object value) { if ( value instanceof Collection && target instanceof SelfDirtinessTracker ) { + // This must be called first, so that we remember that there is a collection out there, + // even if we don't know its size (see below). CollectionTracker tracker = ( (SelfDirtinessTracker) target ).$$_hibernate_getCollectionTracker(); if ( tracker == null ) { ( (SelfDirtinessTracker) target ).$$_hibernate_clearDirtyAttributes(); tracker = ( (SelfDirtinessTracker) target ).$$_hibernate_getCollectionTracker(); } + + if ( value instanceof PersistentCollection && !( (PersistentCollection) value ).wasInitialized() ) { + // Cannot take a snapshot of an un-initialized collection. + return; + } tracker.add( fieldName, ( (Collection) value ).size() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java index 08d31fd0ed..6fdd00e1e6 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java @@ -146,6 +146,7 @@ import org.hibernate.cfg.annotations.Nullability; import org.hibernate.cfg.annotations.PropertyBinder; import org.hibernate.cfg.annotations.QueryBinder; import org.hibernate.cfg.annotations.TableBinder; +import org.hibernate.cfg.internal.NullableDiscriminatorColumnSecondPass; import org.hibernate.engine.OptimisticLockStyle; import org.hibernate.engine.spi.FilterDefinition; import org.hibernate.id.PersistentIdentifierGenerator; @@ -1556,6 +1557,8 @@ public final class AnnotationBinder { if ( LOG.isTraceEnabled() ) { LOG.tracev( "Setting discriminator for entity {0}", rootClass.getEntityName() ); } + context.getMetadataCollector().addSecondPass( + new NullableDiscriminatorColumnSecondPass( rootClass.getEntityName() ) ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java index 88d4e07d25..6ebe4b21b9 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java @@ -213,6 +213,185 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings { String CDI_BEAN_MANAGER = "javax.persistence.bean.manager"; + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Jakarta JPA defined settings + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + /** + * The name of the {@link javax.persistence.spi.PersistenceProvider} implementor + *

+ * See JPA 2 sections 9.4.3 and 8.2.1.4 + */ + String JAKARTA_JPA_PERSISTENCE_PROVIDER = "jakarta.persistence.provider"; + + /** + * The type of transactions supported by the entity managers. + *

+ * See JPA 2 sections 9.4.3 and 8.2.1.2 + */ + String JAKARTA_JPA_TRANSACTION_TYPE = "jakarta.persistence.transactionType"; + + /** + * The JNDI name of a JTA {@link javax.sql.DataSource}. + *

+ * See JPA 2 sections 9.4.3 and 8.2.1.5 + */ + String JAKARTA_JPA_JTA_DATASOURCE = "jakarta.persistence.jtaDataSource"; + + /** + * The JNDI name of a non-JTA {@link javax.sql.DataSource}. + *

+ * See JPA 2 sections 9.4.3 and 8.2.1.5 + */ + String JAKARTA_JPA_NON_JTA_DATASOURCE = "jakarta.persistence.nonJtaDataSource"; + + /** + * The name of a JDBC driver to use to connect to the database. + *

+ * Used in conjunction with {@link #JPA_JDBC_URL}, {@link #JPA_JDBC_USER} and {@link #JPA_JDBC_PASSWORD} + * to define how to make connections to the database in lieu of + * a datasource (either {@link #JPA_JTA_DATASOURCE} or {@link #JPA_NON_JTA_DATASOURCE}). + *

+ * See section 8.2.1.9 + */ + String JAKARTA_JPA_JDBC_DRIVER = "jakarta.persistence.jdbc.driver"; + + /** + * The JDBC connection url to use to connect to the database. + *

+ * Used in conjunction with {@link #JPA_JDBC_DRIVER}, {@link #JPA_JDBC_USER} and {@link #JPA_JDBC_PASSWORD} + * to define how to make connections to the database in lieu of + * a datasource (either {@link #JPA_JTA_DATASOURCE} or {@link #JPA_NON_JTA_DATASOURCE}). + *

+ * See section 8.2.1.9 + */ + String JAKARTA_JPA_JDBC_URL = "jakarta.persistence.jdbc.url"; + + /** + * The JDBC connection user name. + *

+ * Used in conjunction with {@link #JPA_JDBC_DRIVER}, {@link #JPA_JDBC_URL} and {@link #JPA_JDBC_PASSWORD} + * to define how to make connections to the database in lieu of + * a datasource (either {@link #JPA_JTA_DATASOURCE} or {@link #JPA_NON_JTA_DATASOURCE}). + *

+ * See section 8.2.1.9 + */ + String JAKARTA_JPA_JDBC_USER = "jakarta.persistence.jdbc.user"; + + /** + * The JDBC connection password. + *

+ * Used in conjunction with {@link #JPA_JDBC_DRIVER}, {@link #JPA_JDBC_URL} and {@link #JPA_JDBC_USER} + * to define how to make connections to the database in lieu of + * a datasource (either {@link #JPA_JTA_DATASOURCE} or {@link #JPA_NON_JTA_DATASOURCE}). + *

+ * See JPA 2 section 8.2.1.9 + */ + String JAKARTA_JPA_JDBC_PASSWORD = "jakarta.persistence.jdbc.password"; + + /** + * Used to indicate whether second-level (what JPA terms shared cache) caching is + * enabled as per the rules defined in JPA 2 section 3.1.7. + *

+ * See JPA 2 sections 9.4.3 and 8.2.1.7 + * @see javax.persistence.SharedCacheMode + */ + String JAKARTA_JPA_SHARED_CACHE_MODE = "jakarta.persistence.sharedCache.mode"; + + /** + * NOTE : Not a valid EMF property... + *

+ * Used to indicate if the provider should attempt to retrieve requested data + * in the shared cache. + * + * @see javax.persistence.CacheRetrieveMode + */ + String JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE ="jakarta.persistence.cache.retrieveMode"; + + /** + * NOTE : Not a valid EMF property... + *

+ * Used to indicate if the provider should attempt to store data loaded from the database + * in the shared cache. + * + * @see javax.persistence.CacheStoreMode + */ + String JAKARTA_JPA_SHARED_CACHE_STORE_MODE ="jakarta.persistence.cache.storeMode"; + + /** + * Used to indicate what form of automatic validation is in effect as per rules defined + * in JPA 2 section 3.6.1.1 + *

+ * See JPA 2 sections 9.4.3 and 8.2.1.8 + * @see javax.persistence.ValidationMode + */ + String JAKARTA_JPA_VALIDATION_MODE = "jakarta.persistence.validation.mode"; + + /** + * Used to pass along any discovered validator factory. + */ + String JAKARTA_JPA_VALIDATION_FACTORY = "jakarta.persistence.validation.factory"; + + /** + * Used to coordinate with bean validators + *

+ * See JPA 2 section 8.2.1.9 + */ + String JAKARTA_JPA_PERSIST_VALIDATION_GROUP = "jakarta.persistence.validation.group.pre-persist"; + + /** + * Used to coordinate with bean validators + *

+ * See JPA 2 section 8.2.1.9 + */ + String JAKARTA_JPA_UPDATE_VALIDATION_GROUP = "jakarta.persistence.validation.group.pre-update"; + + /** + * Used to coordinate with bean validators + *

+ * See JPA 2 section 8.2.1.9 + */ + String JAKARTA_JPA_REMOVE_VALIDATION_GROUP = "jakarta.persistence.validation.group.pre-remove"; + + /** + * Used to request (hint) a pessimistic lock scope. + *

+ * See JPA 2 sections 8.2.1.9 and 3.4.4.3 + */ + String JAKARTA_JPA_LOCK_SCOPE = "jakarta.persistence.lock.scope"; + + /** + * Used to request (hint) a pessimistic lock timeout (in milliseconds). + *

+ * See JPA 2 sections 8.2.1.9 and 3.4.4.3 + */ + String JAKARTA_JPA_LOCK_TIMEOUT = "jakarta.persistence.lock.timeout"; + + /** + * Used to pass along the CDI BeanManager, if any, to be used. + * + * According to JPA, strictly, the BeanManager should be passed in + * at boot-time and be ready for use at that time. However not all + * environments can do this (WildFly e.g.). To accommodate such + * environments, Hibernate provides 2 options: + * + * * a proprietary CDI extension SPI (that we have proposed to + * the CDI spec group as a standard option) that can be used + * to provide delayed BeanManager access. To use this solution, + * the reference passed as the BeanManager during bootstrap + * should be typed as {@link ExtendedBeanManager} + * * delayed access to the BeanManager reference. Here, Hibernate + * will not access the reference passed as the BeanManager during + * bootstrap until it is first needed. Note however that this has + * the effect of delaying any deployment problems until after + * bootstrapping. + * + * This setting is used to configure Hibernate ORM's access to + * the BeanManager (either directly or via {@link ExtendedBeanManager}). + */ + String JAKARTA_CDI_BEAN_MANAGER = "jakarta.persistence.bean.manager"; + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // BootstrapServiceRegistry level settings // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1581,6 +1760,185 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings { */ String HBM2DDL_CREATE_SCHEMAS = "javax.persistence.create-database-schemas"; + /** + * Setting to perform SchemaManagementTool actions against the database directly via JDBC + * automatically as part of the SessionFactory lifecycle. Valid options are defined by the + * {@link org.hibernate.tool.schema.Action} enum. + *

+ * Interpreted in combination with {@link #HBM2DDL_AUTO}. If no value is specified, the default + * is "none" ({@link org.hibernate.tool.schema.Action#NONE}). + * + * @see org.hibernate.tool.schema.Action + */ + String JAKARTA_HBM2DDL_DATABASE_ACTION = "jakarta.persistence.schema-generation.database.action"; + + /** + * Setting to perform SchemaManagementTool actions writing the commands into a DDL script file. + * Valid options are defined by the {@link org.hibernate.tool.schema.Action} enum. + *

+ * Interpreted in combination with {@link #HBM2DDL_AUTO}. If no value is specified, the default + * is "none" ({@link org.hibernate.tool.schema.Action#NONE}). + * + * @see org.hibernate.tool.schema.Action + */ + String JAKARTA_HBM2DDL_SCRIPTS_ACTION = "jakarta.persistence.schema-generation.scripts.action"; + + /** + * Allows passing a specific {@link java.sql.Connection} instance to be used by SchemaManagementTool. + *

+ * May also be used to determine the values for {@value #HBM2DDL_DB_NAME}, + * {@value #HBM2DDL_DB_MAJOR_VERSION} and {@value #HBM2DDL_DB_MINOR_VERSION}. + */ + String JAKARTA_HBM2DDL_CONNECTION = "jakarta.persistence.schema-generation-connection"; + + /** + * Specifies the name of the database provider in cases where a Connection to the underlying database is + * not available (aka, mainly in generating scripts). In such cases, a value for this setting + * *must* be specified. + *

+ * The value of this setting is expected to match the value returned by + * {@link java.sql.DatabaseMetaData#getDatabaseProductName()} for the target database. + *

+ * Additionally specifying {@value #HBM2DDL_DB_MAJOR_VERSION} and/or {@value #HBM2DDL_DB_MINOR_VERSION} + * may be required to understand exactly how to generate the required schema commands. + * + * @see #HBM2DDL_DB_MAJOR_VERSION + * @see #HBM2DDL_DB_MINOR_VERSION + */ + @SuppressWarnings("JavaDoc") + String JAKARTA_HBM2DDL_DB_NAME = "jakarta.persistence.database-product-name"; + + /** + * Specifies the name of the database provider in cases where a Connection to the underlying database is + * not available (aka, mainly in generating scripts). This value is used to help more precisely determine + * how to perform schema generation tasks for the underlying database in cases where + * {@value #DIALECT_DB_NAME} does not provide enough distinction. + *

+ * The value of this setting is expected to match the value returned by + * {@link java.sql.DatabaseMetaData#getDatabaseProductVersion()} for the target database. + * + * @see #DIALECT_DB_NAME + */ + String JAKARTA_DIALECT_DB_VERSION = "javax.persistence.database-product-version"; + + /** + * Specifies the major version of the underlying database, as would be returned by + * {@link java.sql.DatabaseMetaData#getDatabaseMajorVersion} for the target database. This value is used to + * help more precisely determine how to perform schema generation tasks for the underlying database in cases + * where {@value #HBM2DDL_DB_NAME} does not provide enough distinction. + + * @see #HBM2DDL_DB_NAME + * @see #HBM2DDL_DB_MINOR_VERSION + */ + String JAKARTA_HBM2DDL_DB_MAJOR_VERSION = "jakarta.persistence.database-major-version"; + + /** + * Specifies the minor version of the underlying database, as would be returned by + * {@link java.sql.DatabaseMetaData#getDatabaseMinorVersion} for the target database. This value is used to + * help more precisely determine how to perform schema generation tasks for the underlying database in cases + * where the combination of {@value #HBM2DDL_DB_NAME} and {@value #HBM2DDL_DB_MAJOR_VERSION} does not provide + * enough distinction. + * + * @see #HBM2DDL_DB_NAME + * @see #HBM2DDL_DB_MAJOR_VERSION + */ + String JAKARTA_HBM2DDL_DB_MINOR_VERSION = "jakarta.persistence.database-minor-version"; + + /** + * Specifies whether schema generation commands for schema creation are to be determined based on object/relational + * mapping metadata, DDL scripts, or a combination of the two. See {@link SourceType} for valid set of values. + * If no value is specified, a default is assumed as follows:

    + *
  • + * if source scripts are specified (per {@value #HBM2DDL_CREATE_SCRIPT_SOURCE}),then "scripts" is assumed + *
  • + *
  • + * otherwise, "metadata" is assumed + *
  • + *
+ * + * @see SourceType + */ + String JAKARTA_HBM2DDL_CREATE_SOURCE = "jakarta.persistence.schema-generation.create-source"; + + /** + * Specifies whether schema generation commands for schema dropping are to be determined based on object/relational + * mapping metadata, DDL scripts, or a combination of the two. See {@link SourceType} for valid set of values. + * If no value is specified, a default is assumed as follows:
    + *
  • + * if source scripts are specified (per {@value #HBM2DDL_DROP_SCRIPT_SOURCE}),then "scripts" is assumed + *
  • + *
  • + * otherwise, "metadata" is assumed + *
  • + *
+ * + * @see SourceType + */ + String JAKARTA_HBM2DDL_DROP_SOURCE = "jakarta.persistence.schema-generation.drop-source"; + + /** + * Specifies the CREATE script file as either a {@link java.io.Reader} configured for reading of the DDL script + * file or a string designating a file {@link java.net.URL} for the DDL script. + *

+ * Hibernate historically also accepted {@link #HBM2DDL_IMPORT_FILES} for a similar purpose. This setting + * should be preferred over {@link #HBM2DDL_IMPORT_FILES} moving forward + * + * @see #HBM2DDL_CREATE_SOURCE + * @see #HBM2DDL_IMPORT_FILES + */ + String JAKARTA_HBM2DDL_CREATE_SCRIPT_SOURCE = "jakarta.persistence.schema-generation.create-script-source"; + + /** + * Specifies the DROP script file as either a {@link java.io.Reader} configured for reading of the DDL script + * file or a string designating a file {@link java.net.URL} for the DDL script. + * + * @see #HBM2DDL_DROP_SOURCE + */ + String JAKARTA_HBM2DDL_DROP_SCRIPT_SOURCE = "jakarta.persistence.schema-generation.drop-script-source"; + + /** + * For cases where the {@value #HBM2DDL_SCRIPTS_ACTION} value indicates that schema creation commands should + * be written to DDL script file, {@value #HBM2DDL_SCRIPTS_CREATE_TARGET} specifies either a + * {@link java.io.Writer} configured for output of the DDL script or a string specifying the file URL for the DDL + * script. + * + * @see #HBM2DDL_SCRIPTS_ACTION + */ + @SuppressWarnings("JavaDoc") + String JAKARTA_HBM2DDL_SCRIPTS_CREATE_TARGET = "jakarta.persistence.schema-generation.scripts.create-target"; + + /** + * For cases where the {@value #HBM2DDL_SCRIPTS_ACTION} value indicates that schema drop commands should + * be written to DDL script file, {@value #HBM2DDL_SCRIPTS_DROP_TARGET} specifies either a + * {@link java.io.Writer} configured for output of the DDL script or a string specifying the file URL for the DDL + * script. + * + * @see #HBM2DDL_SCRIPTS_ACTION + */ + @SuppressWarnings("JavaDoc") + String JAKARTA_HBM2DDL_SCRIPTS_DROP_TARGET = "jakarta.persistence.schema-generation.scripts.drop-target"; + + /** + * JPA variant of {@link #HBM2DDL_IMPORT_FILES} + *

+ * Specifies a {@link java.io.Reader} configured for reading of the SQL load script or a string designating the + * file {@link java.net.URL} for the SQL load script. + *

+ * A "SQL load script" is a script that performs some database initialization (INSERT, etc). + */ + String JAKARTA_HBM2DDL_LOAD_SCRIPT_SOURCE = "jakarta.persistence.sql-load-script-source"; + + /** + * The JPA variant of {@link #HBM2DDL_CREATE_NAMESPACES} + *

+ * Specifies whether the persistence provider is to create the database schema(s) in addition to creating + * database objects (tables, sequences, constraints, etc). The value of this boolean property should be set + * to {@code true} if the persistence provider is to create schemas in the database or to generate DDL that + * contains "CREATE SCHEMA" commands. If this property is not supplied (or is explicitly {@code false}), the + * provider should not attempt to create database schemas. + */ + String JAKARTA_HBM2DDL_CREATE_SCHEMAS = "jakarta.persistence.create-database-schemas"; + /** * @deprecated Use {@link #HBM2DDL_CREATE_SCHEMAS} instead: this variable name had a typo. */ diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java index 05593096be..55a7e59fb8 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java @@ -67,6 +67,7 @@ import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.cfg.AccessType; import org.hibernate.cfg.AnnotationBinder; import org.hibernate.cfg.BinderHelper; +import org.hibernate.cfg.Ejb3DiscriminatorColumn; import org.hibernate.cfg.Ejb3JoinColumn; import org.hibernate.cfg.InheritanceState; import org.hibernate.cfg.ObjectNameSource; diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/QueryHintDefinition.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/QueryHintDefinition.java index a60ea76f84..3dfe2800b2 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/QueryHintDefinition.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/QueryHintDefinition.java @@ -20,6 +20,7 @@ import org.hibernate.LockMode; import org.hibernate.LockOptions; import org.hibernate.MappingException; import org.hibernate.annotations.QueryHints; +import org.hibernate.cfg.AvailableSettings; import org.hibernate.internal.util.LockModeConverter; import org.hibernate.internal.util.config.ConfigurationHelper; @@ -132,7 +133,10 @@ public class QueryHintDefinition { public LockOptions determineLockOptions(NamedQuery namedQueryAnnotation) { LockModeType lockModeType = namedQueryAnnotation.lockMode(); - Integer lockTimeoutHint = getInteger( "javax.persistence.lock.timeout" ); + Integer lockTimeoutHint = getInteger( AvailableSettings.JPA_LOCK_TIMEOUT ); + if ( lockTimeoutHint == null ) { + lockTimeoutHint = getInteger( AvailableSettings.JAKARTA_JPA_LOCK_TIMEOUT ); + } Boolean followOnLocking = getBoolean( QueryHints.FOLLOW_ON_LOCKING ); return determineLockOptions(lockModeType, lockTimeoutHint, followOnLocking); diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationIntegrator.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationIntegrator.java index f2524f7144..7ef254e5f5 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationIntegrator.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationIntegrator.java @@ -33,8 +33,10 @@ public class BeanValidationIntegrator implements Integrator { public static final String APPLY_CONSTRAINTS = "hibernate.validator.apply_to_ddl"; public static final String BV_CHECK_CLASS = "javax.validation.ConstraintViolation"; + public static final String JAKARTA_BV_CHECK_CLASS = "jakarta.validation.ConstraintViolation"; public static final String MODE_PROPERTY = "javax.persistence.validation.mode"; + public static final String JAKARTA_MODE_PROPERTY = "jakarta.persistence.validation.mode"; private static final String ACTIVATOR_CLASS_NAME = "org.hibernate.cfg.beanvalidation.TypeSafeActivator"; private static final String VALIDATE_SUPPLIED_FACTORY_METHOD_NAME = "validateSuppliedFactory"; @@ -87,7 +89,11 @@ public class BeanValidationIntegrator implements Integrator { final SessionFactoryServiceRegistry serviceRegistry) { final ConfigurationService cfgService = serviceRegistry.getService( ConfigurationService.class ); // IMPL NOTE : see the comments on ActivationContext.getValidationModes() as to why this is multi-valued... - final Set modes = ValidationMode.getModes( cfgService.getSettings().get( MODE_PROPERTY ) ); + Object modeSetting = cfgService.getSettings().get( MODE_PROPERTY ); + if ( modeSetting == null ) { + modeSetting = cfgService.getSettings().get( JAKARTA_MODE_PROPERTY ); + } + final Set modes = ValidationMode.getModes( modeSetting ); if ( modes.size() > 1 ) { LOG.multipleValidationModes( ValidationMode.loggable( modes ) ); } @@ -157,7 +163,13 @@ public class BeanValidationIntegrator implements Integrator { return true; } catch (Exception e) { - return false; + try { + classLoaderService.classForName( JAKARTA_BV_CHECK_CLASS ); + return true; + } + catch (Exception e2) { + return false; + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/GroupsPerOperation.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/GroupsPerOperation.java index ac40014f57..ff72411121 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/GroupsPerOperation.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/GroupsPerOperation.java @@ -22,6 +22,7 @@ import org.hibernate.internal.util.collections.CollectionHelper; */ public class GroupsPerOperation { private static final String JPA_GROUP_PREFIX = "javax.persistence.validation.group."; + private static final String JAKARTA_JPA_GROUP_PREFIX = "javax.persistence.validation.group."; private static final String HIBERNATE_GROUP_PREFIX = "org.hibernate.validator.group."; private static final Class[] DEFAULT_GROUPS = new Class[] { Default.class }; @@ -55,7 +56,10 @@ public class GroupsPerOperation { } public static Class[] buildGroupsForOperation(Operation operation, Map settings, ClassLoaderAccess classLoaderAccess) { - final Object property = settings.get( operation.getGroupPropertyName() ); + Object property = settings.get( operation.getGroupPropertyName() ); + if ( property == null ) { + property = settings.get( operation.getJakartaGroupPropertyName() ); + } if ( property == null ) { return operation == Operation.DELETE ? EMPTY_GROUPS : DEFAULT_GROUPS; @@ -96,18 +100,20 @@ public class GroupsPerOperation { } public static enum Operation { - INSERT("persist", JPA_GROUP_PREFIX + "pre-persist"), - UPDATE("update", JPA_GROUP_PREFIX + "pre-update"), - DELETE("remove", JPA_GROUP_PREFIX + "pre-remove"), - DDL("ddl", HIBERNATE_GROUP_PREFIX + "ddl"); + INSERT( "persist", JPA_GROUP_PREFIX + "pre-persist", JAKARTA_JPA_GROUP_PREFIX + "pre-persist" ), + UPDATE( "update", JPA_GROUP_PREFIX + "pre-update", JAKARTA_JPA_GROUP_PREFIX + "pre-update" ), + DELETE( "remove", JPA_GROUP_PREFIX + "pre-remove", JAKARTA_JPA_GROUP_PREFIX + "pre-remove" ), + DDL( "ddl", HIBERNATE_GROUP_PREFIX + "ddl", HIBERNATE_GROUP_PREFIX + "ddl" ); private final String exposedName; private final String groupPropertyName; + private final String jakartaGroupPropertyName; - Operation(String exposedName, String groupProperty) { + Operation(String exposedName, String groupProperty, String jakartaGroupPropertyName) { this.exposedName = exposedName; this.groupPropertyName = groupProperty; + this.jakartaGroupPropertyName = jakartaGroupPropertyName; } public String getName() { @@ -117,6 +123,10 @@ public class GroupsPerOperation { public String getGroupPropertyName() { return groupPropertyName; } + + public String getJakartaGroupPropertyName() { + return jakartaGroupPropertyName; + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/TypeSafeActivator.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/TypeSafeActivator.java index 86b7177592..87d2a09835 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/TypeSafeActivator.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/TypeSafeActivator.java @@ -33,6 +33,7 @@ import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; import org.hibernate.boot.spi.ClassLoaderAccess; import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Environment; import org.hibernate.dialect.Dialect; import org.hibernate.engine.config.spi.ConfigurationService; @@ -60,8 +61,6 @@ class TypeSafeActivator { private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, TypeSafeActivator.class.getName()); - private static final String FACTORY_PROPERTY = "javax.persistence.validation.factory"; - /** * Used to validate a supplied ValidatorFactory instance as being castable to ValidatorFactory. * @@ -532,7 +531,7 @@ class TypeSafeActivator { @SuppressWarnings("unchecked") private static ValidatorFactory resolveProvidedFactory(ConfigurationService cfgService) { return cfgService.getSetting( - FACTORY_PROPERTY, + AvailableSettings.JPA_VALIDATION_FACTORY, new ConfigurationService.Converter() { @Override public ValidatorFactory convert(Object value) { @@ -544,7 +543,7 @@ class TypeSafeActivator { String.format( Locale.ENGLISH, "ValidatorFactory reference (provided via `%s` setting) was not castable to %s : %s", - FACTORY_PROPERTY, + AvailableSettings.JPA_VALIDATION_FACTORY, ValidatorFactory.class.getName(), value.getClass().getName() ) @@ -552,7 +551,29 @@ class TypeSafeActivator { } } }, - null + cfgService.getSetting( + AvailableSettings.JAKARTA_JPA_VALIDATION_FACTORY, + new ConfigurationService.Converter() { + @Override + public ValidatorFactory convert(Object value) { + try { + return ValidatorFactory.class.cast( value ); + } + catch ( ClassCastException e ) { + throw new IntegrationException( + String.format( + Locale.ENGLISH, + "ValidatorFactory reference (provided via `%s` setting) was not castable to %s : %s", + AvailableSettings.JAKARTA_JPA_VALIDATION_FACTORY, + ValidatorFactory.class.getName(), + value.getClass().getName() + ) + ); + } + } + }, + null + ) ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/internal/NullableDiscriminatorColumnSecondPass.java b/hibernate-core/src/main/java/org/hibernate/cfg/internal/NullableDiscriminatorColumnSecondPass.java new file mode 100644 index 0000000000..afd3d57c68 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/cfg/internal/NullableDiscriminatorColumnSecondPass.java @@ -0,0 +1,54 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.cfg.internal; + +import java.util.Iterator; +import java.util.Map; + +import org.hibernate.MappingException; +import org.hibernate.cfg.SecondPass; +import org.hibernate.mapping.Column; +import org.hibernate.mapping.PersistentClass; +import org.hibernate.mapping.Selectable; +import org.hibernate.mapping.Subclass; + +public class NullableDiscriminatorColumnSecondPass implements SecondPass { + private final String rootEntityName; + + public NullableDiscriminatorColumnSecondPass(String rootEntityName) { + this.rootEntityName = rootEntityName; + } + + @Override + @SuppressWarnings("rawtypes") + public void doSecondPass(Map persistentClasses) throws MappingException { + PersistentClass rootPersistenceClass = (PersistentClass) persistentClasses.get( rootEntityName ); + if ( hasNullDiscriminatorValue( rootPersistenceClass ) ) { + for ( Iterator iterator = rootPersistenceClass.getDiscriminator().getColumnIterator(); + iterator.hasNext(); ) { + Selectable selectable = iterator.next(); + if ( selectable instanceof Column ) { + ( (Column) selectable ).setNullable( true ); + } + } + } + } + + @SuppressWarnings({ "unchecked" }) + private boolean hasNullDiscriminatorValue(PersistentClass rootPersistenceClass) { + if ( rootPersistenceClass.isDiscriminatorValueNull() ) { + return true; + } + Iterator subclassIterator = rootPersistenceClass.getSubclassIterator(); + while ( subclassIterator.hasNext() ) { + if ( subclassIterator.next().isDiscriminatorValueNull() ) { + return true; + } + } + return false; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/internal/AbstractEntityEntry.java b/hibernate-core/src/main/java/org/hibernate/engine/internal/AbstractEntityEntry.java index a849cf79e8..71974b9c9c 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/internal/AbstractEntityEntry.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/internal/AbstractEntityEntry.java @@ -331,9 +331,7 @@ public abstract class AbstractEntityEntry implements Serializable, EntityEntry { if ( enhancementAsProxyLazinessInterceptor.hasWrittenFieldNames() ) { return false; } - // When a proxy has dirty attributes, we have to treat it like a normal entity to flush changes - return !enhancementAsProxyLazinessInterceptor.isInitialized() - || !persister.hasCollections() && !( (SelfDirtinessTracker) entity ).$$_hibernate_hasDirtyAttributes(); + return true; } } else if ( entity instanceof HibernateProxy ) { diff --git a/hibernate-core/src/main/java/org/hibernate/engine/internal/TwoPhaseLoad.java b/hibernate-core/src/main/java/org/hibernate/engine/internal/TwoPhaseLoad.java index 296f1ef4f7..8ca3ddcd7c 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/internal/TwoPhaseLoad.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/internal/TwoPhaseLoad.java @@ -101,28 +101,6 @@ public final class TwoPhaseLoad { } } - /** - * @deprecated This method will be removed. Use {@link #initializeEntity(Object, boolean, SharedSessionContractImplementor, PreLoadEvent, Iterable)} instead. - * - * @param entity The entity being loaded - * @param readOnly Is the entity being loaded as read-only - * @param session The Session - * @param preLoadEvent The (re-used) pre-load event - */ - @Deprecated - public static void initializeEntity( - final Object entity, - final boolean readOnly, - final SharedSessionContractImplementor session, - final PreLoadEvent preLoadEvent) { - final EventListenerGroup listenerGroup = session - .getFactory() - .getFastSessionServices() - .eventListenerGroup_PRE_LOAD; - final Iterable listeners = listenerGroup.listeners(); - initializeEntity( entity, readOnly, session, preLoadEvent, listeners, EntityResolver.DEFAULT ); - } - /** * Perform the second step of 2-phase load. Fully initialize the entity * instance. @@ -135,15 +113,13 @@ public final class TwoPhaseLoad { * @param readOnly Is the entity being loaded as read-only * @param session The Session * @param preLoadEvent The (re-used) pre-load event - * @param preLoadEventListeners the pre-load event listeners */ public static void initializeEntity( final Object entity, final boolean readOnly, final SharedSessionContractImplementor session, - final PreLoadEvent preLoadEvent, - final Iterable preLoadEventListeners) { - initializeEntity( entity, readOnly, session, preLoadEvent, preLoadEventListeners, EntityResolver.DEFAULT ); + final PreLoadEvent preLoadEvent) { + initializeEntity( entity, readOnly, session, preLoadEvent, EntityResolver.DEFAULT ); } /** @@ -158,7 +134,6 @@ public final class TwoPhaseLoad { * @param readOnly Is the entity being loaded as read-only * @param session The Session * @param preLoadEvent The (re-used) pre-load event - * @param preLoadEventListeners the pre-load event listeners * @param entityResolver the resolver used for to-one entity associations * (not used when an entity is a bytecode-enhanced lazy entity) */ @@ -167,7 +142,6 @@ public final class TwoPhaseLoad { final boolean readOnly, final SharedSessionContractImplementor session, final PreLoadEvent preLoadEvent, - final Iterable preLoadEventListeners, final EntityResolver entityResolver) { final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); final EntityEntry entityEntry = persistenceContext.getEntry( entity ); @@ -175,7 +149,7 @@ public final class TwoPhaseLoad { throw new AssertionFailure( "possible non-threadsafe access to the session" ); } initializeEntityEntryLoadedState( entity, entityEntry, session, entityResolver ); - initializeEntityFromEntityEntryLoadedState( entity, entityEntry, readOnly, session, preLoadEvent, preLoadEventListeners ); + initializeEntityFromEntityEntryLoadedState( entity, entityEntry, readOnly, session, preLoadEvent ); } public static void initializeEntityEntryLoadedState( @@ -255,8 +229,7 @@ public final class TwoPhaseLoad { final EntityEntry entityEntry, final boolean readOnly, final SharedSessionContractImplementor session, - final PreLoadEvent preLoadEvent, - final Iterable preLoadEventListeners) throws HibernateException { + final PreLoadEvent preLoadEvent) throws HibernateException { final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); final EntityPersister persister = entityEntry.getPersister(); @@ -268,9 +241,8 @@ public final class TwoPhaseLoad { //Must occur after resolving identifiers! if ( session.isEventSource() ) { preLoadEvent.setEntity( entity ).setState( hydratedState ).setId( id ).setPersister( persister ); - for ( PreLoadEventListener listener : preLoadEventListeners ) { - listener.onPreLoad( preLoadEvent ); - } + session.getFactory().getFastSessionServices() + .eventListenerGroup_PRE_LOAD.fireEventOnEachListener( preLoadEvent, PreLoadEventListener::onPreLoad ); } persister.setPropertyValues( entity, hydratedState ); @@ -583,7 +555,7 @@ public final class TwoPhaseLoad { /** * Implementations determine how a to-one associations is resolved. * - * @see #initializeEntity(Object, boolean, SharedSessionContractImplementor, PreLoadEvent, Iterable, EntityResolver) + * @see #initializeEntity(Object, boolean, SharedSessionContractImplementor, PreLoadEvent, EntityResolver) */ public interface EntityResolver { diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/EffectiveEntityGraph.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/EffectiveEntityGraph.java index fa96dc082a..bb07a15e3e 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/EffectiveEntityGraph.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/EffectiveEntityGraph.java @@ -113,8 +113,14 @@ public class EffectiveEntityGraph implements AppliedGraph, Serializable { return; } - final RootGraphImplementor fetchHint = (RootGraphImplementor) properties.get( GraphSemantic.FETCH.getJpaHintName() ); - final RootGraphImplementor loadHint = (RootGraphImplementor) properties.get( GraphSemantic.LOAD.getJpaHintName() ); + RootGraphImplementor fetchHint = (RootGraphImplementor) properties.get( GraphSemantic.FETCH.getJpaHintName() ); + RootGraphImplementor loadHint = (RootGraphImplementor) properties.get( GraphSemantic.LOAD.getJpaHintName() ); + if (fetchHint == null) { + fetchHint = (RootGraphImplementor) properties.get( GraphSemantic.FETCH.getJakartaJpaHintName() ); + } + if (loadHint == null) { + loadHint = (RootGraphImplementor) properties.get( GraphSemantic.LOAD.getJakartaJpaHintName() ); + } if ( fetchHint == null && loadHint == null ) { log.debugf( "Neither LOAD nor FETCH graph were found in properties" ); diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractFlushingEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractFlushingEventListener.java index f42d8fb8b9..fdc22d9fe5 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractFlushingEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractFlushingEventListener.java @@ -104,8 +104,8 @@ public abstract class AbstractFlushingEventListener implements JpaBootstrapSensi logFlushResults( event ); } - @SuppressWarnings( value = {"unchecked"} ) - private void logFlushResults(FlushEvent event) { + @SuppressWarnings("unchecked") + protected void logFlushResults(FlushEvent event) { if ( !LOG.isDebugEnabled() ) { return; } @@ -219,7 +219,6 @@ public abstract class AbstractFlushingEventListener implements JpaBootstrapSensi final int count = entityEntries.length; for ( Map.Entry me : entityEntries ) { - // Update the status of the object and if necessary, schedule an update EntityEntry entry = me.getValue(); diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultFlushEntityEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultFlushEntityEventListener.java index 76b1f32093..0437f2f6e7 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultFlushEntityEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultFlushEntityEventListener.java @@ -454,6 +454,7 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener private boolean hasDirtyCollections(FlushEntityEvent event, EntityPersister persister, Status status) { if ( isCollectionDirtyCheckNecessary( persister, status ) ) { DirtyCollectionSearchVisitor visitor = new DirtyCollectionSearchVisitor( + event.getEntity(), event.getSession(), persister.getPropertyVersionability() ); diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DirtyCollectionSearchVisitor.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DirtyCollectionSearchVisitor.java index 73fb564b6e..3cfcd16417 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DirtyCollectionSearchVisitor.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DirtyCollectionSearchVisitor.java @@ -7,7 +7,9 @@ package org.hibernate.event.internal; import org.hibernate.HibernateException; +import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor; import org.hibernate.collection.spi.PersistentCollection; +import org.hibernate.engine.spi.PersistentAttributeInterceptable; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.event.spi.EventSource; import org.hibernate.type.CollectionType; @@ -22,11 +24,19 @@ import org.hibernate.type.CollectionType; */ public class DirtyCollectionSearchVisitor extends AbstractVisitor { + private final EnhancementAsProxyLazinessInterceptor interceptor; + private final boolean[] propertyVersionability; private boolean dirty; - private boolean[] propertyVersionability; - public DirtyCollectionSearchVisitor(EventSource session, boolean[] propertyVersionability) { + public DirtyCollectionSearchVisitor(Object entity, EventSource session, boolean[] propertyVersionability) { super( session ); + EnhancementAsProxyLazinessInterceptor interceptor = null; + if ( entity instanceof PersistentAttributeInterceptable ) { + if ( ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor() instanceof EnhancementAsProxyLazinessInterceptor ) { + interceptor = (EnhancementAsProxyLazinessInterceptor) ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor(); + } + } + this.interceptor = interceptor; this.propertyVersionability = propertyVersionability; } @@ -45,6 +55,9 @@ public class DirtyCollectionSearchVisitor extends AbstractVisitor { // return (ah==null) ? true : searchForDirtyCollections(ah, type); } else { + if ( interceptor != null && !interceptor.isAttributeLoaded( type.getName() ) ) { + return null; + } // if not wrapped yet, its dirty (this can't occur, because // we now always call wrap() before getting to here) // return ( ! (obj instanceof PersistentCollection) ) ? diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/WrapVisitor.java b/hibernate-core/src/main/java/org/hibernate/event/internal/WrapVisitor.java index 195935877a..f0c5a58912 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/WrapVisitor.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/WrapVisitor.java @@ -13,7 +13,6 @@ import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLaziness import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistentAttributeInterceptable; -import org.hibernate.engine.spi.PersistentAttributeInterceptor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.event.spi.EventSource; import org.hibernate.internal.CoreLogging; @@ -107,11 +106,8 @@ public class WrapVisitor extends ProxyVisitor { } else { if ( entity instanceof PersistentAttributeInterceptable ) { - final PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor(); - if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor ) { - if ( !( (EnhancementAsProxyLazinessInterceptor) interceptor ).isInitialized() ) { - return null; - } + if ( ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor() instanceof EnhancementAsProxyLazinessInterceptor ) { + return null; } } diff --git a/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerGroupImpl.java b/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerGroupImpl.java index 7ff63c97ed..02d023b66a 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerGroupImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerGroupImpl.java @@ -11,8 +11,12 @@ import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; import java.util.function.BiConsumer; +import java.util.function.BiFunction; import java.util.function.Consumer; +import java.util.function.Function; import java.util.function.Supplier; import org.hibernate.event.service.spi.DuplicationStrategy; @@ -33,8 +37,10 @@ import org.jboss.logging.Logger; * @author Sanne Grinovero */ class EventListenerGroupImpl implements EventListenerGroup { + private static final Logger log = Logger.getLogger( EventListenerGroupImpl.class ); private static final Set DEFAULT_DUPLICATION_STRATEGIES = Collections.unmodifiableSet( makeDefaultDuplicationStrategy() ); + private static final CompletableFuture COMPLETED = CompletableFuture.completedFuture( null ); private final EventType eventType; private final CallbackRegistry callbackRegistry; @@ -114,6 +120,54 @@ class EventListenerGroupImpl implements EventListenerGroup { } } + @Override + public CompletionStage fireEventOnEachListener( + final U event, + final Function>> fun) { + CompletionStage ret = COMPLETED; + final T[] ls = listeners; + if ( ls != null && ls.length != 0 ) { + for ( T listener : ls ) { + //to preserve atomicity of the Session methods + //call apply() from within the arg of thenCompose() + ret = ret.thenCompose( v -> fun.apply( (RL) listener ).apply( event ) ); + } + } + return ret; + } + + @Override + public CompletionStage fireEventOnEachListener( + U event, X param, Function>> fun) { + CompletionStage ret = COMPLETED; + final T[] ls = listeners; + if ( ls != null && ls.length != 0 ) { + for ( T listener : ls ) { + //to preserve atomicity of the Session methods + //call apply() from within the arg of thenCompose() + ret = ret.thenCompose( v -> fun.apply( (RL) listener ).apply( event, param ) ); + } + } + return ret; + } + + @Override + public CompletionStage fireLazyEventOnEachListener( + final Supplier eventSupplier, + final Function>> fun) { + CompletionStage ret = COMPLETED; + final T[] ls = listeners; + if ( ls != null && ls.length != 0 ) { + final U event = eventSupplier.get(); + for ( T listener : ls ) { + //to preserve atomicity of the Session methods + //call apply() from within the arg of thenCompose() + ret = ret.thenCompose( v -> fun.apply( (RL) listener ).apply( event ) ); + } + } + return ret; + } + @Override public void addDuplicationStrategy(DuplicationStrategy strategy) { if ( duplicationStrategies == DEFAULT_DUPLICATION_STRATEGIES ) { diff --git a/hibernate-core/src/main/java/org/hibernate/event/service/spi/EventListenerGroup.java b/hibernate-core/src/main/java/org/hibernate/event/service/spi/EventListenerGroup.java index a768b08bf5..9ca1fdd64a 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/service/spi/EventListenerGroup.java +++ b/hibernate-core/src/main/java/org/hibernate/event/service/spi/EventListenerGroup.java @@ -7,7 +7,10 @@ package org.hibernate.event.service.spi; import java.io.Serializable; +import java.util.concurrent.CompletionStage; import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Function; import java.util.function.Supplier; import org.hibernate.Incubating; @@ -112,4 +115,53 @@ public interface EventListenerGroup extends Serializable { @Incubating void fireEventOnEachListener(final U event, X param, final EventActionWithParameter actionOnEvent); + /** + * Similar to {@link #fireEventOnEachListener(Object, Function)}, but Reactive friendly: it chains + * processing of the same event on each Reactive Listener, and returns a {@link CompletionStage} of type R. + * The various generic types allow using this for each concrete event type and flexible return types. + *

Used by Hibernate Reactive

+ * @param event The event being fired + * @param fun The function combining each event listener with the event + * @param the return type of the returned CompletionStage + * @param the type of the event being fired on each listener + * @param the type of ReactiveListener: each listener of type T will be casted to it. + * @return the composite completion stage of invoking fun(event) on each listener. + */ + @Incubating + CompletionStage fireEventOnEachListener(final U event, final Function>> fun); + + /** + * Similar to {@link #fireEventOnEachListener(Object, Object, Function)}, but Reactive friendly: it chains + * processing of the same event on each Reactive Listener, and returns a {@link CompletionStage} of type R. + * The various generic types allow using this for each concrete event type and flexible return types. + *

Used by Hibernate Reactive

+ * @param event The event being fired + * @param fun The function combining each event listener with the event + * @param the return type of the returned CompletionStage + * @param the type of the event being fired on each listener + * @param the type of ReactiveListener: each listener of type T will be casted to it. + * @param an additional parameter to be passed to the function fun + * @return the composite completion stage of invoking fun(event) on each listener. + */ + @Incubating + public CompletionStage fireEventOnEachListener(U event, X param, Function>> fun); + + /** + * Similar to {@link #fireLazyEventOnEachListener(Supplier, BiConsumer)}, but Reactive friendly: it chains + * processing of the same event on each Reactive Listener, and returns a {@link CompletionStage} of type R. + * The various generic types allow using this for each concrete event type and flexible return types. + *

This variant expects a Supplier of the event, rather than the event directly; this is useful for the + * event types which are commonly configured with no listeners at all, so to allow skipping creating the + * event; use only for event types which are known to be expensive while the listeners are commonly empty.

+ *

Used by Hibernate Reactive

+ * @param eventSupplier A supplier able to produce the actual event + * @param fun The function combining each event listener with the event + * @param the return type of the returned CompletionStage + * @param the type of the event being fired on each listener + * @param the type of ReactiveListener: each listener of type T will be casted to it. + * @return the composite completion stage of invoking fun(event) on each listener. + */ + @Incubating + CompletionStage fireLazyEventOnEachListener(final Supplier eventSupplier, final Function>> fun); + } diff --git a/hibernate-core/src/main/java/org/hibernate/graph/GraphSemantic.java b/hibernate-core/src/main/java/org/hibernate/graph/GraphSemantic.java index 12498834e7..ceb0817234 100644 --- a/hibernate-core/src/main/java/org/hibernate/graph/GraphSemantic.java +++ b/hibernate-core/src/main/java/org/hibernate/graph/GraphSemantic.java @@ -19,7 +19,7 @@ public enum GraphSemantic { * subsequent select). Attributes that are not specified are treated as * FetchType.LAZY invariably. */ - FETCH( "javax.persistence.fetchgraph" ), + FETCH( "javax.persistence.fetchgraph", "jakarta.persistence.fetchgraph" ), /** * Indicates a "load graph" EntityGraph. Attributes explicitly specified @@ -28,26 +28,32 @@ public enum GraphSemantic { * FetchType.LAZY or FetchType.EAGER depending on the attribute's definition * in metadata. */ - LOAD( "javax.persistence.loadgraph" ); + LOAD( "javax.persistence.loadgraph", "jakarta.persistence.loadgraph" ); private final String jpaHintName; + private final String jakartaJpaHintName; - GraphSemantic(String jpaHintName) { + GraphSemantic(String jpaHintName, String jakartaJpaHintName) { this.jpaHintName = jpaHintName; + this.jakartaJpaHintName = jakartaJpaHintName; } public String getJpaHintName() { return jpaHintName; } + public String getJakartaJpaHintName() { + return jakartaJpaHintName; + } + public static GraphSemantic fromJpaHintName(String hintName) { assert hintName != null; - if ( FETCH.getJpaHintName().equals( hintName ) ) { + if ( FETCH.getJpaHintName().equals( hintName ) || FETCH.getJakartaJpaHintName().equals( hintName ) ) { return FETCH; } - if ( LOAD.getJpaHintName().equalsIgnoreCase( hintName ) ) { + if ( LOAD.getJpaHintName().equalsIgnoreCase( hintName ) || LOAD.getJakartaJpaHintName().equalsIgnoreCase( hintName ) ) { return LOAD; } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/FastSessionServices.java b/hibernate-core/src/main/java/org/hibernate/internal/FastSessionServices.java index c9c0705a32..2165401b68 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/FastSessionServices.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/FastSessionServices.java @@ -68,6 +68,10 @@ import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder; import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptor; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_LOCK_SCOPE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_LOCK_TIMEOUT; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_SHARED_CACHE_STORE_MODE; import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_SCOPE; import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_TIMEOUT; import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_RETRIEVE_MODE; @@ -274,20 +278,29 @@ public final class FastSessionServices { HashMap p = new HashMap<>(); //Static defaults: - p.put( AvailableSettings.FLUSH_MODE, FlushMode.AUTO.name() ); - p.put( JPA_LOCK_SCOPE, PessimisticLockScope.EXTENDED.name() ); - p.put( JPA_LOCK_TIMEOUT, LockOptions.WAIT_FOREVER ); - p.put( JPA_SHARED_CACHE_RETRIEVE_MODE, CacheModeHelper.DEFAULT_RETRIEVE_MODE ); - p.put( JPA_SHARED_CACHE_STORE_MODE, CacheModeHelper.DEFAULT_STORE_MODE ); + p.putIfAbsent( AvailableSettings.FLUSH_MODE, FlushMode.AUTO.name() ); + p.putIfAbsent( JPA_LOCK_SCOPE, PessimisticLockScope.EXTENDED.name() ); + p.putIfAbsent( JAKARTA_JPA_LOCK_SCOPE, PessimisticLockScope.EXTENDED.name() ); + p.putIfAbsent( JPA_LOCK_TIMEOUT, LockOptions.WAIT_FOREVER ); + p.putIfAbsent( JAKARTA_JPA_LOCK_TIMEOUT, LockOptions.WAIT_FOREVER ); + p.putIfAbsent( JPA_SHARED_CACHE_RETRIEVE_MODE, CacheModeHelper.DEFAULT_RETRIEVE_MODE ); + p.putIfAbsent( JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE, CacheModeHelper.DEFAULT_RETRIEVE_MODE ); + p.putIfAbsent( JPA_SHARED_CACHE_STORE_MODE, CacheModeHelper.DEFAULT_STORE_MODE ); + p.putIfAbsent( JAKARTA_JPA_SHARED_CACHE_STORE_MODE, CacheModeHelper.DEFAULT_STORE_MODE ); //Defaults defined by SessionFactory configuration: final String[] ENTITY_MANAGER_SPECIFIC_PROPERTIES = { JPA_LOCK_SCOPE, + JAKARTA_JPA_LOCK_SCOPE, JPA_LOCK_TIMEOUT, + JAKARTA_JPA_LOCK_TIMEOUT, AvailableSettings.FLUSH_MODE, JPA_SHARED_CACHE_RETRIEVE_MODE, + JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE, JPA_SHARED_CACHE_STORE_MODE, - QueryHints.SPEC_HINT_TIMEOUT + JAKARTA_JPA_SHARED_CACHE_STORE_MODE, + QueryHints.SPEC_HINT_TIMEOUT, + QueryHints.JAKARTA_SPEC_HINT_TIMEOUT }; final Map properties = sf.getProperties(); for ( String key : ENTITY_MANAGER_SPECIFIC_PROPERTIES ) { @@ -327,11 +340,19 @@ public final class FastSessionServices { } private static CacheRetrieveMode determineCacheRetrieveMode(Map settings) { - return ( CacheRetrieveMode ) settings.get( JPA_SHARED_CACHE_RETRIEVE_MODE ); + final CacheRetrieveMode cacheRetrieveMode = (CacheRetrieveMode) settings.get( JPA_SHARED_CACHE_RETRIEVE_MODE ); + if ( cacheRetrieveMode == null ) { + return (CacheRetrieveMode) settings.get( JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE ); + } + return cacheRetrieveMode; } private static CacheStoreMode determineCacheStoreMode(Map settings) { - return ( CacheStoreMode ) settings.get( JPA_SHARED_CACHE_STORE_MODE ); + final CacheStoreMode cacheStoreMode = (CacheStoreMode) settings.get( JPA_SHARED_CACHE_STORE_MODE ); + if ( cacheStoreMode == null ) { + return ( CacheStoreMode ) settings.get( JAKARTA_JPA_SHARED_CACHE_STORE_MODE ); + } + return cacheStoreMode; } public ConnectionObserverStatsBridge getDefaultJdbcObserver() { diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java index 3de20049db..7387f10083 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java @@ -164,7 +164,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { private final String name; private final String uuid; - private transient volatile boolean isClosed; + private transient volatile Status status = Status.OPEN; private final transient SessionFactoryObserverChain observer = new SessionFactoryObserverChain(); @@ -235,12 +235,17 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { this.properties = new HashMap<>(); this.properties.putAll( serviceRegistry.getService( ConfigurationService.class ).getSettings() ); - if ( !properties.containsKey( AvailableSettings.JPA_VALIDATION_FACTORY ) ) { + if ( !properties.containsKey( AvailableSettings.JPA_VALIDATION_FACTORY ) + && !properties.containsKey( AvailableSettings.JAKARTA_JPA_VALIDATION_FACTORY ) ) { if ( getSessionFactoryOptions().getValidatorFactoryReference() != null ) { properties.put( AvailableSettings.JPA_VALIDATION_FACTORY, getSessionFactoryOptions().getValidatorFactoryReference() ); + properties.put( + AvailableSettings.JAKARTA_JPA_VALIDATION_FACTORY, + getSessionFactoryOptions().getValidatorFactoryReference() + ); } } @@ -588,7 +593,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { } protected void validateNotClosed() { - if ( isClosed ) { + if ( status == Status.CLOSED ) { throw new IllegalStateException( "EntityManagerFactory is closed" ); } } @@ -663,7 +668,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { } private Session buildEntityManager(final SynchronizationType synchronizationType, final Map map) { - assert !isClosed; + assert status != Status.CLOSED; SessionBuilderImplementor builder = withOptions(); if ( synchronizationType == SynchronizationType.SYNCHRONIZED ) { @@ -732,7 +737,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { @Override public boolean isOpen() { - return !isClosed; + return status != Status.CLOSED; } @Override @@ -809,9 +814,10 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { * collector release the memory. * @throws HibernateException */ + @Override public void close() throws HibernateException { synchronized (this) { - if ( isClosed ) { + if ( status != Status.OPEN ) { if ( getSessionFactoryOptions().getJpaCompliance().isJpaClosedComplianceEnabled() ) { throw new IllegalStateException( "EntityManagerFactory is already closed" ); } @@ -820,46 +826,54 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { return; } - isClosed = true; + status = Status.CLOSING; } - LOG.closing(); - observer.sessionFactoryClosing( this ); + try { + LOG.closing(); + observer.sessionFactoryClosing( this ); // NOTE : the null checks below handle cases where close is called from // a failed attempt to create the SessionFactory - if ( cacheAccess != null ) { - cacheAccess.close(); - } + if ( cacheAccess != null ) { + cacheAccess.close(); + } - if ( runtimeMetamodels != null && runtimeMetamodels.getMappingMetamodel() != null ) { - final JdbcConnectionAccess jdbcConnectionAccess = jdbcServices.getBootstrapJdbcConnectionAccess(); - runtimeMetamodels.getMappingMetamodel().visitEntityDescriptors( - entityPersister -> { - if ( entityPersister.getSqmMultiTableMutationStrategy() != null ) { - entityPersister.getSqmMultiTableMutationStrategy().release( this, jdbcConnectionAccess ); + if ( runtimeMetamodels != null && runtimeMetamodels.getMappingMetamodel() != null ) { + final JdbcConnectionAccess jdbcConnectionAccess = jdbcServices.getBootstrapJdbcConnectionAccess(); + runtimeMetamodels.getMappingMetamodel().visitEntityDescriptors( + entityPersister -> { + if ( entityPersister.getSqmMultiTableMutationStrategy() != null ) { + entityPersister.getSqmMultiTableMutationStrategy().release( + this, + jdbcConnectionAccess + ); + } } - } + ); + ( (MappingMetamodelImpl) runtimeMetamodels.getMappingMetamodel() ).close(); + } + + if ( queryEngine != null ) { + queryEngine.close(); + } + + if ( delayedDropAction != null ) { + delayedDropAction.perform( serviceRegistry ); + } + + SessionFactoryRegistry.INSTANCE.removeSessionFactory( + getUuid(), + name, + settings.isSessionFactoryNameAlsoJndiName(), + serviceRegistry.getService( JndiService.class ) ); - ( (MappingMetamodelImpl) runtimeMetamodels.getMappingMetamodel() ).close(); } - - if ( queryEngine != null ) { - queryEngine.close(); + finally { + status = Status.CLOSED; } - if ( delayedDropAction != null ) { - delayedDropAction.perform( serviceRegistry ); - } - - SessionFactoryRegistry.INSTANCE.removeSessionFactory( - getUuid(), - name, - settings.isSessionFactoryNameAlsoJndiName(), - serviceRegistry.getService( JndiService.class ) - ); - observer.sessionFactoryClosed( this ); serviceRegistry.destroy(); } @@ -956,8 +970,9 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { getMetamodel().addNamedEntityGraph( graphName, (RootGraphImplementor) entityGraph ); } + @Override public boolean isClosed() { - return isClosed; + return status == Status.CLOSED; } private transient StatisticsImplementor statistics; @@ -1624,6 +1639,8 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { private void maskOutSensitiveInformation(Map props) { maskOutIfSet( props, AvailableSettings.JPA_JDBC_USER ); maskOutIfSet( props, AvailableSettings.JPA_JDBC_PASSWORD ); + maskOutIfSet( props, AvailableSettings.JAKARTA_JPA_JDBC_USER ); + maskOutIfSet( props, AvailableSettings.JAKARTA_JPA_JDBC_PASSWORD ); maskOutIfSet( props, AvailableSettings.USER ); maskOutIfSet( props, AvailableSettings.PASS ); } @@ -1658,4 +1675,9 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { return this.fastSessionServices; } + private enum Status { + OPEN, + CLOSING, + CLOSED; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java index dc98d0435e..75618f249c 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java @@ -139,6 +139,10 @@ import org.hibernate.stat.SessionStatistics; import org.hibernate.stat.internal.SessionStatisticsImpl; import org.hibernate.stat.spi.StatisticsImplementor; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_LOCK_SCOPE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_LOCK_TIMEOUT; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_SHARED_CACHE_STORE_MODE; import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_SCOPE; import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_TIMEOUT; import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_RETRIEVE_MODE; @@ -269,8 +273,28 @@ public class SessionImpl if ( ( queryTimeout = getSessionProperty( QueryHints.SPEC_HINT_TIMEOUT ) ) != null ) { query.setHint( QueryHints.SPEC_HINT_TIMEOUT, queryTimeout ); } + final Object jakartaQueryTimeout; + if ( ( jakartaQueryTimeout = getSessionProperty( QueryHints.JAKARTA_SPEC_HINT_TIMEOUT ) ) != null ) { + query.setHint( QueryHints.JAKARTA_SPEC_HINT_TIMEOUT, jakartaQueryTimeout ); + } final Object lockTimeout; - if ( ( lockTimeout = getSessionProperty( JPA_LOCK_TIMEOUT ) ) != null ) { + final Object jpaLockTimeout = getSessionProperty( JPA_LOCK_TIMEOUT ); + if ( jpaLockTimeout == null ) { + lockTimeout = getSessionProperty( JAKARTA_JPA_LOCK_TIMEOUT ); + } + else if ( Integer.valueOf( LockOptions.WAIT_FOREVER ).equals( jpaLockTimeout ) ) { + final Object jakartaLockTimeout = getSessionProperty( JAKARTA_JPA_LOCK_TIMEOUT ); + if ( jakartaLockTimeout == null ) { + lockTimeout = jpaLockTimeout; + } + else { + lockTimeout = jakartaLockTimeout; + } + } + else { + lockTimeout = jpaLockTimeout; + } + if ( lockTimeout != null ) { query.setHint( JPA_LOCK_TIMEOUT, lockTimeout ); } } @@ -2323,11 +2347,19 @@ public class SessionImpl } private static CacheRetrieveMode determineCacheRetrieveMode(Map settings) { - return ( CacheRetrieveMode ) settings.get( JPA_SHARED_CACHE_RETRIEVE_MODE ); + final CacheRetrieveMode cacheRetrieveMode = (CacheRetrieveMode) settings.get( JPA_SHARED_CACHE_RETRIEVE_MODE ); + if ( cacheRetrieveMode == null ) { + return (CacheRetrieveMode) settings.get( JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE ); + } + return cacheRetrieveMode; } private static CacheStoreMode determineCacheStoreMode(Map settings) { - return ( CacheStoreMode ) settings.get( JPA_SHARED_CACHE_STORE_MODE ); + final CacheStoreMode cacheStoreMode = (CacheStoreMode) settings.get( JPA_SHARED_CACHE_STORE_MODE ); + if ( cacheStoreMode == null ) { + return ( CacheStoreMode ) settings.get( JAKARTA_JPA_SHARED_CACHE_STORE_MODE ); + } + return cacheStoreMode; } private void checkTransactionNeededForUpdateOperation() { @@ -2485,10 +2517,14 @@ public class SessionImpl if ( AvailableSettings.FLUSH_MODE.equals( propertyName ) ) { setHibernateFlushMode( ConfigurationHelper.getFlushMode( value, FlushMode.AUTO ) ); } - else if ( JPA_LOCK_SCOPE.equals( propertyName ) || JPA_LOCK_TIMEOUT.equals( propertyName ) ) { + else if ( JPA_LOCK_SCOPE.equals( propertyName ) || JPA_LOCK_TIMEOUT.equals( propertyName ) + || JAKARTA_JPA_LOCK_SCOPE.equals( propertyName ) || JAKARTA_JPA_LOCK_TIMEOUT.equals( propertyName ) ) { LockOptionsHelper.applyPropertiesToLockOptions( properties, this::getLockOptionsForWrite ); } - else if ( JPA_SHARED_CACHE_RETRIEVE_MODE.equals( propertyName ) || JPA_SHARED_CACHE_STORE_MODE.equals( propertyName ) ) { + else if ( JPA_SHARED_CACHE_RETRIEVE_MODE.equals( propertyName ) + || JPA_SHARED_CACHE_STORE_MODE.equals( propertyName ) + || JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE.equals( propertyName ) + || JAKARTA_JPA_SHARED_CACHE_STORE_MODE.equals( propertyName ) ) { setCacheMode( CacheModeHelper.interpretCacheMode( determineCacheStoreMode( properties ), diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/QueryHints.java b/hibernate-core/src/main/java/org/hibernate/jpa/QueryHints.java index b71d4cdf35..47c42a7a4f 100644 --- a/hibernate-core/src/main/java/org/hibernate/jpa/QueryHints.java +++ b/hibernate-core/src/main/java/org/hibernate/jpa/QueryHints.java @@ -23,6 +23,7 @@ import static org.hibernate.annotations.QueryHints.NATIVE_SPACES; import static org.hibernate.annotations.QueryHints.PASS_DISTINCT_THROUGH; import static org.hibernate.annotations.QueryHints.READ_ONLY; import static org.hibernate.annotations.QueryHints.TIMEOUT_HIBERNATE; +import static org.hibernate.annotations.QueryHints.TIMEOUT_JAKARTA_JPA; import static org.hibernate.annotations.QueryHints.TIMEOUT_JPA; /** @@ -42,6 +43,11 @@ public class QueryHints { */ public static final String SPEC_HINT_TIMEOUT = TIMEOUT_JPA; + /** + * The hint key for specifying a query timeout per JPA, which defines the timeout in milliseconds + */ + public static final String JAKARTA_SPEC_HINT_TIMEOUT = TIMEOUT_JAKARTA_JPA; + /** * The hint key for specifying a comment which is to be embedded into the SQL sent to the database. */ @@ -100,6 +106,22 @@ public class QueryHints { */ public static final String HINT_LOADGRAPH = GraphSemantic.LOAD.getJpaHintName(); + /** + * Hint providing a "fetchgraph" EntityGraph. Attributes explicitly specified as AttributeNodes are treated as + * FetchType.EAGER (via join fetch or subsequent select). + * + * Note: Currently, attributes that are not specified are treated as FetchType.LAZY or FetchType.EAGER depending + * on the attribute's definition in metadata, rather than forcing FetchType.LAZY. + */ + public static final String JAKARTA_HINT_FETCHGRAPH = GraphSemantic.FETCH.getJakartaJpaHintName(); + + /** + * Hint providing a "loadgraph" EntityGraph. Attributes explicitly specified as AttributeNodes are treated as + * FetchType.EAGER (via join fetch or subsequent select). Attributes that are not specified are treated as + * FetchType.LAZY or FetchType.EAGER depending on the attribute's definition in metadata + */ + public static final String JAKARTA_HINT_LOADGRAPH = GraphSemantic.LOAD.getJakartaJpaHintName(); + public static final String HINT_FOLLOW_ON_LOCKING = FOLLOW_ON_LOCKING; public static final String HINT_PASS_DISTINCT_THROUGH = PASS_DISTINCT_THROUGH; @@ -113,6 +135,7 @@ public class QueryHints { HashSet hints = new HashSet<>(); hints.add( HINT_TIMEOUT ); hints.add( SPEC_HINT_TIMEOUT ); + hints.add( JAKARTA_SPEC_HINT_TIMEOUT ); hints.add( HINT_COMMENT ); hints.add( HINT_FETCH_SIZE ); hints.add( HINT_CACHE_REGION ); @@ -123,6 +146,8 @@ public class QueryHints { hints.add( HINT_NATIVE_LOCKMODE ); hints.add( HINT_FETCHGRAPH ); hints.add( HINT_LOADGRAPH ); + hints.add( JAKARTA_HINT_FETCHGRAPH ); + hints.add( JAKARTA_HINT_LOADGRAPH ); hints.add( HINT_NATIVE_SPACES ); return java.util.Collections.unmodifiableSet( hints ); } diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java index eb992b16b6..f980ca9dfd 100644 --- a/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java @@ -92,6 +92,15 @@ import static org.hibernate.cfg.AvailableSettings.DRIVER; import static org.hibernate.cfg.AvailableSettings.JACC_CONTEXT_ID; import static org.hibernate.cfg.AvailableSettings.JACC_ENABLED; import static org.hibernate.cfg.AvailableSettings.JACC_PREFIX; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_JDBC_DRIVER; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_JDBC_PASSWORD; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_JDBC_URL; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_JDBC_USER; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_JTA_DATASOURCE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_NON_JTA_DATASOURCE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_SHARED_CACHE_MODE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_TRANSACTION_TYPE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_VALIDATION_MODE; import static org.hibernate.cfg.AvailableSettings.JPA_JDBC_DRIVER; import static org.hibernate.cfg.AvailableSettings.JPA_JDBC_PASSWORD; import static org.hibernate.cfg.AvailableSettings.JPA_JDBC_URL; @@ -260,7 +269,13 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil metamodelBuilder.getBootstrapContext() ); - withValidatorFactory( configurationValues.get( org.hibernate.cfg.AvailableSettings.JPA_VALIDATION_FACTORY ) ); + final Object validatorFactory = configurationValues.get( org.hibernate.cfg.AvailableSettings.JPA_VALIDATION_FACTORY ); + if ( validatorFactory == null ) { + withValidatorFactory( configurationValues.get( org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_VALIDATION_FACTORY ) ); + } + else { + withValidatorFactory( validatorFactory ); + } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // push back class transformation to the environment; for the time being this only has any effect in EE @@ -574,20 +589,30 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil // normalize ValidationMode final Object intgValidationMode = integrationSettingsCopy.remove( JPA_VALIDATION_MODE ); + final Object jakartaIntgValidationMode = integrationSettingsCopy.remove( JAKARTA_JPA_VALIDATION_MODE ); if ( intgValidationMode != null ) { mergedSettings.configurationValues.put( JPA_VALIDATION_MODE, intgValidationMode ); } + else if ( jakartaIntgValidationMode != null ) { + mergedSettings.configurationValues.put( JAKARTA_JPA_VALIDATION_MODE, jakartaIntgValidationMode ); + } else if ( persistenceUnit.getValidationMode() != null ) { mergedSettings.configurationValues.put( JPA_VALIDATION_MODE, persistenceUnit.getValidationMode() ); + mergedSettings.configurationValues.put( JAKARTA_JPA_VALIDATION_MODE, persistenceUnit.getValidationMode() ); } // normalize SharedCacheMode final Object intgCacheMode = integrationSettingsCopy.remove( JPA_SHARED_CACHE_MODE ); + final Object jakartaIntgCacheMode = integrationSettingsCopy.remove( JAKARTA_JPA_SHARED_CACHE_MODE ); if ( intgCacheMode != null ) { mergedSettings.configurationValues.put( JPA_SHARED_CACHE_MODE, intgCacheMode ); } + else if ( jakartaIntgCacheMode != null ) { + mergedSettings.configurationValues.put( JAKARTA_JPA_SHARED_CACHE_MODE, jakartaIntgCacheMode ); + } else if ( persistenceUnit.getSharedCacheMode() != null ) { mergedSettings.configurationValues.put( JPA_SHARED_CACHE_MODE, persistenceUnit.getSharedCacheMode() ); + mergedSettings.configurationValues.put( JAKARTA_JPA_SHARED_CACHE_MODE, persistenceUnit.getSharedCacheMode() ); } // Apply all "integration overrides" as the last step. By specification, @@ -620,16 +645,20 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil final Object effectiveUser = NullnessHelper.coalesceSuppliedValues( () -> integrationSettingsCopy.remove( USER ), () -> integrationSettingsCopy.remove( JPA_JDBC_USER ), + () -> integrationSettingsCopy.remove( JAKARTA_JPA_JDBC_USER ), () -> extractPuProperty( persistenceUnit, USER ), - () -> extractPuProperty( persistenceUnit, JPA_JDBC_USER ) + () -> extractPuProperty( persistenceUnit, JPA_JDBC_USER ), + () -> extractPuProperty( persistenceUnit, JAKARTA_JPA_JDBC_USER ) ); //noinspection unchecked final Object effectivePass = NullnessHelper.coalesceSuppliedValues( () -> integrationSettingsCopy.remove( PASS ), () -> integrationSettingsCopy.remove( JPA_JDBC_PASSWORD ), + () -> integrationSettingsCopy.remove( JAKARTA_JPA_JDBC_PASSWORD ), () -> extractPuProperty( persistenceUnit, PASS ), - () -> extractPuProperty( persistenceUnit, JPA_JDBC_PASSWORD ) + () -> extractPuProperty( persistenceUnit, JPA_JDBC_PASSWORD ), + () -> extractPuProperty( persistenceUnit, JAKARTA_JPA_JDBC_PASSWORD ) ); if ( effectiveUser != null || effectivePass != null ) { @@ -647,11 +676,13 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil if ( effectiveUser != null ) { mergedSettings.configurationValues.put( USER, effectiveUser ); mergedSettings.configurationValues.put( JPA_JDBC_USER, effectiveUser ); + mergedSettings.configurationValues.put( JAKARTA_JPA_JDBC_USER, effectiveUser ); } if ( effectivePass != null ) { mergedSettings.configurationValues.put( PASS, effectivePass ); mergedSettings.configurationValues.put( JPA_JDBC_PASSWORD, effectivePass ); + mergedSettings.configurationValues.put( JAKARTA_JPA_JDBC_PASSWORD, effectivePass ); } } @@ -664,7 +695,10 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil MergedSettings mergedSettings) { PersistenceUnitTransactionType txnType = null; - final Object intgTxnType = integrationSettingsCopy.remove( JPA_TRANSACTION_TYPE ); + Object intgTxnType = integrationSettingsCopy.remove( JPA_TRANSACTION_TYPE ); + if ( intgTxnType == null ) { + intgTxnType = integrationSettingsCopy.remove( JAKARTA_JPA_TRANSACTION_TYPE ); + } if ( intgTxnType != null ) { txnType = PersistenceUnitTransactionTypeHelper.interpretTransactionType( intgTxnType ); @@ -673,7 +707,10 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil txnType = persistenceUnit.getTransactionType(); } else { - final Object puPropTxnType = mergedSettings.configurationValues.get( JPA_TRANSACTION_TYPE ); + Object puPropTxnType = mergedSettings.configurationValues.get( JPA_TRANSACTION_TYPE ); + if ( puPropTxnType == null ) { + puPropTxnType = mergedSettings.configurationValues.get( JAKARTA_JPA_TRANSACTION_TYPE ); + } if ( puPropTxnType != null ) { txnType = PersistenceUnitTransactionTypeHelper.interpretTransactionType( puPropTxnType ); } @@ -764,6 +801,21 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil } } + if ( integrationSettingsCopy.containsKey( JAKARTA_JPA_JTA_DATASOURCE ) ) { + final Object dataSourceRef = integrationSettingsCopy.remove( JAKARTA_JPA_JTA_DATASOURCE ); + if ( dataSourceRef != null ) { + applyDataSource( + dataSourceRef, + true, + integrationSettingsCopy, + mergedSettings + ); + + // EARLY EXIT!! + return; + } + } + if ( integrationSettingsCopy.containsKey( JPA_NON_JTA_DATASOURCE ) ) { final Object dataSourceRef = integrationSettingsCopy.remove( JPA_NON_JTA_DATASOURCE ); @@ -778,6 +830,20 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil return; } + if ( integrationSettingsCopy.containsKey( JAKARTA_JPA_NON_JTA_DATASOURCE ) ) { + final Object dataSourceRef = integrationSettingsCopy.remove( JAKARTA_JPA_NON_JTA_DATASOURCE ); + + applyDataSource( + dataSourceRef, + false, + integrationSettingsCopy, + mergedSettings + ); + + // EARLY EXIT!! + return; + } + if ( integrationSettingsCopy.containsKey( URL ) ) { // these have precedence over the JPA ones final Object integrationJdbcUrl = integrationSettingsCopy.get( URL ); @@ -788,8 +854,10 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil NullnessHelper.coalesceSuppliedValues( () -> ConfigurationHelper.getString( DRIVER, integrationSettingsCopy ), () -> ConfigurationHelper.getString( JPA_JDBC_DRIVER, integrationSettingsCopy ), + () -> ConfigurationHelper.getString( JAKARTA_JPA_JDBC_DRIVER, integrationSettingsCopy ), () -> ConfigurationHelper.getString( DRIVER, mergedSettings.configurationValues ), - () -> ConfigurationHelper.getString( JPA_JDBC_DRIVER, mergedSettings.configurationValues ) + () -> ConfigurationHelper.getString( JPA_JDBC_DRIVER, mergedSettings.configurationValues ), + () -> ConfigurationHelper.getString( JAKARTA_JPA_JDBC_DRIVER, mergedSettings.configurationValues ) ), integrationSettingsCopy, mergedSettings @@ -820,6 +888,26 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil } } + if ( integrationSettingsCopy.containsKey( JAKARTA_JPA_JDBC_URL ) ) { + final Object integrationJdbcUrl = integrationSettingsCopy.get( JAKARTA_JPA_JDBC_URL ); + + if ( integrationJdbcUrl != null ) { + //noinspection unchecked + applyJdbcSettings( + integrationJdbcUrl, + NullnessHelper.coalesceSuppliedValues( + () -> ConfigurationHelper.getString( JAKARTA_JPA_JDBC_DRIVER, integrationSettingsCopy ), + () -> ConfigurationHelper.getString( JAKARTA_JPA_JDBC_DRIVER, mergedSettings.configurationValues ) + ), + integrationSettingsCopy, + mergedSettings + ); + + // EARLY EXIT!! + return; + } + } + if ( persistenceUnit.getJtaDataSource() != null ) { applyDataSource( persistenceUnit.getJtaDataSource(), @@ -876,6 +964,22 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil } } + if ( mergedSettings.configurationValues.containsKey( JAKARTA_JPA_JDBC_URL ) ) { + final Object url = mergedSettings.configurationValues.get( JAKARTA_JPA_JDBC_URL ); + + if ( url != null && ( ! ( url instanceof String ) || StringHelper.isNotEmpty( (String) url ) ) ) { + applyJdbcSettings( + url, + ConfigurationHelper.getString( JAKARTA_JPA_JDBC_DRIVER, mergedSettings.configurationValues ), + integrationSettingsCopy, + mergedSettings + ); + + // EARLY EXIT!! + return; + } + } + // any other conditions to account for? } @@ -896,31 +1000,48 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil // add to EMF properties (questionable - see HHH-13432) final String emfKey; final String inverseEmfKey; + final String jakartaEmfKey; + final String jakartaInverseEmfKey; if ( isJta ) { emfKey = JPA_JTA_DATASOURCE; + jakartaEmfKey = JAKARTA_JPA_JTA_DATASOURCE; inverseEmfKey = JPA_NON_JTA_DATASOURCE; + jakartaInverseEmfKey = JAKARTA_JPA_NON_JTA_DATASOURCE; } else { emfKey = JPA_NON_JTA_DATASOURCE; + jakartaEmfKey = JAKARTA_JPA_NON_JTA_DATASOURCE; inverseEmfKey = JPA_JTA_DATASOURCE; + jakartaInverseEmfKey = JAKARTA_JPA_JTA_DATASOURCE; } mergedSettings.configurationValues.put( emfKey, dataSourceRef ); + mergedSettings.configurationValues.put( jakartaEmfKey, dataSourceRef ); // clear any settings logically overridden by this datasource cleanUpConfigKeys( integrationSettingsCopy, mergedSettings, inverseEmfKey, + jakartaInverseEmfKey, JPA_JDBC_DRIVER, + JAKARTA_JPA_JDBC_DRIVER, DRIVER, JPA_JDBC_URL, + JAKARTA_JPA_JDBC_URL, URL ); // clean-up the entries in the "integration overrides" so they do not get get picked // up in the general "integration overrides" handling - cleanUpConfigKeys( integrationSettingsCopy, DATASOURCE, JPA_JTA_DATASOURCE, JPA_NON_JTA_DATASOURCE ); + cleanUpConfigKeys( + integrationSettingsCopy, + DATASOURCE, + JPA_JTA_DATASOURCE, + JAKARTA_JPA_JTA_DATASOURCE, + JPA_NON_JTA_DATASOURCE, + JAKARTA_JPA_NON_JTA_DATASOURCE + ); // add under Hibernate's DATASOURCE setting where the ConnectionProvider will find it mergedSettings.configurationValues.put( DATASOURCE, dataSourceRef ); @@ -954,14 +1075,17 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil MergedSettings mergedSettings) { mergedSettings.configurationValues.put( URL, url ); mergedSettings.configurationValues.put( JPA_JDBC_URL, url ); + mergedSettings.configurationValues.put( JAKARTA_JPA_JDBC_URL, url ); if ( driver != null ) { mergedSettings.configurationValues.put( DRIVER, driver ); mergedSettings.configurationValues.put( JPA_JDBC_DRIVER, driver ); + mergedSettings.configurationValues.put( JAKARTA_JPA_JDBC_DRIVER, driver ); } else { mergedSettings.configurationValues.remove( DRIVER ); mergedSettings.configurationValues.remove( JPA_JDBC_DRIVER ); + mergedSettings.configurationValues.remove( JAKARTA_JPA_JDBC_DRIVER ); } // clean up the integration-map values @@ -969,12 +1093,16 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil integrationSettingsCopy, DRIVER, JPA_JDBC_DRIVER, + JAKARTA_JPA_JDBC_DRIVER, URL, JPA_JDBC_URL, + JAKARTA_JPA_JDBC_URL, USER, JPA_JDBC_USER, + JAKARTA_JPA_JDBC_USER, PASS, - JPA_JDBC_PASSWORD + JPA_JDBC_PASSWORD, + JAKARTA_JPA_JDBC_PASSWORD ); cleanUpConfigKeys( @@ -982,7 +1110,9 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil mergedSettings, DATASOURCE, JPA_JTA_DATASOURCE, - JPA_NON_JTA_DATASOURCE + JAKARTA_JPA_JTA_DATASOURCE, + JPA_NON_JTA_DATASOURCE, + JAKARTA_JPA_NON_JTA_DATASOURCE ); } diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java b/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java index 873b529c59..f80feb10e0 100644 --- a/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java +++ b/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/PersistenceXmlParser.java @@ -269,16 +269,29 @@ public class PersistenceXmlParser { if ( integration.containsKey( AvailableSettings.JPA_PERSISTENCE_PROVIDER ) ) { persistenceUnit.setProviderClassName( (String) integration.get( AvailableSettings.JPA_PERSISTENCE_PROVIDER ) ); } + else if ( integration.containsKey( AvailableSettings.JAKARTA_JPA_PERSISTENCE_PROVIDER ) ) { + persistenceUnit.setProviderClassName( (String) integration.get( AvailableSettings.JAKARTA_JPA_PERSISTENCE_PROVIDER ) ); + } if ( integration.containsKey( AvailableSettings.JPA_TRANSACTION_TYPE ) ) { String transactionType = (String) integration.get( AvailableSettings.JPA_TRANSACTION_TYPE ); persistenceUnit.setTransactionType( parseTransactionType( transactionType ) ); } + else if ( integration.containsKey( AvailableSettings.JAKARTA_JPA_TRANSACTION_TYPE ) ) { + String transactionType = (String) integration.get( AvailableSettings.JAKARTA_JPA_TRANSACTION_TYPE ); + persistenceUnit.setTransactionType( parseTransactionType( transactionType ) ); + } if ( integration.containsKey( AvailableSettings.JPA_JTA_DATASOURCE ) ) { persistenceUnit.setJtaDataSource( integration.get( AvailableSettings.JPA_JTA_DATASOURCE ) ); } + else if ( integration.containsKey( AvailableSettings.JAKARTA_JPA_JTA_DATASOURCE ) ) { + persistenceUnit.setJtaDataSource( integration.get( AvailableSettings.JAKARTA_JPA_JTA_DATASOURCE ) ); + } if ( integration.containsKey( AvailableSettings.JPA_NON_JTA_DATASOURCE ) ) { persistenceUnit.setNonJtaDataSource( integration.get( AvailableSettings.JPA_NON_JTA_DATASOURCE ) ); } + else if ( integration.containsKey( AvailableSettings.JAKARTA_JPA_NON_JTA_DATASOURCE ) ) { + persistenceUnit.setNonJtaDataSource( integration.get( AvailableSettings.JAKARTA_JPA_NON_JTA_DATASOURCE ) ); + } decodeTransactionType( persistenceUnit ); diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/boot/spi/ProviderChecker.java b/hibernate-core/src/main/java/org/hibernate/jpa/boot/spi/ProviderChecker.java index 2b4d57fc8c..4cd136809c 100644 --- a/hibernate-core/src/main/java/org/hibernate/jpa/boot/spi/ProviderChecker.java +++ b/hibernate-core/src/main/java/org/hibernate/jpa/boot/spi/ProviderChecker.java @@ -101,7 +101,10 @@ public final class ProviderChecker { if ( integration == null ) { return null; } - final String setting = (String) integration.get( AvailableSettings.JPA_PERSISTENCE_PROVIDER ); + String setting = (String) integration.get(AvailableSettings.JPA_PERSISTENCE_PROVIDER); + if ( setting == null ) { + setting = (String) integration.get(AvailableSettings.JAKARTA_JPA_PERSISTENCE_PROVIDER); + } return setting == null ? null : setting.trim(); } diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/internal/util/LockOptionsHelper.java b/hibernate-core/src/main/java/org/hibernate/jpa/internal/util/LockOptionsHelper.java index 20e1ea641b..621258df6d 100644 --- a/hibernate-core/src/main/java/org/hibernate/jpa/internal/util/LockOptionsHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/jpa/internal/util/LockOptionsHelper.java @@ -13,6 +13,8 @@ import javax.persistence.PessimisticLockScope; import org.hibernate.LockOptions; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_LOCK_SCOPE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_LOCK_TIMEOUT; import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_SCOPE; import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_TIMEOUT; @@ -31,7 +33,12 @@ public final class LockOptionsHelper { * @param lockOptionsSupplier The reference to the lock to modify */ public static void applyPropertiesToLockOptions(final Map props, final Supplier lockOptionsSupplier) { - Object lockScope = props.get( JPA_LOCK_SCOPE ); + String lockScopeHint = JPA_LOCK_SCOPE; + Object lockScope = props.get( lockScopeHint ); + if ( lockScope == null ) { + lockScopeHint = JAKARTA_JPA_LOCK_SCOPE; + lockScope = props.get( lockScopeHint ); + } if ( lockScope instanceof String && PessimisticLockScope.valueOf( (String) lockScope ) == PessimisticLockScope.EXTENDED ) { lockOptionsSupplier.get().setScope( true ); } @@ -40,10 +47,15 @@ public final class LockOptionsHelper { lockOptionsSupplier.get().setScope( extended ); } else if ( lockScope != null ) { - throw new PersistenceException( "Unable to parse " + JPA_LOCK_SCOPE + ": " + lockScope ); + throw new PersistenceException( "Unable to parse " + lockScopeHint + ": " + lockScope ); } - Object lockTimeout = props.get( JPA_LOCK_TIMEOUT ); + String timeoutHint = JPA_LOCK_TIMEOUT; + Object lockTimeout = props.get( timeoutHint ); + if (lockTimeout == null) { + timeoutHint = JAKARTA_JPA_LOCK_TIMEOUT; + lockTimeout = props.get( timeoutHint ); + } int timeout = 0; boolean timeoutSet = false; if ( lockTimeout instanceof String ) { @@ -55,7 +67,7 @@ public final class LockOptionsHelper { timeoutSet = true; } else if ( lockTimeout != null ) { - throw new PersistenceException( "Unable to parse " + JPA_LOCK_TIMEOUT + ": " + lockTimeout ); + throw new PersistenceException( "Unable to parse " + timeoutHint + ": " + lockTimeout ); } if ( timeoutSet ) { diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 289bd59633..b2cd1506c2 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -263,6 +263,7 @@ public abstract class AbstractEntityPersister private static final CoreMessageLogger LOG = CoreLogging.messageLogger( AbstractEntityPersister.class ); public static final String ENTITY_CLASS = "class"; + public static final String VERSION_COLUMN_ALIAS = "version_"; private final String sqlAliasStem; private EntityMappingType rootEntityDescriptor; @@ -2018,7 +2019,7 @@ public abstract class AbstractEntityPersister SimpleSelect select = new SimpleSelect( getFactory().getJdbcServices().getDialect() ) .setTableName( getVersionedTableName() ); if ( isVersioned() ) { - select.addColumn( versionColumnName ); + select.addColumn( getVersionColumnName(), VERSION_COLUMN_ALIAS ); } else { select.addColumns( rootTableKeyColumnNames ); @@ -2244,7 +2245,7 @@ public abstract class AbstractEntityPersister if ( !isVersioned() ) { return this; } - return getVersionType().nullSafeGet( rs, getVersionColumnName(), session, null ); + return getVersionType().nullSafeGet( rs, VERSION_COLUMN_ALIAS, session, null ); } finally { session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( rs, st ); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java index 3c525d8808..5c8c415fd0 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java @@ -871,7 +871,16 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { } public String getSubclassForDiscriminatorValue(Object value) { - return subclassesByDiscriminatorValue.get( value ); + if ( value == null ) { + return subclassesByDiscriminatorValue.get( NULL_DISCRIMINATOR ); + } + else { + String result = subclassesByDiscriminatorValue.get( value ); + if ( result == null ) { + result = subclassesByDiscriminatorValue.get( NOT_NULL_DISCRIMINATOR ); + } + return result; + } } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java b/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java index f94521c927..229ec8639e 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java +++ b/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java @@ -77,6 +77,10 @@ import org.hibernate.transform.ResultTransformer; import org.jboss.logging.Logger; import static org.hibernate.LockOptions.WAIT_FOREVER; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_LOCK_SCOPE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_LOCK_TIMEOUT; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_SHARED_CACHE_STORE_MODE; import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_SCOPE; import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_TIMEOUT; import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_RETRIEVE_MODE; @@ -94,6 +98,9 @@ import static org.hibernate.jpa.QueryHints.HINT_LOADGRAPH; import static org.hibernate.jpa.QueryHints.HINT_NATIVE_SPACES; import static org.hibernate.jpa.QueryHints.HINT_READONLY; import static org.hibernate.jpa.QueryHints.HINT_TIMEOUT; +import static org.hibernate.jpa.QueryHints.JAKARTA_HINT_FETCHGRAPH; +import static org.hibernate.jpa.QueryHints.JAKARTA_HINT_LOADGRAPH; +import static org.hibernate.jpa.QueryHints.JAKARTA_SPEC_HINT_TIMEOUT; import static org.hibernate.jpa.QueryHints.SPEC_HINT_TIMEOUT; /** @@ -905,16 +912,19 @@ public abstract class AbstractProducedQuery implements QueryImplementor { if ( queryTimeout != null ) { hints.put( HINT_TIMEOUT, queryTimeout ); hints.put( SPEC_HINT_TIMEOUT, queryTimeout * 1000 ); + hints.put( JAKARTA_SPEC_HINT_TIMEOUT, queryTimeout * 1000 ); } final LockOptions lockOptions = getLockOptions(); final int lockOptionsTimeOut = lockOptions.getTimeOut(); if ( lockOptionsTimeOut != WAIT_FOREVER ) { hints.put( JPA_LOCK_TIMEOUT, lockOptionsTimeOut ); + hints.put( JAKARTA_JPA_LOCK_TIMEOUT, lockOptionsTimeOut ); } if ( lockOptions.getScope() ) { hints.put( JPA_LOCK_SCOPE, lockOptions.getScope() ); + hints.put( JAKARTA_JPA_LOCK_SCOPE, lockOptions.getScope() ); } if ( lockOptions.hasAliasSpecificLockModes() && canApplyAliasSpecificLockModeHints() ) { @@ -932,9 +942,11 @@ public abstract class AbstractProducedQuery implements QueryImplementor { final CacheMode cacheMode = getQueryOptions().getCacheMode(); if ( cacheMode != null ) { - hints.put( HINT_CACHE_MODE, cacheMode ); - hints.put( JPA_SHARED_CACHE_RETRIEVE_MODE, cacheMode.getJpaRetrieveMode() ); - hints.put( JPA_SHARED_CACHE_STORE_MODE, cacheMode.getJpaStoreMode() ); + putIfNotNull( hints, HINT_CACHE_MODE, cacheMode ); + putIfNotNull( hints, JPA_SHARED_CACHE_RETRIEVE_MODE, cacheMode.getJpaRetrieveMode() ); + putIfNotNull( hints, JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE, cacheMode.getJpaRetrieveMode( ) ); + putIfNotNull( hints, JPA_SHARED_CACHE_STORE_MODE, cacheMode.getJpaStoreMode() ); + putIfNotNull( hints, JAKARTA_JPA_SHARED_CACHE_STORE_MODE, cacheMode.getJpaStoreMode() ); } if ( isCacheable() ) { @@ -975,12 +987,12 @@ public abstract class AbstractProducedQuery implements QueryImplementor { if ( HINT_TIMEOUT.equals( hintName ) ) { applied = applyTimeoutHint( ConfigurationHelper.getInteger( value ) ); } - else if ( SPEC_HINT_TIMEOUT.equals( hintName ) ) { + else if ( SPEC_HINT_TIMEOUT.equals( hintName ) || JAKARTA_SPEC_HINT_TIMEOUT.equals( hintName ) ) { // convert milliseconds to seconds int timeout = (int)Math.round( ConfigurationHelper.getInteger( value ).doubleValue() / 1000.0 ); applied = applyTimeoutHint( timeout ); } - else if ( JPA_LOCK_TIMEOUT.equals( hintName ) ) { + else if ( JPA_LOCK_TIMEOUT.equals( hintName ) || JAKARTA_JPA_LOCK_TIMEOUT.equals( hintName ) ) { applied = applyLockTimeoutHint( ConfigurationHelper.getInteger( value ) ); } else if ( HINT_COMMENT.equals( hintName ) ) { @@ -1004,11 +1016,11 @@ public abstract class AbstractProducedQuery implements QueryImplementor { else if ( HINT_CACHE_MODE.equals( hintName ) ) { applied = applyCacheModeHint( ConfigurationHelper.getCacheMode( value ) ); } - else if ( JPA_SHARED_CACHE_RETRIEVE_MODE.equals( hintName ) ) { + else if ( JPA_SHARED_CACHE_RETRIEVE_MODE.equals( hintName ) || JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE.equals( hintName ) ) { final CacheRetrieveMode retrieveMode = value != null ? CacheRetrieveMode.valueOf( value.toString() ) : null; applied = applyJpaCacheRetrieveMode( retrieveMode ); } - else if ( JPA_SHARED_CACHE_STORE_MODE.equals( hintName ) ) { + else if ( JPA_SHARED_CACHE_STORE_MODE.equals( hintName ) || JAKARTA_JPA_SHARED_CACHE_STORE_MODE.equals( hintName ) ) { final CacheStoreMode storeMode = value != null ? CacheStoreMode.valueOf( value.toString() ) : null; applied = applyJpaCacheStoreMode( storeMode ); } @@ -1036,7 +1048,10 @@ public abstract class AbstractProducedQuery implements QueryImplementor { applied = false; } } - else if ( HINT_FETCHGRAPH.equals( hintName ) || HINT_LOADGRAPH.equals( hintName ) ) { + else if ( HINT_FETCHGRAPH.equals( hintName ) + || HINT_LOADGRAPH.equals( hintName ) + || JAKARTA_HINT_FETCHGRAPH.equals( hintName ) + || JAKARTA_HINT_LOADGRAPH.equals( hintName ) ) { if ( value instanceof RootGraph ) { applyGraph( (RootGraph) value, GraphSemantic.fromJpaHintName( hintName ) ); } diff --git a/hibernate-core/src/main/java/org/hibernate/resource/beans/spi/ManagedBeanRegistryInitiator.java b/hibernate-core/src/main/java/org/hibernate/resource/beans/spi/ManagedBeanRegistryInitiator.java index aec15c390a..1e6760e8f7 100644 --- a/hibernate-core/src/main/java/org/hibernate/resource/beans/spi/ManagedBeanRegistryInitiator.java +++ b/hibernate-core/src/main/java/org/hibernate/resource/beans/spi/ManagedBeanRegistryInitiator.java @@ -60,7 +60,10 @@ public class ManagedBeanRegistryInitiator implements StandardServiceInitiator mappingPredicate = m -> { - String existingReferencingColumn = m.getReferencingColumnMetadata().getColumnIdentifier().getText(); - String existingReferencedTable = m.getReferencedColumnMetadata().getContainingTableInformation().getName().getTableName().getCanonicalName(); - return referencingColumn.equals( existingReferencingColumn ) && referencedTable.equals( existingReferencedTable ); - }; - Stream keyStream = StreamSupport.stream( tableInformation.getForeignKeys().spliterator(), false ); - Stream mappingStream = keyStream.flatMap( k -> StreamSupport.stream( k.getColumnReferenceMappings().spliterator(), false ) ); - boolean found = mappingStream.anyMatch( mappingPredicate ); - if ( found ) { + if (equivalentForeignKeyExistsInDatabase(tableInformation, referencingColumn, referencedTable)) { return true; } @@ -497,6 +489,17 @@ public abstract class AbstractSchemaMigrator implements SchemaMigrator { return tableInformation.getForeignKey( Identifier.toIdentifier( foreignKey.getName() ) ) != null; } + boolean equivalentForeignKeyExistsInDatabase(TableInformation tableInformation, String referencingColumn, String referencedTable) { + Predicate mappingPredicate = m -> { + String existingReferencingColumn = m.getReferencingColumnMetadata().getColumnIdentifier().getText(); + String existingReferencedTable = m.getReferencedColumnMetadata().getContainingTableInformation().getName().getTableName().getCanonicalName(); + return referencingColumn.equalsIgnoreCase( existingReferencingColumn ) && referencedTable.equalsIgnoreCase( existingReferencedTable ); + }; + Stream keyStream = StreamSupport.stream( tableInformation.getForeignKeys().spliterator(), false ); + Stream mappingStream = keyStream.flatMap( k -> StreamSupport.stream( k.getColumnReferenceMappings().spliterator(), false ) ); + return mappingStream.anyMatch( mappingPredicate ); + } + protected void checkExportIdentifier(Exportable exportable, Set exportIdentifiers) { final String exportIdentifier = exportable.getExportIdentifier(); if ( exportIdentifiers.contains( exportIdentifier ) ) { diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/Helper.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/Helper.java index 9d031c0a39..3ff225e51b 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/Helper.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/Helper.java @@ -12,6 +12,7 @@ import java.io.Writer; import java.net.URL; import java.sql.SQLException; import java.util.Map; +import java.util.regex.Pattern; import org.hibernate.boot.model.relational.Namespace; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; @@ -24,6 +25,8 @@ import org.hibernate.resource.transaction.spi.DdlTransactionIsolator; import org.hibernate.service.ServiceRegistry; import org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl; import org.hibernate.tool.schema.extract.spi.DatabaseInformation; +import org.hibernate.tool.schema.internal.exec.AbstractScriptSourceInput; +import org.hibernate.tool.schema.internal.exec.ScriptSourceInputAggregate; import org.hibernate.tool.schema.internal.exec.ScriptSourceInputFromFile; import org.hibernate.tool.schema.internal.exec.ScriptSourceInputFromReader; import org.hibernate.tool.schema.internal.exec.ScriptSourceInputFromUrl; @@ -41,6 +44,7 @@ import org.hibernate.tool.schema.spi.ScriptTargetOutput; public class Helper { private static final CoreMessageLogger log = CoreLogging.messageLogger( Helper.class ); + private static final Pattern COMMA_PATTERN = Pattern.compile( "\\s*,\\s*" ); public static ScriptSourceInput interpretScriptSourceSetting( Object scriptSourceSetting, @@ -53,24 +57,40 @@ public class Helper { final String scriptSourceSettingString = scriptSourceSetting.toString(); log.debugf( "Attempting to resolve script source setting : %s", scriptSourceSettingString ); - // setting could be either: - // 1) string URL representation (i.e., "file://...") - // 2) relative file path (resource lookup) - // 3) absolute file path - - log.trace( "Trying as URL..." ); - // ClassLoaderService.locateResource() first tries the given resource name as url form... - final URL url = classLoaderService.locateResource( scriptSourceSettingString ); - if ( url != null ) { - return new ScriptSourceInputFromUrl( url, charsetName ); + final String[] paths = COMMA_PATTERN.split( scriptSourceSettingString ); + if ( paths.length == 1 ) { + return interpretScriptSourceSetting( scriptSourceSettingString, classLoaderService, charsetName ); + } + final AbstractScriptSourceInput[] inputs = new AbstractScriptSourceInput[paths.length]; + for ( int i = 0; i < paths.length; i++ ) { + inputs[i] = interpretScriptSourceSetting( paths[i], classLoaderService, charsetName ) ; } - // assume it is a File path - final File file = new File( scriptSourceSettingString ); - return new ScriptSourceInputFromFile( file, charsetName ); + return new ScriptSourceInputAggregate( inputs ); } } + private static AbstractScriptSourceInput interpretScriptSourceSetting( + String scriptSourceSettingString, + ClassLoaderService classLoaderService, + String charsetName) { + // setting could be either: + // 1) string URL representation (i.e., "file://...") + // 2) relative file path (resource lookup) + // 3) absolute file path + + log.trace( "Trying as URL..." ); + // ClassLoaderService.locateResource() first tries the given resource name as url form... + final URL url = classLoaderService.locateResource( scriptSourceSettingString ); + if ( url != null ) { + return new ScriptSourceInputFromUrl( url, charsetName ); + } + + // assume it is a File path + final File file = new File( scriptSourceSettingString ); + return new ScriptSourceInputFromFile( file, charsetName ); + } + public static ScriptTargetOutput interpretScriptTargetSetting( Object scriptTargetSetting, ClassLoaderService classLoaderService, @@ -109,6 +129,9 @@ public class Helper { if ( configurationValues.containsKey( AvailableSettings.HBM2DDL_CREATE_SCHEMAS ) ) { count++; } + if ( configurationValues.containsKey( AvailableSettings.JAKARTA_HBM2DDL_CREATE_SCHEMAS ) ) { + count++; + } if ( configurationValues.containsKey( AvailableSettings.HBM2DDL_CREATE_NAMESPACES ) ) { count++; } @@ -122,15 +145,20 @@ public class Helper { return ConfigurationHelper.getBoolean( AvailableSettings.HBM2DDL_CREATE_SCHEMAS, configurationValues, - //Then try the Hibernate ORM setting: + //Then try the Jakarta JPA setting: ConfigurationHelper.getBoolean( - AvailableSettings.HBM2DDL_CREATE_NAMESPACES, + AvailableSettings.JAKARTA_HBM2DDL_CREATE_SCHEMAS, configurationValues, - //And finally fall back to the old name this had before we fixed the typo: + //Then try the Hibernate ORM setting: ConfigurationHelper.getBoolean( - AvailableSettings.HBM2DLL_CREATE_NAMESPACES, + AvailableSettings.HBM2DDL_CREATE_NAMESPACES, configurationValues, - false + //And finally fall back to the old name this had before we fixed the typo: + ConfigurationHelper.getBoolean( + AvailableSettings.HBM2DLL_CREATE_NAMESPACES, + configurationValues, + false + ) ) ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/HibernateSchemaManagementTool.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/HibernateSchemaManagementTool.java index 10e5e57795..8db7d0d540 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/HibernateSchemaManagementTool.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/HibernateSchemaManagementTool.java @@ -46,6 +46,7 @@ import org.jboss.logging.Logger; import static org.hibernate.cfg.AvailableSettings.HBM2DDL_CONNECTION; import static org.hibernate.cfg.AvailableSettings.HBM2DDL_DELIMITER; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_HBM2DDL_CONNECTION; /** * The standard Hibernate implementation for performing schema management. @@ -196,13 +197,35 @@ public class HibernateSchemaManagementTool implements SchemaManagementTool, Serv if ( providedConnection != null ) { jdbcContextBuilder.jdbcConnectionAccess = new JdbcConnectionAccessProvidedConnectionImpl( providedConnection ); } + else { + final Connection jakartaProvidedConnection = (Connection) configurationValues.get( JAKARTA_HBM2DDL_CONNECTION ); + if ( jakartaProvidedConnection != null ) { + jdbcContextBuilder.jdbcConnectionAccess = new JdbcConnectionAccessProvidedConnectionImpl( jakartaProvidedConnection ); + } + } // see if a specific Dialect override has been provided... - final String explicitDbName = (String) configurationValues.get( AvailableSettings.DIALECT_DB_NAME ); + String dbName = (String) configurationValues.get( AvailableSettings.DIALECT_DB_NAME ); + if ( dbName == null ) { + dbName = (String) configurationValues.get( AvailableSettings.JAKARTA_HBM2DDL_DB_NAME ); + } + final String explicitDbName = dbName; if ( StringHelper.isNotEmpty( explicitDbName ) ) { - final String explicitDbVersion = (String) configurationValues.get( AvailableSettings.DIALECT_DB_VERSION ); - final String explicitDbMajor = (String) configurationValues.get( AvailableSettings.DIALECT_DB_MAJOR_VERSION ); - final String explicitDbMinor = (String) configurationValues.get( AvailableSettings.DIALECT_DB_MINOR_VERSION ); + String dbVersion = (String) configurationValues.get( AvailableSettings.DIALECT_DB_VERSION ); + if ( dbVersion == null ) { + dbVersion = (String) configurationValues.get( AvailableSettings.JAKARTA_DIALECT_DB_VERSION ); + } + String dbMajor = (String) configurationValues.get( AvailableSettings.DIALECT_DB_MAJOR_VERSION ); + if ( dbMajor == null ) { + dbMajor = (String) configurationValues.get( AvailableSettings.JAKARTA_HBM2DDL_DB_MAJOR_VERSION ); + } + String dbMinor = (String) configurationValues.get( AvailableSettings.DIALECT_DB_MINOR_VERSION ); + if ( dbMinor == null ) { + dbMinor = (String) configurationValues.get( AvailableSettings.JAKARTA_HBM2DDL_DB_MINOR_VERSION ); + } + final String explicitDbVersion = dbVersion; + final String explicitDbMajor = dbMajor; + final String explicitDbMinor = dbMinor; final Dialect indicatedDialect = serviceRegistry.getService( DialectResolver.class ).resolveDialect( new DialectResolutionInfo() { diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaCreatorImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaCreatorImpl.java index bb444a2a2a..fab02cb164 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaCreatorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaCreatorImpl.java @@ -63,6 +63,7 @@ import org.hibernate.tool.schema.spi.TargetDescriptor; import static org.hibernate.cfg.AvailableSettings.HBM2DDL_CHARSET_NAME; import static org.hibernate.cfg.AvailableSettings.HBM2DDL_LOAD_SCRIPT_SOURCE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_HBM2DDL_LOAD_SCRIPT_SOURCE; import static org.hibernate.tool.schema.internal.Helper.interpretScriptSourceSetting; /** @@ -506,7 +507,10 @@ public class SchemaCreatorImpl implements SchemaCreator { //final Formatter formatter = format ? DDLFormatterImpl.INSTANCE : FormatStyle.NONE.getFormatter(); final Formatter formatter = FormatStyle.NONE.getFormatter(); - final Object importScriptSetting = options.getConfigurationValues().get( HBM2DDL_LOAD_SCRIPT_SOURCE ); + Object importScriptSetting = options.getConfigurationValues().get( HBM2DDL_LOAD_SCRIPT_SOURCE ); + if ( importScriptSetting == null ) { + importScriptSetting = options.getConfigurationValues().get( JAKARTA_HBM2DDL_LOAD_SCRIPT_SOURCE ); + } String charsetName = (String) options.getConfigurationValues().get( HBM2DDL_CHARSET_NAME ); if ( importScriptSetting != null ) { diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputAggregate.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputAggregate.java new file mode 100644 index 0000000000..7fbba6d21b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputAggregate.java @@ -0,0 +1,69 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.tool.schema.internal.exec; + +import java.io.Reader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; + +import org.hibernate.internal.CoreLogging; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.tool.schema.internal.SchemaCreatorImpl; +import org.hibernate.tool.schema.spi.ScriptSourceInput; + +/** + * A script source input that aggregates over multiple other {@link ScriptSourceInput}. + * + * @author Christian Beikov + */ +public class ScriptSourceInputAggregate implements ScriptSourceInput { + + private static final CoreMessageLogger log = CoreLogging.messageLogger( SchemaCreatorImpl.class ); + + private final AbstractScriptSourceInput[] inputs; + + /** + * Constructs a ScriptSourceInputAggregate + * + * @param inputs The script source inputs + */ + public ScriptSourceInputAggregate(AbstractScriptSourceInput[] inputs) { + this.inputs = inputs; + } + + @Override + public List extract(Function> extractor) { + + final List[] lists = new List[inputs.length]; + int size = 0; + for ( int i = 0; i < inputs.length; i++ ) { + final AbstractScriptSourceInput scriptSourceInput = inputs[i]; + final Reader reader = scriptSourceInput.prepareReader(); + try { + log.executingImportScript( scriptSourceInput.getScriptDescription() ); + lists[i] = extractor.apply( reader ); + size += lists[i].size(); + } + finally { + scriptSourceInput.releaseReader( reader ); + } + } + final List list = new ArrayList<>( size ); + for ( List strings : lists ) { + list.addAll( strings ); + } + + return list; + } + + @Override + public String toString() { + return "ScriptSourceInputAggregate(" + Arrays.toString( inputs ) + ")"; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputFromFile.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputFromFile.java index 388d5a8272..4500cc96d2 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputFromFile.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputFromFile.java @@ -13,7 +13,6 @@ import java.io.InputStreamReader; import java.io.Reader; import org.hibernate.tool.schema.spi.SchemaManagementException; -import org.hibernate.tool.schema.spi.ScriptSourceInput; import org.jboss.logging.Logger; @@ -22,7 +21,7 @@ import org.jboss.logging.Logger; * * @author Steve Ebersole */ -public class ScriptSourceInputFromFile extends AbstractScriptSourceInput implements ScriptSourceInput { +public class ScriptSourceInputFromFile extends AbstractScriptSourceInput { private static final Logger log = Logger.getLogger( ScriptSourceInputFromFile.class ); private final File file; diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputFromReader.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputFromReader.java index 41de9cf84d..f5c778ddd9 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputFromReader.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputFromReader.java @@ -8,14 +8,12 @@ package org.hibernate.tool.schema.internal.exec; import java.io.Reader; -import org.hibernate.tool.schema.spi.ScriptSourceInput; - /** * ScriptSourceInput implementation for explicitly given Readers. * * @author Steve Ebersole */ -public class ScriptSourceInputFromReader extends AbstractScriptSourceInput implements ScriptSourceInput { +public class ScriptSourceInputFromReader extends AbstractScriptSourceInput { private final Reader reader; /** diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputFromUrl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputFromUrl.java index bd1ac4a017..15247bfdc6 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputFromUrl.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputFromUrl.java @@ -12,7 +12,6 @@ import java.io.Reader; import java.net.URL; import org.hibernate.tool.schema.spi.SchemaManagementException; -import org.hibernate.tool.schema.spi.ScriptSourceInput; import org.jboss.logging.Logger; @@ -22,7 +21,7 @@ import org.jboss.logging.Logger; * @author Christian Beikov * @author Steve Ebersole */ -public class ScriptSourceInputFromUrl extends AbstractScriptSourceInput implements ScriptSourceInput { +public class ScriptSourceInputFromUrl extends AbstractScriptSourceInput { private static final Logger log = Logger.getLogger( ScriptSourceInputFromFile.class ); private final URL url; diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputNonExistentImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputNonExistentImpl.java index 11798887ad..ab23769050 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputNonExistentImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/exec/ScriptSourceInputNonExistentImpl.java @@ -18,12 +18,27 @@ import org.hibernate.tool.schema.spi.ScriptSourceInput; * * @author Steve Ebersole */ -public class ScriptSourceInputNonExistentImpl implements ScriptSourceInput { +public class ScriptSourceInputNonExistentImpl extends AbstractScriptSourceInput { /** * Singleton access */ public static final ScriptSourceInputNonExistentImpl INSTANCE = new ScriptSourceInputNonExistentImpl(); + @Override + protected String getScriptDescription() { + return "[injected ScriptSourceInputNonExistentImpl script]"; + } + + @Override + protected Reader prepareReader() { + return null; + } + + @Override + protected void releaseReader(Reader reader) { + + } + @Override public List extract(Function> extractor) { return Collections.emptyList(); diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaManagementToolCoordinator.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaManagementToolCoordinator.java index dfdf6ab6e4..4932388399 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaManagementToolCoordinator.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/spi/SchemaManagementToolCoordinator.java @@ -39,6 +39,14 @@ import static org.hibernate.cfg.AvailableSettings.HBM2DDL_DROP_SOURCE; import static org.hibernate.cfg.AvailableSettings.HBM2DDL_SCRIPTS_ACTION; import static org.hibernate.cfg.AvailableSettings.HBM2DDL_SCRIPTS_CREATE_TARGET; import static org.hibernate.cfg.AvailableSettings.HBM2DDL_SCRIPTS_DROP_TARGET; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_HBM2DDL_CREATE_SCRIPT_SOURCE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_HBM2DDL_CREATE_SOURCE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_HBM2DDL_DATABASE_ACTION; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_HBM2DDL_DROP_SCRIPT_SOURCE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_HBM2DDL_DROP_SOURCE; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_HBM2DDL_SCRIPTS_ACTION; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_HBM2DDL_SCRIPTS_CREATE_TARGET; +import static org.hibernate.cfg.AvailableSettings.JAKARTA_HBM2DDL_SCRIPTS_DROP_TARGET; /** * Responsible for coordinating SchemaManagementTool execution(s) for auto-tooling whether @@ -491,17 +499,29 @@ public class SchemaManagementToolCoordinator { @Override public Object getSourceTypeSetting(Map configurationValues) { - return configurationValues.get( HBM2DDL_CREATE_SOURCE ); + Object setting = configurationValues.get( HBM2DDL_CREATE_SOURCE ); + if ( setting == null ) { + setting = configurationValues.get( JAKARTA_HBM2DDL_CREATE_SOURCE ); + } + return setting; } @Override public Object getScriptSourceSetting(Map configurationValues) { - return configurationValues.get( HBM2DDL_CREATE_SCRIPT_SOURCE ); + Object setting = configurationValues.get( HBM2DDL_CREATE_SCRIPT_SOURCE ); + if ( setting == null ) { + setting = configurationValues.get( JAKARTA_HBM2DDL_CREATE_SCRIPT_SOURCE ); + } + return setting; } @Override public Object getScriptTargetSetting(Map configurationValues) { - return configurationValues.get( HBM2DDL_SCRIPTS_CREATE_TARGET ); + Object setting = configurationValues.get( HBM2DDL_SCRIPTS_CREATE_TARGET ); + if ( setting == null ) { + setting = configurationValues.get( JAKARTA_HBM2DDL_SCRIPTS_CREATE_TARGET ); + } + return setting; } } @@ -513,17 +533,29 @@ public class SchemaManagementToolCoordinator { @Override public Object getSourceTypeSetting(Map configurationValues) { - return configurationValues.get( HBM2DDL_DROP_SOURCE ); + Object setting = configurationValues.get( HBM2DDL_DROP_SOURCE ); + if ( setting == null ) { + setting = configurationValues.get( JAKARTA_HBM2DDL_DROP_SOURCE ); + } + return setting; } @Override public Object getScriptSourceSetting(Map configurationValues) { - return configurationValues.get( HBM2DDL_DROP_SCRIPT_SOURCE ); + Object setting = configurationValues.get( HBM2DDL_DROP_SCRIPT_SOURCE ); + if ( setting == null ) { + setting = configurationValues.get( JAKARTA_HBM2DDL_DROP_SCRIPT_SOURCE ); + } + return setting; } @Override public Object getScriptTargetSetting(Map configurationValues) { - return configurationValues.get( HBM2DDL_SCRIPTS_DROP_TARGET ); + Object setting = configurationValues.get( HBM2DDL_SCRIPTS_DROP_TARGET ); + if ( setting == null ) { + setting = configurationValues.get( JAKARTA_HBM2DDL_SCRIPTS_DROP_TARGET ); + } + return setting; } } @@ -551,7 +583,11 @@ public class SchemaManagementToolCoordinator { @Override public Object getScriptTargetSetting(Map configurationValues) { // for now, reuse the CREATE script target setting - return configurationValues.get( HBM2DDL_SCRIPTS_CREATE_TARGET ); + Object setting = configurationValues.get( HBM2DDL_SCRIPTS_CREATE_TARGET ); + if ( setting == null ) { + setting = configurationValues.get( JAKARTA_HBM2DDL_SCRIPTS_CREATE_TARGET ); + } + return setting; } } @@ -588,9 +624,17 @@ public class SchemaManagementToolCoordinator { */ @Internal public static ActionGrouping interpret(Map configurationValues) { + Object databaseActionSetting = configurationValues.get( HBM2DDL_DATABASE_ACTION ); + Object scriptsActionSetting = configurationValues.get( HBM2DDL_SCRIPTS_ACTION ); + if ( databaseActionSetting == null ) { + databaseActionSetting = configurationValues.get( JAKARTA_HBM2DDL_DATABASE_ACTION ); + } + if ( scriptsActionSetting == null ) { + scriptsActionSetting = configurationValues.get( JAKARTA_HBM2DDL_SCRIPTS_ACTION ); + } // interpret the JPA settings first - Action databaseAction = Action.interpretJpaSetting( configurationValues.get( HBM2DDL_DATABASE_ACTION ) ); - Action scriptAction = Action.interpretJpaSetting( configurationValues.get( HBM2DDL_SCRIPTS_ACTION ) ); + Action databaseAction = Action.interpretJpaSetting( databaseActionSetting ); + Action scriptAction = Action.interpretJpaSetting( scriptsActionSetting ); // if no JPA settings were specified, look at the legacy HBM2DDL_AUTO setting... if ( databaseAction == Action.NONE && scriptAction == Action.NONE ) { diff --git a/hibernate-core/src/test/bundles/cfgxmlpar/META-INF/persistence.xml b/hibernate-core/src/test/bundles/templates/cfgxmlpar/META-INF/persistence.xml similarity index 100% rename from hibernate-core/src/test/bundles/cfgxmlpar/META-INF/persistence.xml rename to hibernate-core/src/test/bundles/templates/cfgxmlpar/META-INF/persistence.xml diff --git a/hibernate-core/src/test/bundles/cfgxmlpar/org/hibernate/jpa/test/pack/cfgxmlpar/hibernate.cfg.xml b/hibernate-core/src/test/bundles/templates/cfgxmlpar/org/hibernate/jpa/test/pack/cfgxmlpar/hibernate.cfg.xml similarity index 100% rename from hibernate-core/src/test/bundles/cfgxmlpar/org/hibernate/jpa/test/pack/cfgxmlpar/hibernate.cfg.xml rename to hibernate-core/src/test/bundles/templates/cfgxmlpar/org/hibernate/jpa/test/pack/cfgxmlpar/hibernate.cfg.xml diff --git a/hibernate-core/src/test/bundles/defaultpar/META-INF/orm.xml b/hibernate-core/src/test/bundles/templates/defaultpar/META-INF/orm.xml similarity index 100% rename from hibernate-core/src/test/bundles/defaultpar/META-INF/orm.xml rename to hibernate-core/src/test/bundles/templates/defaultpar/META-INF/orm.xml diff --git a/hibernate-core/src/test/bundles/defaultpar/META-INF/persistence.xml b/hibernate-core/src/test/bundles/templates/defaultpar/META-INF/persistence.xml similarity index 100% rename from hibernate-core/src/test/bundles/defaultpar/META-INF/persistence.xml rename to hibernate-core/src/test/bundles/templates/defaultpar/META-INF/persistence.xml diff --git a/hibernate-core/src/test/bundles/defaultpar/org/hibernate/jpa/test/pack/defaultpar/Mouse.hbm.xml b/hibernate-core/src/test/bundles/templates/defaultpar/org/hibernate/jpa/test/pack/defaultpar/Mouse.hbm.xml similarity index 100% rename from hibernate-core/src/test/bundles/defaultpar/org/hibernate/jpa/test/pack/defaultpar/Mouse.hbm.xml rename to hibernate-core/src/test/bundles/templates/defaultpar/org/hibernate/jpa/test/pack/defaultpar/Mouse.hbm.xml diff --git a/hibernate-core/src/test/bundles/defaultpar_1_0/META-INF/orm.xml b/hibernate-core/src/test/bundles/templates/defaultpar_1_0/META-INF/orm.xml similarity index 100% rename from hibernate-core/src/test/bundles/defaultpar_1_0/META-INF/orm.xml rename to hibernate-core/src/test/bundles/templates/defaultpar_1_0/META-INF/orm.xml diff --git a/hibernate-core/src/test/bundles/defaultpar_1_0/META-INF/persistence.xml b/hibernate-core/src/test/bundles/templates/defaultpar_1_0/META-INF/persistence.xml similarity index 100% rename from hibernate-core/src/test/bundles/defaultpar_1_0/META-INF/persistence.xml rename to hibernate-core/src/test/bundles/templates/defaultpar_1_0/META-INF/persistence.xml diff --git a/hibernate-core/src/test/bundles/defaultpar_1_0/org/hibernate/jpa/test/pack/defaultpar_1_0/Mouse1.hbm.xml b/hibernate-core/src/test/bundles/templates/defaultpar_1_0/org/hibernate/jpa/test/pack/defaultpar_1_0/Mouse1.hbm.xml similarity index 100% rename from hibernate-core/src/test/bundles/defaultpar_1_0/org/hibernate/jpa/test/pack/defaultpar_1_0/Mouse1.hbm.xml rename to hibernate-core/src/test/bundles/templates/defaultpar_1_0/org/hibernate/jpa/test/pack/defaultpar_1_0/Mouse1.hbm.xml diff --git a/hibernate-core/src/test/bundles/excludehbmpar/META-INF/orm2.xml b/hibernate-core/src/test/bundles/templates/excludehbmpar/META-INF/orm2.xml similarity index 100% rename from hibernate-core/src/test/bundles/excludehbmpar/META-INF/orm2.xml rename to hibernate-core/src/test/bundles/templates/excludehbmpar/META-INF/orm2.xml diff --git a/hibernate-core/src/test/bundles/excludehbmpar/META-INF/persistence.xml b/hibernate-core/src/test/bundles/templates/excludehbmpar/META-INF/persistence.xml similarity index 100% rename from hibernate-core/src/test/bundles/excludehbmpar/META-INF/persistence.xml rename to hibernate-core/src/test/bundles/templates/excludehbmpar/META-INF/persistence.xml diff --git a/hibernate-core/src/test/bundles/excludehbmpar/org/hibernate/jpa/test/pack/excludehbmpar/Mouse.hbm.xml b/hibernate-core/src/test/bundles/templates/excludehbmpar/org/hibernate/jpa/test/pack/excludehbmpar/Mouse.hbm.xml similarity index 100% rename from hibernate-core/src/test/bundles/excludehbmpar/org/hibernate/jpa/test/pack/excludehbmpar/Mouse.hbm.xml rename to hibernate-core/src/test/bundles/templates/excludehbmpar/org/hibernate/jpa/test/pack/excludehbmpar/Mouse.hbm.xml diff --git a/hibernate-core/src/test/bundles/explicitpar/META-INF/orm.xml b/hibernate-core/src/test/bundles/templates/explicitpar/META-INF/orm.xml similarity index 100% rename from hibernate-core/src/test/bundles/explicitpar/META-INF/orm.xml rename to hibernate-core/src/test/bundles/templates/explicitpar/META-INF/orm.xml diff --git a/hibernate-core/src/test/bundles/explicitpar/META-INF/persistence.xml b/hibernate-core/src/test/bundles/templates/explicitpar/META-INF/persistence.xml similarity index 100% rename from hibernate-core/src/test/bundles/explicitpar/META-INF/persistence.xml rename to hibernate-core/src/test/bundles/templates/explicitpar/META-INF/persistence.xml diff --git a/hibernate-core/src/test/bundles/explicitpar2/META-INF/orm.xml b/hibernate-core/src/test/bundles/templates/explicitpar2/META-INF/orm.xml similarity index 100% rename from hibernate-core/src/test/bundles/explicitpar2/META-INF/orm.xml rename to hibernate-core/src/test/bundles/templates/explicitpar2/META-INF/orm.xml diff --git a/hibernate-core/src/test/bundles/explicitpar2/META-INF/persistence.xml b/hibernate-core/src/test/bundles/templates/explicitpar2/META-INF/persistence.xml similarity index 100% rename from hibernate-core/src/test/bundles/explicitpar2/META-INF/persistence.xml rename to hibernate-core/src/test/bundles/templates/explicitpar2/META-INF/persistence.xml diff --git a/hibernate-core/src/test/bundles/explodedpar/META-INF/persistence.xml b/hibernate-core/src/test/bundles/templates/explodedpar/META-INF/persistence.xml similarity index 100% rename from hibernate-core/src/test/bundles/explodedpar/META-INF/persistence.xml rename to hibernate-core/src/test/bundles/templates/explodedpar/META-INF/persistence.xml diff --git a/hibernate-core/src/test/bundles/explodedpar/org/hibernate/jpa/test/pack/explodedpar/Elephant.hbm.xml b/hibernate-core/src/test/bundles/templates/explodedpar/org/hibernate/jpa/test/pack/explodedpar/Elephant.hbm.xml similarity index 100% rename from hibernate-core/src/test/bundles/explodedpar/org/hibernate/jpa/test/pack/explodedpar/Elephant.hbm.xml rename to hibernate-core/src/test/bundles/templates/explodedpar/org/hibernate/jpa/test/pack/explodedpar/Elephant.hbm.xml diff --git a/hibernate-core/src/test/bundles/externaljar/META-INF/orm.xml b/hibernate-core/src/test/bundles/templates/externaljar/META-INF/orm.xml similarity index 100% rename from hibernate-core/src/test/bundles/externaljar/META-INF/orm.xml rename to hibernate-core/src/test/bundles/templates/externaljar/META-INF/orm.xml diff --git a/hibernate-core/src/test/bundles/overridenpar/META-INF/persistence.xml b/hibernate-core/src/test/bundles/templates/overridenpar/META-INF/persistence.xml similarity index 100% rename from hibernate-core/src/test/bundles/overridenpar/META-INF/persistence.xml rename to hibernate-core/src/test/bundles/templates/overridenpar/META-INF/persistence.xml diff --git a/hibernate-core/src/test/bundles/overridenpar/overridenpar.properties b/hibernate-core/src/test/bundles/templates/overridenpar/overridenpar.properties similarity index 100% rename from hibernate-core/src/test/bundles/overridenpar/overridenpar.properties rename to hibernate-core/src/test/bundles/templates/overridenpar/overridenpar.properties diff --git a/hibernate-core/src/test/bundles/space par/META-INF/persistence.xml b/hibernate-core/src/test/bundles/templates/space par/META-INF/persistence.xml similarity index 100% rename from hibernate-core/src/test/bundles/space par/META-INF/persistence.xml rename to hibernate-core/src/test/bundles/templates/space par/META-INF/persistence.xml diff --git a/hibernate-core/src/test/bundles/war/WEB-INF/classes/META-INF/orm.xml b/hibernate-core/src/test/bundles/templates/war/WEB-INF/classes/META-INF/orm.xml similarity index 100% rename from hibernate-core/src/test/bundles/war/WEB-INF/classes/META-INF/orm.xml rename to hibernate-core/src/test/bundles/templates/war/WEB-INF/classes/META-INF/orm.xml diff --git a/hibernate-core/src/test/bundles/war/WEB-INF/classes/META-INF/persistence.xml b/hibernate-core/src/test/bundles/templates/war/WEB-INF/classes/META-INF/persistence.xml similarity index 100% rename from hibernate-core/src/test/bundles/war/WEB-INF/classes/META-INF/persistence.xml rename to hibernate-core/src/test/bundles/templates/war/WEB-INF/classes/META-INF/persistence.xml diff --git a/hibernate-core/src/test/bundles/war/WEB-INF/classes/org/hibernate/jpa/test/pack/war/Mouse.hbm.xml b/hibernate-core/src/test/bundles/templates/war/WEB-INF/classes/org/hibernate/jpa/test/pack/war/Mouse.hbm.xml similarity index 100% rename from hibernate-core/src/test/bundles/war/WEB-INF/classes/org/hibernate/jpa/test/pack/war/Mouse.hbm.xml rename to hibernate-core/src/test/bundles/templates/war/WEB-INF/classes/org/hibernate/jpa/test/pack/war/Mouse.hbm.xml diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/iso8859/JpaFileSchemaGeneratorWithHbm2DdlCharsetNameTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/iso8859/JpaFileSchemaGeneratorWithHbm2DdlCharsetNameTest.java index 89ea650380..90e8ba7870 100644 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/iso8859/JpaFileSchemaGeneratorWithHbm2DdlCharsetNameTest.java +++ b/hibernate-core/src/test/java/org/hibernate/jpa/test/schemagen/iso8859/JpaFileSchemaGeneratorWithHbm2DdlCharsetNameTest.java @@ -45,10 +45,6 @@ public class JpaFileSchemaGeneratorWithHbm2DdlCharsetNameTest extends JpaSchemaG return toFilePath(super.getDropSqlScript()); } - protected String toFilePath(String relativePath) { - return Thread.currentThread().getContextClassLoader().getResource( relativePath ).getFile(); - } - @Override protected String getResourceUrlString(String resource) { return resource; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/events/CallbackTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/events/CallbackTest.java index b01bc34c24..dba722dc2a 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/events/CallbackTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/events/CallbackTest.java @@ -22,9 +22,11 @@ import org.hibernate.event.spi.EventType; import org.hibernate.integrator.spi.Integrator; import org.hibernate.service.spi.SessionFactoryServiceRegistry; +import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; @@ -33,6 +35,7 @@ import static org.junit.Assert.assertEquals; * * @author Steve Ebersole */ +@TestForIssue(jiraKey = {"HHH-2884", "HHH-10674", "HHH-14541"}) public class CallbackTest extends BaseCoreFunctionalTestCase { private TestingObserver observer = new TestingObserver(); private TestingListener listener = new TestingListener(); @@ -97,16 +100,22 @@ public class CallbackTest extends BaseCoreFunctionalTestCase { private int closedCount = 0; private int closingCount = 0; + @Override public void sessionFactoryCreated(SessionFactory factory) { + assertThat( factory.isClosed() ).isFalse(); creationCount++; } @Override public void sessionFactoryClosing(SessionFactory factory) { + // Test for HHH-14541 + assertThat( factory.isClosed() ).isFalse(); closingCount++; } + @Override public void sessionFactoryClosed(SessionFactory factory) { + assertThat( factory.isClosed() ).isTrue(); closedCount++; } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/schemagen/JpaFileSchemaGeneratorTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/schemagen/JpaFileSchemaGeneratorTest.java index 11ea72b151..ab49af7501 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/schemagen/JpaFileSchemaGeneratorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/schemagen/JpaFileSchemaGeneratorTest.java @@ -30,10 +30,6 @@ public class JpaFileSchemaGeneratorTest extends JpaSchemaGeneratorTest { return toFilePath(super.getDropSqlScript()); } - protected String toFilePath(String relativePath) { - return Thread.currentThread().getContextClassLoader().getResource( relativePath ).getFile(); - } - @Override protected String getResourceUrlString(String resource) { return resource; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/schemagen/JpaSchemaGeneratorTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/schemagen/JpaSchemaGeneratorTest.java index 0aae5e26ff..425609e831 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/schemagen/JpaSchemaGeneratorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/schemagen/JpaSchemaGeneratorTest.java @@ -8,6 +8,7 @@ package org.hibernate.orm.test.jpa.schemagen; import java.net.URL; import java.util.Map; +import java.util.function.Function; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; @@ -19,6 +20,7 @@ import org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.orm.junit.EntityManagerFactoryBasedFunctionalTest; import org.hibernate.testing.orm.junit.RequiresDialect; +import org.junit.Assert; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -28,9 +30,9 @@ import org.junit.jupiter.api.Test; @RequiresDialect( H2Dialect.class ) public class JpaSchemaGeneratorTest extends EntityManagerFactoryBasedFunctionalTest { - private final String LOAD_SQL = getScriptFolderPath() + "load-script-source.sql"; - private final String CREATE_SQL = getScriptFolderPath() + "create-script-source.sql"; - private final String DROP_SQL = getScriptFolderPath() + "drop-script-source.sql"; + private final String LOAD_SQL = getScriptFolderPath() + "load-script-source.sql , " + getScriptFolderPath() + "load-script-source2.sql"; + private final String CREATE_SQL = getScriptFolderPath() + "create-script-source.sql , " + getScriptFolderPath() + "create-script-source2.sql"; + private final String DROP_SQL = getScriptFolderPath() + "drop-script-source.sql , " + getScriptFolderPath() + "drop-script-source2.sql"; private static int schemagenNumber = 0; @@ -119,12 +121,29 @@ public class JpaSchemaGeneratorTest extends EntityManagerFactoryBasedFunctionalT return "sch" + (char) 233 + "magen-test"; } - protected String getResourceUrlString(String resource) { - final URL url = getClass().getClassLoader().getResource( resource ); - if ( url == null ) { - throw new RuntimeException( "Unable to locate requested resource [" + resource + "]" ); + protected String getResourceUrlString(String string) { + return getResourceUrlString( getClass().getClassLoader(), string, URL::toString ); + } + + protected String getResourceUrlString(ClassLoader classLoader, String string, Function transformer) { + final String[] strings = string.split( "\\s*,\\s*" ); + final StringBuilder sb = new StringBuilder( string.length() ); + for ( int i = 0; i < strings.length; i++ ) { + if ( i != 0 ) { + sb.append( ',' ); + } + final String resource = strings[i]; + final URL url = classLoader.getResource( resource ); + if ( url == null ) { + throw new RuntimeException( "Unable to locate requested resource [" + resource + "]" ); + } + sb.append( transformer.apply( url ) ); } - return url.toString(); + return sb.toString(); + } + + protected String toFilePath(String relativePath) { + return getResourceUrlString( Thread.currentThread().getContextClassLoader(), relativePath, URL::getFile ); } private void doTest(Map settings) { @@ -141,6 +160,7 @@ public class JpaSchemaGeneratorTest extends EntityManagerFactoryBasedFunctionalT EntityManager em = emf.createEntityManager(); try { Assertions.assertNotNull( em.find( Item.class, encodedName() ) ); + Assert.assertNotNull( em.find( Item.class, "multi-file-test" ) ); } finally { em.close(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/LazyCollectionLoadingTest.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/LazyCollectionLoadingTest.java index f61895cd5d..1433a80e20 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/LazyCollectionLoadingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/LazyCollectionLoadingTest.java @@ -36,6 +36,7 @@ import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.sameInstance; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hibernate.Hibernate.isInitialized; import static org.hibernate.Hibernate.isPropertyInitialized; import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.checkDirtyTracking; import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; @@ -90,7 +91,6 @@ public class LazyCollectionLoadingTest extends BaseCoreFunctionalTestCase { Parent parent = s.load( Parent.class, parentID ); assertThat( parent, notNullValue() ); assertThat( parent, not( instanceOf( HibernateProxy.class ) ) ); - assertThat( parent, not( instanceOf( HibernateProxy.class ) ) ); assertFalse( isPropertyInitialized( parent, "children" ) ); checkDirtyTracking( parent ); @@ -101,7 +101,39 @@ public class LazyCollectionLoadingTest extends BaseCoreFunctionalTestCase { checkDirtyTracking( parent ); assertThat( children1, sameInstance( children2 ) ); + + assertFalse( isInitialized( children1 ) ); assertThat( children1.size(), equalTo( CHILDREN_SIZE ) ); + assertTrue( isInitialized( children1 ) ); + } ); + } + + @Test + @TestForIssue( jiraKey = "HHH-14620" ) + public void testTransaction_noProxy() { + doInHibernate( this::sessionFactory, s -> { + // find will not return a proxy, which is exactly what we want here. + Parent parent = s.find( Parent.class, parentID ); + assertThat( parent, notNullValue() ); + assertThat( parent, not( instanceOf( HibernateProxy.class ) ) ); + assertFalse( isPropertyInitialized( parent, "children" ) ); + checkDirtyTracking( parent ); + + List children1 = parent.children; + List children2 = parent.children; + + assertTrue( isPropertyInitialized( parent, "children" ) ); + checkDirtyTracking( parent ); + + assertThat( children1, sameInstance( children2 ) ); + + // This check is important: a bug used to cause the collection to be initialized + // during the call to parent.children above. + // Note the same problem would occur if we were using getters: + // we only need extended enhancement to be enabled. + assertFalse( isInitialized( children1 ) ); + assertThat( children1.size(), equalTo( CHILDREN_SIZE ) ); + assertTrue( isInitialized( children1 ) ); } ); } @@ -111,7 +143,6 @@ public class LazyCollectionLoadingTest extends BaseCoreFunctionalTestCase { parent = s.load( Parent.class, parentID ); assertThat( parent, notNullValue() ); assertThat( parent, not( instanceOf( HibernateProxy.class ) ) ); - assertThat( parent, not( instanceOf( HibernateProxy.class ) ) ); assertFalse( isPropertyInitialized( parent, "children" ) ); } ); @@ -122,7 +153,10 @@ public class LazyCollectionLoadingTest extends BaseCoreFunctionalTestCase { checkDirtyTracking( parent ); assertThat( children1, sameInstance( children2 ) ); + + assertFalse( isInitialized( children1 ) ); assertThat( children1.size(), equalTo( CHILDREN_SIZE ) ); + assertTrue( isInitialized( children1 ) ); } // --- // diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/LazyProxyWithCollectionTest.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/LazyProxyWithCollectionTest.java new file mode 100644 index 0000000000..d818fa52e8 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/LazyProxyWithCollectionTest.java @@ -0,0 +1,166 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.bytecode.enhancement.lazy; + +import java.util.HashSet; +import java.util.Set; + +import org.hibernate.HibernateException; +import org.hibernate.bytecode.enhance.spi.UnloadedClass; +import org.hibernate.event.service.spi.EventListenerRegistry; +import org.hibernate.event.spi.EventType; +import org.hibernate.event.spi.LoadEvent; +import org.hibernate.event.spi.LoadEventListener; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; +import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext; +import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.OneToOne; +import javax.persistence.Table; +import javax.persistence.Version; + +import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; + +/** + * @author Christian Beikov + */ +@TestForIssue( jiraKey = "HHH-14619" ) +@RunWith( BytecodeEnhancerRunner.class ) +public class LazyProxyWithCollectionTest extends BaseCoreFunctionalTestCase { + + private Long childId; + + @Override + public Class[] getAnnotatedClasses() { + return new Class[]{Parent.class, Child.class}; + } + + @Before + public void prepare() { + doInJPA( this::sessionFactory, em -> { + Child c = new Child(); + em.persist( c ); + childId = c.getId(); + } ); + } + + @Test + public void testReference() { + doInJPA( this::sessionFactory, em -> { + Child child = em.getReference( Child.class, childId ); + Parent parent = new Parent(); + parent.child = child; + em.persist( parent ); + // Class cast exception occurs during auto-flush + em.find( Parent.class, parent.getId() ); + } ); + } + + @Test + public void testLazyCollection() { + doInJPA( this::sessionFactory, em -> { + Child child = em.find( Child.class, childId ); + Parent parent = new Parent(); + parent.child = child; + em.persist( parent ); + child.children = new HashSet<>(); + // Class cast exception occurs during auto-flush + em.find( Parent.class, parent.getId() ); + } ); + } + + // --- // + + @Entity + @Table( name = "PARENT" ) + private static class Parent { + + @Id + @GeneratedValue( strategy = GenerationType.AUTO ) + Long id; + + @OneToOne( fetch = FetchType.LAZY ) + Child child; + + public Long getId() { + return id; + } + + public Child getChild() { + return child; + } + + public void setChild(Child child) { + this.child = child; + } + } + + @Entity + @Table( name = "CHILD" ) + private static class Child { + + @Id + @GeneratedValue( strategy = GenerationType.AUTO ) + Long id; + @Version + Long version; + + String name; + + @OneToMany + Set children = new HashSet<>(); + + Child() { + // No-arg constructor necessary for proxy factory + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getVersion() { + return version; + } + + public void setVersion(Long version) { + this.version = version; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Set getChildren() { + return children; + } + + public void setChildren(Set children) { + this.children = children; + } + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/ondemandload/OnDemandLoadTest.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/ondemandload/OnDemandLoadTest.java index 8d78290c49..13cf60798d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/ondemandload/OnDemandLoadTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/ondemandload/OnDemandLoadTest.java @@ -117,16 +117,17 @@ public class OnDemandLoadTest extends BaseCoreFunctionalTestCase { store.getInventories().size(); assertTrue( isPropertyInitialized( store, "inventories" ) ); - // the extra Session is the temp Session needed to perform the init - assertEquals( 2, sessionFactory().getStatistics().getSessionOpenCount() ); - assertEquals( 1, sessionFactory().getStatistics().getSessionCloseCount() ); + // the extra Sessions are the temp Sessions needed to perform the init: + // first the entity, then the collection (since it's lazy) + assertEquals( 3, sessionFactory().getStatistics().getSessionOpenCount() ); + assertEquals( 2, sessionFactory().getStatistics().getSessionCloseCount() ); // clear Session again. The collection should still be recognized as initialized from above s.clear(); assertNotNull( store ); assertTrue( isPropertyInitialized( store, "inventories" ) ); - assertEquals( 2, sessionFactory().getStatistics().getSessionOpenCount() ); - assertEquals( 1, sessionFactory().getStatistics().getSessionCloseCount() ); + assertEquals( 3, sessionFactory().getStatistics().getSessionOpenCount() ); + assertEquals( 2, sessionFactory().getStatistics().getSessionCloseCount() ); // lets clear the Session again and this time reload the Store s.clear(); @@ -136,21 +137,22 @@ public class OnDemandLoadTest extends BaseCoreFunctionalTestCase { // collection should be back to uninitialized since we have a new entity instance assertFalse( isPropertyInitialized( store, "inventories" ) ); - assertEquals( 2, sessionFactory().getStatistics().getSessionOpenCount() ); - assertEquals( 1, sessionFactory().getStatistics().getSessionCloseCount() ); + assertEquals( 3, sessionFactory().getStatistics().getSessionOpenCount() ); + assertEquals( 2, sessionFactory().getStatistics().getSessionCloseCount() ); store.getInventories().size(); assertTrue( isPropertyInitialized( store, "inventories" ) ); - // the extra Session is the temp Session needed to perform the init - assertEquals( 3, sessionFactory().getStatistics().getSessionOpenCount() ); - assertEquals( 2, sessionFactory().getStatistics().getSessionCloseCount() ); + // the extra Sessions are the temp Sessions needed to perform the init: + // first the entity, then the collection (since it's lazy) + assertEquals( 5, sessionFactory().getStatistics().getSessionOpenCount() ); + assertEquals( 4, sessionFactory().getStatistics().getSessionCloseCount() ); // clear Session again. The collection should still be recognized as initialized from above s.clear(); assertNotNull( store ); assertTrue( isPropertyInitialized( store, "inventories" ) ); - assertEquals( 3, sessionFactory().getStatistics().getSessionOpenCount() ); - assertEquals( 2, sessionFactory().getStatistics().getSessionCloseCount() ); + assertEquals( 5, sessionFactory().getStatistics().getSessionOpenCount() ); + assertEquals( 4, sessionFactory().getStatistics().getSessionCloseCount() ); } ); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/size/WhereClauseOrderBySizeTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/size/WhereClauseOrderBySizeTest.java new file mode 100644 index 0000000000..f7baf77809 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/size/WhereClauseOrderBySizeTest.java @@ -0,0 +1,187 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ + +package org.hibernate.test.hql.size; + +import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.TypedQuery; + +import org.hibernate.annotations.ResultCheckStyle; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Where; +import org.hibernate.dialect.H2Dialect; +import org.hibernate.dialect.PostgreSQL82Dialect; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; + +import org.hibernate.testing.RequiresDialect; +import org.hibernate.testing.TestForIssue; +import org.junit.Test; + +@TestForIssue(jiraKey = "HHH-14585") +@RequiresDialect(value = PostgreSQL82Dialect.class, comment = "Other databases may not support boolean data types") +@RequiresDialect(value = H2Dialect.class, comment = "Other databases may not support boolean data types") +public class WhereClauseOrderBySizeTest extends BaseEntityManagerFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { Person.class, Book.class }; + } + + @Test + public void testSizeAsOrderByExpression() { + doInJPA( + this::entityManagerFactory, + entityManager -> { + // initial situation: Alice has 1 book, Bob none + final Person alice = new Person( "Alice" ); + entityManager.persist( alice ); + + final Book book1 = new Book(); + book1.setOwner( alice ); + entityManager.persist( book1 ); + + final Person bob = new Person( "Bob" ); + entityManager.persist( bob ); + + final TypedQuery orderByBroken = entityManager.createQuery( + "SELECT p FROM Person p ORDER BY size(p.books) DESC", + Person.class + ); + final TypedQuery orderByWorking = entityManager.createQuery( + "SELECT p FROM Person p ORDER BY p.books.size DESC", + Person.class + ); + + List dbPeopleBroken = orderByBroken.getResultList(); + List dbPeopleWorking = orderByWorking.getResultList(); + assertEquals( Arrays.asList( alice, bob ), dbPeopleWorking ); + assertEquals( dbPeopleWorking, dbPeopleBroken ); + + // add 2 books to Bob + final Book book2 = new Book(); + book2.setOwner( bob ); + entityManager.persist( book2 ); + + final Book book3 = new Book(); + book3.setOwner( bob ); + entityManager.persist( book3 ); + + dbPeopleBroken = orderByBroken.getResultList(); + dbPeopleWorking = orderByWorking.getResultList(); + assertEquals( Arrays.asList( bob, alice ), dbPeopleWorking ); + assertEquals( dbPeopleWorking, dbPeopleBroken ); + + // remove (soft-deleting) both Bob's books + entityManager.remove( book2 ); + entityManager.remove( book3 ); + + // result lists are not equal anymore + dbPeopleBroken = orderByBroken.getResultList(); + dbPeopleWorking = orderByWorking.getResultList(); + assertEquals( Arrays.asList( alice, bob ), dbPeopleWorking ); + assertEquals( dbPeopleWorking, dbPeopleBroken ); + } + ); + } + + @Entity(name = "Person") + public static class Person { + @Id + @GeneratedValue + private Long id; + private String name; + @OneToMany(mappedBy = "owner", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) + private List books = new ArrayList<>(); + + public Person() { + } + + public Person(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getBooks() { + return books; + } + + public void setBooks(List books) { + this.books = books; + } + + @Override + public String toString() { + return "Person{" + + "id=" + id + + ", name='" + name + '\'' + + '}'; + } + } + + @Entity(name = "Book") + @SQLDelete(sql = "UPDATE Book SET deleted = true WHERE id = ?", check = ResultCheckStyle.COUNT) + @Where(clause = "deleted = false") + public static class Book { + @Id + @GeneratedValue + private Long id; + private Boolean deleted = false; + @ManyToOne + private Person owner; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Boolean getDeleted() { + return deleted; + } + + public void setDeleted(Boolean deleted) { + this.deleted = deleted; + } + + public Person getOwner() { + return owner; + } + + public void setOwner(Person owner) { + this.owner = owner; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/City.java b/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/City.java new file mode 100644 index 0000000000..c60400e547 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/City.java @@ -0,0 +1,60 @@ +/* + * Hibernate Search, full-text search for your domain model + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.hql.size.filter; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +import org.hibernate.annotations.Where; + +@Entity +@Where(clause = "deleted = false") +public class City { + + @Id + private Integer id; + + private String name; + + @ManyToOne + private Region region; + + private Boolean deleted; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Region getRegion() { + return region; + } + + public void setRegion(Region region) { + this.region = region; + } + + public Boolean getDeleted() { + return deleted; + } + + public void setDeleted(Boolean deleted) { + this.deleted = deleted; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/Region.java b/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/Region.java new file mode 100644 index 0000000000..59da4d4f35 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/Region.java @@ -0,0 +1,49 @@ +/* + * Hibernate Search, full-text search for your domain model + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.hql.size.filter; + +import java.util.ArrayList; +import java.util.List; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.OneToMany; + +@Entity +public class Region { + + @Id + private Integer id; + + private String name; + + @OneToMany(mappedBy = "region") + private List cities = new ArrayList<>(); + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getCities() { + return cities; + } + + public void setCities(List cities) { + this.cities = cities; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/WhereAnnotatedOneToManySizeTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/WhereAnnotatedOneToManySizeTest.java new file mode 100644 index 0000000000..a3ec5d5a35 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/size/filter/WhereAnnotatedOneToManySizeTest.java @@ -0,0 +1,136 @@ +/* + * Hibernate Search, full-text search for your domain model + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.hql.size.filter; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + +import org.hibernate.dialect.AbstractHANADialect; +import org.hibernate.dialect.DB2Dialect; +import org.hibernate.query.spi.QueryImplementor; + +import org.hibernate.testing.SkipForDialect; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +@TestForIssue(jiraKey = "HHH-14585") +public class WhereAnnotatedOneToManySizeTest extends BaseCoreFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { Region.class, City.class }; + } + + @Before + public void before() { + Region lazio = new Region(); + lazio.setId( 1 ); + lazio.setName( "Lazio" ); + + Region lombardy = new Region(); + lombardy.setId( 2 ); + lombardy.setName( "Lombardy" ); + + City rome = new City(); + rome.setId( 1 ); + rome.setName( "Rome" ); + rome.setDeleted( false ); + rome.setRegion( lazio ); + + City gradoli = new City(); + gradoli.setId( 2 ); + gradoli.setName( "Gradoli" ); + gradoli.setDeleted( true ); + gradoli.setRegion( lazio ); + + City milan = new City(); + milan.setId( 3 ); + milan.setName( "Milan" ); + milan.setDeleted( false ); + milan.setRegion( lombardy ); + + City pavia = new City(); + pavia.setId( 4 ); + pavia.setName( "Pavia" ); + pavia.setDeleted( false ); + pavia.setRegion( lombardy ); + + lazio.getCities().add( rome ); + lazio.getCities().add( gradoli ); + + lombardy.getCities().add( milan ); + lombardy.getCities().add( pavia ); + + inTransaction( session -> { + session.persist( lazio ); + session.persist( lombardy ); + + session.persist( rome ); + session.persist( gradoli ); + session.persist( milan ); + session.persist( pavia ); + } ); + } + + @After + public void after() { + inTransaction( session -> { + session.createQuery( "DELETE FROM City c" ).executeUpdate(); + session.createQuery( "DELETE FROM Region c" ).executeUpdate(); + } ); + } + + @Test + @SkipForDialect(value = DB2Dialect.class, comment = "DB2 does not support correlated subqueries in the ORDER BY clause") + @SkipForDialect(value = AbstractHANADialect.class, comment = "HANA db does not support correlated subqueries in the ORDER BY clause") + public void orderBy_sizeOf() { + inSession( session -> { + QueryImplementor query = session.createQuery( + "select r, size(r.cities) from Region r order by size(r.cities) desc" ); + List result = query.getResultList(); + assertThat( result ).extracting( f -> f[0] ).extracting( "name" ).containsExactly( "Lombardy", "Lazio" ); + assertThat( result ).extracting( f -> f[1] ).containsExactly( 2, 1 ); + } ); + } + + @Test + @SkipForDialect(value = DB2Dialect.class, comment = "DB2 does not support correlated subqueries in the ORDER BY clause") + @SkipForDialect(value = AbstractHANADialect.class, comment = "HANA db does not support correlated subqueries in the ORDER BY clause") + public void orderBy_dotSize() { + inSession( session -> { + QueryImplementor query = session.createQuery( + "select r, r.cities.size from Region r order by r.cities.size desc" ); + List result = query.getResultList(); + assertThat( result ).extracting( f -> f[0] ).extracting( "name" ).containsExactly( "Lombardy", "Lazio" ); + assertThat( result ).extracting( f -> f[1] ).containsExactly( 2, 1 ); + } ); + } + + @Test + public void project_sizeOf() { + inSession( session -> { + QueryImplementor query = session.createQuery( + "SELECT size(r.cities) FROM Region r", Integer.class ); + List cityCounts = query.getResultList(); + assertThat( cityCounts ).containsExactlyInAnyOrder( 1, 2 ); + } ); + } + + @Test + public void project_dotSize() { + inSession( session -> { + QueryImplementor query = session.createQuery( + "SELECT r.cities.size FROM Region r", Integer.class ); + List cityCounts = query.getResultList(); + assertThat( cityCounts ).containsExactlyInAnyOrder( 1, 2 ); + } ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/inheritance/discriminator/SingleTableNullNotNullDiscriminatorTest.java b/hibernate-core/src/test/java/org/hibernate/test/inheritance/discriminator/SingleTableNullNotNullDiscriminatorTest.java new file mode 100644 index 0000000000..71d48e40c6 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/inheritance/discriminator/SingleTableNullNotNullDiscriminatorTest.java @@ -0,0 +1,112 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.inheritance.discriminator; + +import java.sql.Statement; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +@TestForIssue(jiraKey = "HHH-12445") +public class SingleTableNullNotNullDiscriminatorTest extends BaseCoreFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + RootEntity.class, + Val1Entity.class, + Val2Entity.class, + NotNullEntity.class + }; + } + + @Test + public void test() { + inTransaction( session -> { + Val1Entity val1 = new Val1Entity(); + val1.setId( 1L ); + + Val2Entity val2 = new Val2Entity(); + val2.setId( 2L ); + + RootEntity root = new RootEntity(); + root.setId( 3L ); + + session.persist( val1 ); + session.persist( val2 ); + session.persist( root ); + + session.doWork( connection -> { + try (Statement statement = connection.createStatement()) { + statement.executeUpdate( + "insert into root_ent (DTYPE, id) " + + "values ('other', 4)" + ); + } + } ); + } ); + + inTransaction( session -> { + Map entities = session.createQuery( + "select e from root_ent e", RootEntity.class ) + .getResultList() + .stream() + .collect( Collectors.toMap( RootEntity::getId, Function.identity() ) ); + + assertThat( entities ).extractingByKey( 1L ).isInstanceOf( Val1Entity.class ); + assertThat( entities ).extractingByKey( 2L ).isInstanceOf( Val2Entity.class ); + assertThat( entities ).extractingByKey( 3L ).isInstanceOf( RootEntity.class ); + assertThat( entities ).extractingByKey( 4L ).isInstanceOf( NotNullEntity.class ); + } ); + } + + @Entity(name = "root_ent") + @Inheritance(strategy = InheritanceType.SINGLE_TABLE) + @DiscriminatorValue("null") + public static class RootEntity { + + @Id + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + @Entity(name = "val1_ent") + @DiscriminatorValue("val1") + public static class Val1Entity extends RootEntity { + + } + + @Entity(name = "val2_ent") + @DiscriminatorValue("val2") + public static class Val2Entity extends RootEntity { + + } + + @Entity(name = "notnull_ent") + @DiscriminatorValue("not null") + public static class NotNullEntity extends RootEntity { + + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/inheritance/discriminator/joinedsubclass/JoinedNullNotNullDiscriminatorTest.java b/hibernate-core/src/test/java/org/hibernate/test/inheritance/discriminator/joinedsubclass/JoinedNullNotNullDiscriminatorTest.java new file mode 100644 index 0000000000..495ab9fff4 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/inheritance/discriminator/joinedsubclass/JoinedNullNotNullDiscriminatorTest.java @@ -0,0 +1,114 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.inheritance.discriminator.joinedsubclass; + +import java.sql.Statement; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import javax.persistence.DiscriminatorColumn; +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +@TestForIssue(jiraKey = "HHH-12445") +public class JoinedNullNotNullDiscriminatorTest extends BaseCoreFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + RootEntity.class, + Val1Entity.class, + Val2Entity.class, + NotNullEntity.class + }; + } + + @Test + public void test() { + inTransaction( session -> { + Val1Entity val1 = new Val1Entity(); + val1.setId( 1L ); + + Val2Entity val2 = new Val2Entity(); + val2.setId( 2L ); + + RootEntity root = new RootEntity(); + root.setId( 3L ); + + session.persist( val1 ); + session.persist( val2 ); + session.persist( root ); + + session.doWork( connection -> { + try (Statement statement = connection.createStatement()) { + statement.executeUpdate( + "insert into root_ent (DTYPE, id) " + + "values ('other', 4)" + ); + } + } ); + } ); + + inTransaction( session -> { + Map entities = session.createQuery( + "select e from root_ent e", RootEntity.class ) + .getResultList() + .stream() + .collect( Collectors.toMap( RootEntity::getId, Function.identity() ) ); + + assertThat( entities ).extractingByKey( 1L ).isInstanceOf( Val1Entity.class ); + assertThat( entities ).extractingByKey( 2L ).isInstanceOf( Val2Entity.class ); + assertThat( entities ).extractingByKey( 3L ).isInstanceOf( RootEntity.class ); + assertThat( entities ).extractingByKey( 4L ).isInstanceOf( NotNullEntity.class ); + } ); + } + + @Entity(name = "root_ent") + @Inheritance(strategy = InheritanceType.JOINED) + @DiscriminatorColumn() + @DiscriminatorValue("null") + public static class RootEntity { + + @Id + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + @Entity(name = "val1_ent") + @DiscriminatorValue("val1") + public static class Val1Entity extends RootEntity { + + } + + @Entity(name = "val2_ent") + @DiscriminatorValue("val2") + public static class Val2Entity extends RootEntity { + + } + + @Entity(name = "notnull_ent") + @DiscriminatorValue("not null") + public static class NotNullEntity extends RootEntity { + + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/optlock/OptimisticLockWithGloballyQuotedIdentifierTest.java b/hibernate-core/src/test/java/org/hibernate/test/optlock/OptimisticLockWithGloballyQuotedIdentifierTest.java new file mode 100644 index 0000000000..109b0fc0c4 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/optlock/OptimisticLockWithGloballyQuotedIdentifierTest.java @@ -0,0 +1,92 @@ +package org.hibernate.test.optlock; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.LockModeType; +import javax.persistence.Version; + +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Configuration; + +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class OptimisticLockWithGloballyQuotedIdentifierTest extends BaseCoreFunctionalTestCase { + + @Override + protected void configure(Configuration configuration) { + configuration.setProperty( AvailableSettings.GLOBALLY_QUOTED_IDENTIFIERS, "true" ); + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { Person.class }; + } + + @Before + public void setUp() { + inTransaction( + session -> { + Person person = new Person( "1", "Fabiana" ); + session.persist( person ); + } + ); + } + + @After + public void tearDown() { + inTransaction( + session -> { + session.createQuery( "delete from Person" ).executeUpdate(); + } + ); + } + + @Test + public void testHqlQueryWithOptimisticLock() { + inTransaction( + session -> { + session.createQuery( "from Person e", Person.class ) + .setLockMode( LockModeType.OPTIMISTIC ) + .getResultList().get( 0 ); + } + ); + } + + @Entity(name = "Person") + public static class Person { + @Id + private String id; + + @Version + private long version; + + private String name; + + public Person() { + } + + public Person(String id, String name) { + this.id = id; + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/optlock/OptimisticLockWithQuotedVersionTest.java b/hibernate-core/src/test/java/org/hibernate/test/optlock/OptimisticLockWithQuotedVersionTest.java new file mode 100644 index 0000000000..6d1bb39a87 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/optlock/OptimisticLockWithQuotedVersionTest.java @@ -0,0 +1,89 @@ +package org.hibernate.test.optlock; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.LockModeType; +import javax.persistence.Version; + +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Configuration; + +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class OptimisticLockWithQuotedVersionTest extends BaseCoreFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { Person.class }; + } + + @Before + public void setUp() { + inTransaction( + session -> { + Person person = new Person( "1", "Fabiana" ); + session.persist( person ); + } + ); + } + + @After + public void tearDown() { + inTransaction( + session -> { + session.createQuery( "delete from Person" ).executeUpdate(); + } + ); + } + + @Test + public void testHqlQueryWithOptimisticLock() { + inTransaction( + session -> { + session.createQuery( "from Person e", Person.class ) + .setLockMode( LockModeType.OPTIMISTIC ) + .getResultList().get( 0 ); + } + ); + } + + @Entity(name = "Person") + public static class Person { + @Id + private String id; + + @Version + @Column(name = "`version`") + private long version; + + private String name; + + public Person() { + } + + public Person(String id, String name) { + this.id = id; + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/tool/schema/internal/AbstractSchemaMigratorTest.java b/hibernate-core/src/test/java/org/hibernate/tool/schema/internal/AbstractSchemaMigratorTest.java new file mode 100644 index 0000000000..a817a40526 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/tool/schema/internal/AbstractSchemaMigratorTest.java @@ -0,0 +1,88 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.tool.schema.internal; + +import java.util.ArrayList; +import java.util.Set; + +import org.hibernate.boot.Metadata; +import org.hibernate.boot.model.TruthValue; +import org.hibernate.boot.model.naming.Identifier; +import org.hibernate.boot.model.relational.Namespace; +import org.hibernate.boot.model.relational.QualifiedTableName; +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.internal.Formatter; +import org.hibernate.testing.TestForIssue; +import org.hibernate.tool.schema.extract.internal.ColumnInformationImpl; +import org.hibernate.tool.schema.extract.internal.ForeignKeyInformationImpl; +import org.hibernate.tool.schema.extract.spi.DatabaseInformation; +import org.hibernate.tool.schema.extract.spi.ForeignKeyInformation; +import org.hibernate.tool.schema.extract.spi.NameSpaceTablesInformation; +import org.hibernate.tool.schema.extract.spi.TableInformation; +import org.hibernate.tool.schema.internal.exec.GenerationTarget; +import org.hibernate.tool.schema.spi.ContributableMatcher; +import org.hibernate.tool.schema.spi.ExecutionOptions; +import org.junit.Test; + +import static java.util.Collections.singletonList; +import static org.hamcrest.core.Is.is; +import static org.hibernate.boot.model.naming.Identifier.toIdentifier; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +/** + * @author Emmanuel Duchastenier + */ +public class AbstractSchemaMigratorTest { + + @Test + @TestForIssue(jiraKey = "HHH-13779") + public void testForeignKeyPreExistenceDetectionIgnoresCaseForTableAndColumnName() { + final AbstractSchemaMigrator schemaMigrator = new AbstractSchemaMigrator(null, null) { + @Override + protected NameSpaceTablesInformation performTablesMigration( + Metadata metadata, + DatabaseInformation existingDatabase, + ExecutionOptions options, + ContributableMatcher contributableInclusionFilter, + Dialect dialect, + Formatter formatter, + Set exportIdentifiers, + boolean tryToCreateCatalogs, + boolean tryToCreateSchemas, + Set exportedCatalogs, + Namespace namespace, + GenerationTarget[] targets) { + return null; + } + }; + + final TableInformation existingTableInformation = mock(TableInformation.class); + final ArrayList columnReferenceMappings = new ArrayList<>(); + + final TableInformation destinationTableInformation = mock(TableInformation.class); + doReturn(new QualifiedTableName(toIdentifier("catalog"), toIdentifier("schema"), + toIdentifier("referenced_table"))) // Table name is lower case + .when(destinationTableInformation).getName(); + columnReferenceMappings.add(new ForeignKeyInformationImpl.ColumnReferenceMappingImpl( + new ColumnInformationImpl(null, toIdentifier("referencing_column"), // column name is lower case + 0, "typeName", 255, 0, TruthValue.TRUE), + new ColumnInformationImpl(destinationTableInformation, null, 1, "typeName", 0, 0, TruthValue.TRUE))); + doReturn(singletonList(new ForeignKeyInformationImpl(toIdentifier("FKp8mpamfw2inhj88hwhty1eipm"), columnReferenceMappings))) + .when(existingTableInformation).getForeignKeys(); + + final boolean existInDatabase = schemaMigrator.equivalentForeignKeyExistsInDatabase( + existingTableInformation, + "REFERENCING_COLUMN", "REFERENCED_TABLE"); // Table and column names are UPPER-case here, to prove the test + + assertThat("Expected ForeignKey pre-existence check to be case-insensitive", + existInDatabase, + is(true)); + } + +} \ No newline at end of file diff --git a/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/iso8859/create-script-source2.sql b/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/iso8859/create-script-source2.sql new file mode 100644 index 0000000000..ae16517d82 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/iso8859/create-script-source2.sql @@ -0,0 +1 @@ +INSERT INTO Item(name) VALUES('multi-file-test'); \ No newline at end of file diff --git a/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/iso8859/drop-script-source2.sql b/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/iso8859/drop-script-source2.sql new file mode 100644 index 0000000000..ae16517d82 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/iso8859/drop-script-source2.sql @@ -0,0 +1 @@ +INSERT INTO Item(name) VALUES('multi-file-test'); \ No newline at end of file diff --git a/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/iso8859/load-script-source2.sql b/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/iso8859/load-script-source2.sql new file mode 100644 index 0000000000..4fec78b408 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/jpa/test/schemagen/iso8859/load-script-source2.sql @@ -0,0 +1 @@ +INSERT INTO Item(name) VALUES('multi-file-test'); diff --git a/hibernate-core/src/test/resources/org/hibernate/orm/test/jpa/schemagen/create-script-source2.sql b/hibernate-core/src/test/resources/org/hibernate/orm/test/jpa/schemagen/create-script-source2.sql new file mode 100644 index 0000000000..4fec78b408 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/orm/test/jpa/schemagen/create-script-source2.sql @@ -0,0 +1 @@ +INSERT INTO Item(name) VALUES('multi-file-test'); diff --git a/hibernate-core/src/test/resources/org/hibernate/orm/test/jpa/schemagen/drop-script-source2.sql b/hibernate-core/src/test/resources/org/hibernate/orm/test/jpa/schemagen/drop-script-source2.sql new file mode 100644 index 0000000000..4fec78b408 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/orm/test/jpa/schemagen/drop-script-source2.sql @@ -0,0 +1 @@ +INSERT INTO Item(name) VALUES('multi-file-test'); diff --git a/hibernate-core/src/test/resources/org/hibernate/orm/test/jpa/schemagen/load-script-source2.sql b/hibernate-core/src/test/resources/org/hibernate/orm/test/jpa/schemagen/load-script-source2.sql new file mode 100644 index 0000000000..4fec78b408 --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/orm/test/jpa/schemagen/load-script-source2.sql @@ -0,0 +1 @@ +INSERT INTO Item(name) VALUES('multi-file-test'); diff --git a/hibernate-envers-jakarta/hibernate-envers-jakarta.gradle b/hibernate-envers-jakarta/hibernate-envers-jakarta.gradle new file mode 100644 index 0000000000..9e1e109c9f --- /dev/null +++ b/hibernate-envers-jakarta/hibernate-envers-jakarta.gradle @@ -0,0 +1,103 @@ +import org.apache.tools.ant.filters.ReplaceTokens + +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ + +description = 'Hibernate\'s entity version (audit/history) support Jakarta edition' + +apply from: rootProject.file( 'gradle/published-java-module.gradle' ) + +configurations { + jakartaeeTransformJars +} + +dependencies { + compile( project( ':hibernate-core-jakarta' ) ) { + // Exclude access to this to avoid future use. + exclude group: "org.javassist", module: "javassist" + } + + jakartaeeTransformJars 'biz.aQute.bnd:biz.aQute.bnd.transform:5.1.1', + 'commons-cli:commons-cli:1.4', + 'org.slf4j:slf4j-simple:1.7.30', + 'org.slf4j:slf4j-api:1.7.26', + 'org.eclipse.transformer:org.eclipse.transformer:0.2.0', + 'org.eclipse.transformer:org.eclipse.transformer.cli:0.2.0' + + testCompile( project( ':hibernate-envers-jakarta' ) ) + testCompile( project( ':hibernate-testing-jakarta' ) ) + testCompile( project( path: ':hibernate-core-jakarta', configuration: 'tests' ) ) +} + +jar { + mustRunAfter project(':hibernate-envers').tasks.jar + mustRunAfter project(':hibernate-envers').tasks.testJar + dependsOn project(':hibernate-envers').tasks.jar + dependsOn project(':hibernate-envers').tasks.testJar + def baseDir = project(':hibernate-envers').buildDir + def baseJars = fileTree(baseDir).matching {include 'libs/*.jar' } + inputs.files(baseJars).skipWhenEmpty() + outputs.dir project.buildDir + doLast { + new File(project.buildDir, "libs").mkdirs() + fileTree(project.buildDir).matching { include 'libs/*.jar' }.each { delete it } + + baseJars.each { bundleJar -> + def sourceJarPath = baseDir.path + '/libs/' + bundleJar.name + println 'Initial bundle jar name [ ' + sourceJarPath + ' ]' + + def finalBundleJarName = project.buildDir.path + '/libs/' + bundleJar.name.replaceAll( 'hibernate-envers', 'hibernate-envers-jakarta' ) + println 'Default jakarta final bundle jar name [ ' + finalBundleJarName + ' ]' + + def transformerArgs = [ + sourceJarPath, finalBundleJarName, + '-q', // quiet output + '-tr', new File(getProjectDir().getParentFile(), 'rules/jakarta-renames.properties').path, + '-tv', new File(getProjectDir().getParentFile(), 'rules/jakarta-versions.properties').path, + '-td', new File(getProjectDir().getParentFile(), 'rules/jakarta-direct.properties').path, + ] + + println 'Transformer options:' + transformerArgs.each { + println ' [ ' + it + ' ]' + } + + javaexec { + classpath configurations.jakartaeeTransformJars + main = 'org.eclipse.transformer.jakarta.JakartaTransformer' + args = transformerArgs + } + } + } +} + +task unpackTestJar(type: Copy) { + dependsOn jar + fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { + def outputDir = file("${buildDir}/unpacked/" + it.name) + from zipTree(it) + into outputDir + } +} + +test { + dependsOn unpackTestJar + fileTree(project.buildDir).matching { include 'libs/*-test.jar' }.each { + def outputDir = file("${buildDir}/unpacked/" + it.name) + testClassesDirs += files(outputDir) + classpath += files(outputDir) + } + systemProperty 'file.encoding', 'utf-8' + + if ( gradle.ext.javaVersions.test.launcher.asInt() >= 9 ) { + // See org.hibernate.boot.model.naming.NamingHelperTest.DefaultCharset.set + jvmArgs( ['--add-opens', 'java.base/java.nio.charset=ALL-UNNAMED'] ) + // Weld needs this to generate proxies + jvmArgs( ['--add-opens', 'java.base/java.security=ALL-UNNAMED'] ) + jvmArgs( ['--add-opens', 'java.base/java.lang=ALL-UNNAMED'] ) + } +} \ No newline at end of file diff --git a/hibernate-envers/hibernate-envers.gradle b/hibernate-envers/hibernate-envers.gradle index 92db30e3a2..68ff11caf5 100644 --- a/hibernate-envers/hibernate-envers.gradle +++ b/hibernate-envers/hibernate-envers.gradle @@ -45,6 +45,12 @@ sourceSets { } } +configurations { + tests { + description = 'Configuration for the produced test jar' + } +} + jar { manifest { attributes( @@ -69,6 +75,16 @@ jar { } } +task testJar(type: Jar, dependsOn: testClasses) { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + archiveClassifier.set( 'test' ) + from sourceSets.test.output +} + +artifacts { + tests testJar +} + tasks."matrix_mariadb" { beforeTest { descriptor -> println "Starting test: " + descriptor diff --git a/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle b/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle new file mode 100644 index 0000000000..716f96c9b0 --- /dev/null +++ b/hibernate-testing-jakarta/hibernate-testing-jakarta.gradle @@ -0,0 +1,79 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ + +description = 'Support for testing Hibernate ORM Jakarta functionality' + +apply from: rootProject.file( 'gradle/published-java-module.gradle' ) + +configurations { + jakartaeeTransformJars +} + +dependencies { + compile project( ':hibernate-core-jakarta' ) + compile( libraries.jakarta_jta ) + compile( libraries.junit ) + compile( libraries.byteman ) + compile( libraries.byteman_install ) + compile( libraries.byteman_bmunit ) + compile( libraries.xapool ) + compile( libraries.log4j ) + compile( libraries.jboss_tx_spi_jakarta ) { + transitive=false; + } + compile ( libraries.jboss_jta_jakarta ) { + transitive=false; + } + + jakartaeeTransformJars 'biz.aQute.bnd:biz.aQute.bnd.transform:5.1.1', + 'commons-cli:commons-cli:1.4', + 'org.slf4j:slf4j-simple:1.7.30', + 'org.slf4j:slf4j-api:1.7.26', + 'org.eclipse.transformer:org.eclipse.transformer:0.2.0', + 'org.eclipse.transformer:org.eclipse.transformer.cli:0.2.0' + testCompile fileTree(dir: 'libs', include: '*.jar') +} + +jar { + mustRunAfter project(':hibernate-testing').tasks.jar + dependsOn project(':hibernate-testing').tasks.jar + def baseDir = project(':hibernate-testing').buildDir + def baseJars = fileTree(baseDir).matching {include 'libs/*.jar' } + inputs.files(baseJars).skipWhenEmpty() + outputs.dir project.buildDir + doLast { + new File(project.buildDir, "libs").mkdirs() + fileTree(project.buildDir).matching { include 'libs/*.jar' }.each { delete it } + + baseJars.each { bundleJar -> + def sourceJarPath = baseDir.path + '/libs/' + bundleJar.name + println 'Initial bundle jar name [ ' + sourceJarPath + ' ]' + + def finalBundleJarName = project.buildDir.path + '/libs/' + bundleJar.name.replaceAll( 'hibernate-testing', 'hibernate-testing-jakarta' ) + println 'Default jakarta final bundle jar name [ ' + finalBundleJarName + ' ]' + + def transformerArgs = [ + sourceJarPath, finalBundleJarName, + '-q', // quiet output + '-tr', new File(getProjectDir().getParentFile(), 'rules/jakarta-renames.properties').path, + '-tv', new File(getProjectDir().getParentFile(), 'rules/jakarta-versions.properties').path, + '-td', new File(getProjectDir().getParentFile(), 'rules/jakarta-direct.properties').path, + ] + + println 'Transformer options:' + transformerArgs.each { + println ' [ ' + it + ' ]' + } + + javaexec { + classpath configurations.jakartaeeTransformJars + main = 'org.eclipse.transformer.jakarta.JakartaTransformer' + args = transformerArgs + } + } + } +} diff --git a/hibernate-testing/hibernate-testing.gradle b/hibernate-testing/hibernate-testing.gradle index e9dfb85518..f4aeb39736 100644 --- a/hibernate-testing/hibernate-testing.gradle +++ b/hibernate-testing/hibernate-testing.gradle @@ -22,9 +22,9 @@ dependencies { api libraries.byteman_bmunit api libraries.xapool -// api( libraries.jboss_tx_spi ) { -// transitive=false; -// } + api( libraries.jboss_tx_spi ) { + transitive=false; + } api( libraries.jboss_jta ) { transitive=false; } diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/jdbc/ConnectionProviderDelegate.java b/hibernate-testing/src/main/java/org/hibernate/testing/jdbc/ConnectionProviderDelegate.java index a3fa64c301..e1cd53ad46 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/jdbc/ConnectionProviderDelegate.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/jdbc/ConnectionProviderDelegate.java @@ -75,6 +75,9 @@ public class ConnectionProviderDelegate implements serviceRegistry ); } + if ( connectionProvider instanceof ServiceRegistryAwareService ) { + ( (ServiceRegistryAwareService) connectionProvider ).injectServices( serviceRegistry ); + } if ( connectionProvider instanceof Configurable ) { Configurable configurableConnectionProvider = (Configurable) connectionProvider; configurableConnectionProvider.configure( configurationValues ); diff --git a/hibernate-transaction-client/hibernate-transaction-client.gradle b/hibernate-transaction-client/hibernate-transaction-client.gradle new file mode 100644 index 0000000000..2341fccede --- /dev/null +++ b/hibernate-transaction-client/hibernate-transaction-client.gradle @@ -0,0 +1,68 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ + +description = 'Wildfly Transaction Client transformed to be JTA 2.0 compatible' + +apply from: rootProject.file( 'gradle/published-java-module.gradle' ) + +tasks.withType(PublishToMavenRepository) { + onlyIf { + repository.name == "MavenLocal" + } +} + +configurations { + jakartaeeTransformJars +} + +dependencies { + compile( libraries.jakarta_jta ) + + jakartaeeTransformJars 'biz.aQute.bnd:biz.aQute.bnd.transform:5.1.1', + 'commons-cli:commons-cli:1.4', + 'org.slf4j:slf4j-simple:1.7.30', + 'org.slf4j:slf4j-api:1.7.26', + 'org.eclipse.transformer:org.eclipse.transformer:0.2.0', + 'org.eclipse.transformer:org.eclipse.transformer.cli:0.2.0' + testCompile ( libraries.wildfly_transaction_client ) { + transitive=false; + } +} + +jar { + def sourceJarPath = project.configurations.testCompile.find { it.name.startsWith("wildfly-transaction-client-") } + inputs.files(sourceJarPath).skipWhenEmpty() + outputs.dir project.buildDir + doLast { + new File(project.buildDir, "libs").mkdirs() + fileTree(project.buildDir).matching { include 'libs/*.jar' }.each { delete it } + + println 'Initial bundle jar name [ ' + sourceJarPath + ' ]' + + def finalBundleJarName = project.buildDir.path + '/libs/hibernate-transaction-client-' + project.version + ".jar" + println 'Default jakarta final bundle jar name [ ' + finalBundleJarName + ' ]' + + def transformerArgs = [ + sourceJarPath, finalBundleJarName, + '-q', // quiet output + '-tr', new File(getProjectDir().getParentFile(), 'rules/jakarta-renames.properties').path, + '-tv', new File(getProjectDir().getParentFile(), 'rules/jakarta-versions.properties').path, + '-td', new File(getProjectDir().getParentFile(), 'rules/jakarta-direct.properties').path, + ] + + println 'Transformer options:' + transformerArgs.each { + println ' [ ' + it + ' ]' + } + + javaexec { + classpath configurations.jakartaeeTransformJars + main = 'org.eclipse.transformer.jakarta.JakartaTransformer' + args = transformerArgs + } + } +} \ No newline at end of file diff --git a/rules/jakarta-direct-modelgen.properties b/rules/jakarta-direct-modelgen.properties new file mode 100644 index 0000000000..40142417e8 --- /dev/null +++ b/rules/jakarta-direct-modelgen.properties @@ -0,0 +1,34 @@ +# Taken from https://github.com/OpenLiberty/open-liberty/tree/30ca58383f9018227afd4b511bdedf33363b747e/dev/wlp-jakartaee-transform/rules + +# Direct String Replacement + +http\://java.sun.com/xml/ns/jaxb=https://jakarta.ee/xml/ns/jaxb + +# xmlBinding-3.0 properties +javax.xml.bind.JAXBElement=jakarta.xml.bind.JAXBElement + +com.sun.xml.bind.v2.ContextFactory=org.glassfish.jaxb.runtime.v2.JAXBContextFactory + +javax.annotation.security.RolesAllowed=jakarta.annotation.security.RolesAllowed + +javax.persistence.Entity=jakarta.persistence.Entity +javax.persistence.MappedSuperclass=jakarta.persistence.MappedSuperclass +javax.persistence.Embeddable=jakarta.persistence.Embeddable +javax.persistence.Id=jakarta.persistence.Id +javax.persistence.EmbeddedId=jakarta.persistence.EmbeddedId +javax.persistence.Transient=jakarta.persistence.Transient +javax.persistence.Basic=jakarta.persistence.Basic +javax.persistence.OneToOne=jakarta.persistence.OneToOne +javax.persistence.OneToMany=jakarta.persistence.OneToMany +javax.persistence.ManyToOne=jakarta.persistence.ManyToOne +javax.persistence.ManyToMany=jakarta.persistence.ManyToMany +javax.persistence.MapKeyClass=jakarta.persistence.MapKeyClass +javax.persistence.ElementCollection=jakarta.persistence.ElementCollection +javax.persistence.Access=jakarta.persistence.Access +javax.persistence.Convert=jakarta.persistence.Convert +javax.persistence.metamodel.StaticMetamodel=jakarta.persistence.metamodel.StaticMetamodel +javax.persistence.metamodel.SingularAttribute=jakarta.persistence.metamodel.SingularAttribute +javax.persistence.metamodel.CollectionAttribute=jakarta.persistence.metamodel.CollectionAttribute +javax.persistence.metamodel.SetAttribute=jakarta.persistence.metamodel.SetAttribute +javax.persistence.metamodel.ListAttribute=jakarta.persistence.metamodel.ListAttribute +javax.persistence.metamodel.MapAttribute=jakarta.persistence.metamodel.MapAttribute \ No newline at end of file diff --git a/rules/jakarta-direct.properties b/rules/jakarta-direct.properties new file mode 100644 index 0000000000..cd8e6b52ac --- /dev/null +++ b/rules/jakarta-direct.properties @@ -0,0 +1,12 @@ +# Taken from https://github.com/OpenLiberty/open-liberty/tree/30ca58383f9018227afd4b511bdedf33363b747e/dev/wlp-jakartaee-transform/rules + +# Direct String Replacement + +http\://java.sun.com/xml/ns/jaxb=https://jakarta.ee/xml/ns/jaxb + +# xmlBinding-3.0 properties +javax.xml.bind.JAXBElement=jakarta.xml.bind.JAXBElement + +com.sun.xml.bind.v2.ContextFactory=org.glassfish.jaxb.runtime.v2.JAXBContextFactory + +javax.annotation.security.RolesAllowed=jakarta.annotation.security.RolesAllowed diff --git a/rules/jakarta-renames.properties b/rules/jakarta-renames.properties new file mode 100644 index 0000000000..86e5ac487f --- /dev/null +++ b/rules/jakarta-renames.properties @@ -0,0 +1,260 @@ +# Taken from https://github.com/OpenLiberty/open-liberty/tree/30ca58383f9018227afd4b511bdedf33363b747e/dev/wlp-jakartaee-transform/rules + +com.sun.xml.bind=org.glassfish.jaxb.runtime +com.sun.xml.bind.api=org.glassfish.jaxb.runtime.api +com.sun.xml.bind.api.impl=org.glassfish.jaxb.core.api.impl +com.sun.xml.bind.marshaller=org.glassfish.jaxb.core.marshaller +com.sun.xml.bind.unmarshaller=org.glassfish.jaxb.core.unmarshaller +com.sun.xml.bind.util=org.glassfish.jaxb.runtime.util +com.sun.xml.bind.v2=org.glassfish.jaxb.runtime.v2 +com.sun.xml.bind.v2.model.annotation=org.glassfish.jaxb.runtime.v2.model.annotation +com.sun.xml.bind.v2.model.nav=org.glassfish.jaxb.core.v2.model.nav +com.sun.xml.bind.v2.model.runtime=org.glassfish.jaxb.runtime.v2.model.runtime +com.sun.xml.bind.v2.runtime=org.glassfish.jaxb.runtime.v2.runtime +com.sun.xml.bind.v2.runtime.unmarshaller=org.glassfish.jaxb.runtime.v2.runtime.unmarshaller +com.sun.xml.bind.v2.schemagen=org.glassfish.jaxb.runtime.v2.schemagen +com.sun.xml.bind.v2.schemagen.xmlschema=org.glassfish.jaxb.runtime.v2.schemagen.xmlschema +com.sun.xml.bind.v2.util=org.glassfish.jaxb.runtime.v2.util +com.sun.xml.internal.bind=org.glassfish.jaxb + +javax.activation=jakarta.activation +javax.annotation.security=jakarta.annotation.security +javax.annotation.sql=jakarta.annotation.sql +javax.annotation=jakarta.annotation +javax.batch.api=jakarta.batch.api +javax.batch.api.chunk=jakarta.batch.api.chunk +javax.batch.api.chunk.listener=jakarta.batch.api.chunk.listener +javax.batch.api.listener=jakarta.batch.api.listener +javax.batch.api.partition=jakarta.batch.api.partition +javax.batch.operations=jakarta.batch.operations +javax.batch.runtime=jakarta.batch.runtime +javax.batch.runtime.context=jakarta.batch.runtime.context +javax.decorator=jakarta.decorator +javax.ejb=jakarta.ejb +javax.ejb.embeddable=jakarta.ejb.embeddable +javax.ejb.spi=jakarta.ejb.spi +javax.el=jakarta.el +javax.enterprise.concurrent=jakarta.enterprise.concurrent +javax.enterprise.context.control=jakarta.enterprise.context.control +javax.enterprise.context.spi=jakarta.enterprise.context.spi +javax.enterprise.context=jakarta.enterprise.context +javax.enterprise.event=jakarta.enterprise.event +javax.enterprise.inject.literal=jakarta.enterprise.inject.literal +javax.enterprise.inject.se=jakarta.enterprise.inject.se +javax.enterprise.inject.spi.configurator=jakarta.enterprise.inject.spi.configurator +javax.enterprise.inject.spi=jakarta.enterprise.inject.spi +javax.enterprise.inject=jakarta.enterprise.inject +javax.enterprise.util=jakarta.enterprise.util +javax.faces=jakarta.faces +javax.faces.annotation=jakarta.faces.annotation +javax.faces.application=jakarta.faces.application +javax.faces.bean=jakarta.faces.bean +javax.faces.component=jakarta.faces.component +javax.faces.component.behavior=jakarta.faces.component.behavior +javax.faces.component.html=jakarta.faces.component.html +javax.faces.component.search=jakarta.faces.component.search +javax.faces.component.visit=jakarta.faces.component.visit +javax.faces.context=jakarta.faces.context +javax.faces.convert=jakarta.faces.convert +javax.faces.el=jakarta.faces.el +javax.faces.event=jakarta.faces.event +javax.faces.flow=jakarta.faces.flow +javax.faces.flow.builder=jakarta.faces.flow.builder +javax.faces.lifecycle=jakarta.faces.lifecycle +javax.faces.model=jakarta.faces.model +javax.faces.push=jakarta.faces.push +javax.faces.render=jakarta.faces.render +javax.faces.validator=jakarta.faces.validator +javax.faces.view=jakarta.faces.view +javax.faces.view.facelets=jakarta.faces.view.facelets +javax.faces.webapp=jakarta.faces.webapp +javax.inject=jakarta.inject +javax.interceptor=jakarta.interceptor +javax.jms=jakarta.jms +javax.json.bind.adapter=jakarta.json.bind.adapter +javax.json.bind.annotation=jakarta.json.bind.annotation +javax.json.bind.config=jakarta.json.bind.config +javax.json.bind.serializer=jakarta.json.bind.serializer +javax.json.bind.spi=jakarta.json.bind.spi +javax.json.bind=jakarta.json.bind +javax.json.spi=jakarta.json.spi +javax.json.stream=jakarta.json.stream +javax.json=jakarta.json +javax.jws=jakarta.jws +javax.jws.soap=jakarta.jws.soap +javax.mail=jakarta.mail +javax.persistence.criteria=jakarta.persistence.criteria +javax.persistence.metamodel=jakarta.persistence.metamodel +javax.persistence.spi=jakarta.persistence.spi +javax.persistence=jakarta.persistence +javax.persistence.cache.storeMode=jakarta.persistence.cache.storeMode +javax.persistence.cache.retrieveMode=jakarta.persistence.cache.retrieveMode +javax.persistence.bean.manager=jakarta.persistence.bean.manager +javax.persistence.validation.factory=jakarta.persistence.validation.factory +javax.resource.cci=jakarta.resource.cci +javax.resource.spi.endpoint=jakarta.resource.spi.endpoint +javax.resource.spi.security=jakarta.resource.spi.security +javax.resource.spi.work=jakarta.resource.spi.work +javax.resource.spi=jakarta.resource.spi +javax.resource=jakarta.resource +javax.security.auth.message=jakarta.security.auth.message +javax.security.auth.message.callback=jakarta.security.auth.message.callback +javax.security.auth.message.config=jakarta.security.auth.message.config +javax.security.auth.message.module=jakarta.security.auth.message.module +javax.security.enterprise=jakarta.security.enterprise +javax.security.enterprise.authentication.mechanism.http=jakarta.security.enterprise.authentication.mechanism.http +javax.security.enterprise.credential=jakarta.security.enterprise.credential +javax.security.enterprise.identitystore=jakarta.security.enterprise.identitystore +javax.security.jacc=jakarta.security.jacc +javax.servlet.annotation=jakarta.servlet.annotation +javax.servlet.descriptor=jakarta.servlet.descriptor +javax.servlet.http=jakarta.servlet.http +javax.servlet.jsp.el=jakarta.servlet.jsp.el +javax.servlet.jsp.jstl.core=jakarta.servlet.jsp.jstl.core +javax.servlet.jsp.jstl.fmt=jakarta.servlet.jsp.jstl.fmt +javax.servlet.jsp.jstl.sql=jakarta.servlet.jsp.jstl.sql +javax.servlet.jsp.jstl.tlv=jakarta.servlet.jsp.jstl.tlv +javax.servlet.jsp.jstl=jakarta.servlet.jsp.jstl +javax.servlet.jsp.resources=jakarta.servlet.jsp.resources +javax.servlet.jsp.tagext=jakarta.servlet.jsp.tagext +javax.servlet.jsp=jakarta.servlet.jsp +javax.servlet.resources=jakarta.servlet.resources +javax.servlet=jakarta.servlet +javax.transaction=jakarta.transaction +javax.validation=jakarta.validation +javax.validation.bootstrap=jakarta.validation.bootstrap +javax.validation.constraints=jakarta.validation.constraints +javax.validation.constraintvalidation=jakarta.validation.constraintvalidation +javax.validation.executable=jakarta.validation.executable +javax.validation.groups=jakarta.validation.groups +javax.validation.metadata=jakarta.validation.metadata +javax.validation.spi=jakarta.validation.spi +javax.validation.valueextraction=jakarta.validation.valueextraction +javax.websocket=jakarta.websocket +javax.websocket.server=jakarta.websocket.server +javax.ws.rs=jakarta.ws.rs +javax.ws.rs.client=jakarta.ws.rs.client +javax.ws.rs.container=jakarta.ws.rs.container +javax.ws.rs.core=jakarta.ws.rs.core +javax.ws.rs.ext=jakarta.ws.rs.ext +javax.ws.rs.sse=jakarta.ws.rs.sse +javax.xml.bind.annotation.adapters=jakarta.xml.bind.annotation.adapters +javax.xml.bind.annotation=jakarta.xml.bind.annotation +javax.xml.bind.attachment=jakarta.xml.bind.attachment +javax.xml.bind.helpers=jakarta.xml.bind.helpers +javax.xml.bind.util=jakarta.xml.bind.util +javax.xml.bind=jakarta.xml.bind +javax.xml.soap=jakarta.xml.soap +javax.xml.ws=jakarta.xml.ws +javax.xml.ws.handler=jakarta.xml.ws.handler +javax.xml.ws.handler.soap=jakarta.xml.ws.handler.soap +javax.xml.ws.http=jakarta.xml.ws.http +javax.xml.ws.soap=jakarta.xml.ws.soap +javax.xml.ws.spi=jakarta.xml.ws.spi +javax.xml.ws.spi.http=jakarta.xml.ws.spi.http +javax.xml.ws.wsaddressing=jakarta.xml.ws.wsaddressing + + +#Required for common enterprise beans test tools +com.ibm.websphere.ejbcontainer.test.mdb=io.openliberty.ejbcontainer.jakarta.test.mdb +com.ibm.websphere.ejbcontainer.test.mdb.interceptors=io.openliberty.ejbcontainer.jakarta.test.mdb.interceptors +com.ibm.websphere.ejbcontainer.test.osgi.pmi=io.openliberty.ejbcontainer.jakarta.test.osgi.pmi +com.ibm.websphere.ejbcontainer.test.osgi.pmi.internal=io.openliberty.ejbcontainer.jakarta.test.osgi.pmi.internal +com.ibm.websphere.ejbcontainer.test.tools=io.openliberty.ejbcontainer.jakarta.test.tools + +#Required to transform the package versions only +com.ibm.wsspi.el=com.ibm.wsspi.el +org.apache.myfaces.cdi.util=org.apache.myfaces.cdi.util +org.apache.myfaces.config.annotation=org.apache.myfaces.config.annotation +org.apache.myfaces.ee=org.apache.myfaces.ee +org.apache.myfaces.shared.util=org.apache.myfaces.shared.util +org.apache.myfaces.spi=org.apache.myfaces.spi +org.apache.myfaces.util=org.apache.myfaces.util +org.apache.myfaces.webapp=org.apache.myfaces.webapp +org.hibernate.validator=org.hibernate.validator +org.hibernate.validator.cdi.internal=org.hibernate.validator.cdi.internal +org.hibernate.validator.cdi=org.hibernate.validator.cdi +org.hibernate.validator.internal.engine.valueextraction=org.hibernate.validator.internal.engine.valueextraction +org.hibernate.validator.internal.properties=org.hibernate.validator.internal.properties +org.hibernate.validator.internal.util.classhierarchy=org.hibernate.validator.internal.util.classhierarchy +org.hibernate.validator.internal.util.logging=org.hibernate.validator.internal.util.logging +org.hibernate.validator.internal.util.privilegedactions=org.hibernate.validator.internal.util.privilegedactions +org.hibernate.validator.internal.util=org.hibernate.validator.internal.util +org.hibernate.validator.internal=org.hibernate.validator.internal +org.hibernate.validator.spi.properties=org.hibernate.validator.spi.properties +org.jboss.weld.annotated.enhanced=org.jboss.weld.annotated.enhanced +org.jboss.weld.bean.builtin=org.jboss.weld.bean.builtin +org.jboss.weld.bean.proxy=org.jboss.weld.bean.proxy +org.jboss.weld.bean.proxy.util=org.jboss.weld.bean.proxy.util +org.jboss.weld.bean=org.jboss.weld.bean +org.jboss.weld.bootstrap.api.helpers=org.jboss.weld.bootstrap.api.helpers +org.jboss.weld.bootstrap.api=org.jboss.weld.bootstrap.api +org.jboss.weld.bootstrap.spi.helpers=org.jboss.weld.bootstrap.spi.helpers +org.jboss.weld.bootstrap.spi=org.jboss.weld.bootstrap.spi +org.jboss.weld.bootstrap=org.jboss.weld.bootstrap +org.jboss.weld.config=org.jboss.weld.config +org.jboss.weld.construction.api=org.jboss.weld.construction.api +org.jboss.weld.context=org.jboss.weld.context +org.jboss.weld.context.api=org.jboss.weld.context.api +org.jboss.weld.context.bound=org.jboss.weld.context.bound +org.jboss.weld.context.http=org.jboss.weld.context.http +org.jboss.weld.contexts=org.jboss.weld.contexts +org.jboss.weld.ejb.api=org.jboss.weld.ejb.api +org.jboss.weld.ejb.spi=org.jboss.weld.ejb.spi +org.jboss.weld.exceptions=org.jboss.weld.exceptions +org.jboss.weld.executor=org.jboss.weld.executor +org.jboss.weld.injection.spi=org.jboss.weld.injection.spi +org.jboss.weld.injection=org.jboss.weld.injection +org.jboss.weld.interceptor.spi.model=org.jboss.weld.interceptor.spi.model +org.jboss.weld.manager.api=org.jboss.weld.manager.api +org.jboss.weld.manager=org.jboss.weld.manager +org.jboss.weld.metadata=org.jboss.weld.metadata +org.jboss.weld.module.ejb=org.jboss.weld.module.ejb +org.jboss.weld.module.jsf=org.jboss.weld.module.jsf +org.jboss.weld.module.web.el=org.jboss.weld.module.web.el +org.jboss.weld.module.web.servlet=org.jboss.weld.module.web.servlet +org.jboss.weld.probe=org.jboss.weld.probe +org.jboss.weld.resolution=org.jboss.weld.resolution +org.jboss.weld.resources.spi=org.jboss.weld.resources.spi +org.jboss.weld.resources=org.jboss.weld.resources +org.jboss.weld.security.spi=org.jboss.weld.security.spi +org.jboss.weld.serialization.spi=org.jboss.weld.serialization.spi +org.jboss.weld.transaction.spi=org.jboss.weld.transaction.spi +org.jboss.weld.util.collections=org.jboss.weld.util.collections +org.jboss.weld=org.jboss.weld + +org.eclipse.persistence.exceptions=org.eclipse.persistence.exceptions +org.eclipse.persistence.logging=org.eclipse.persistence.logging +org.eclipse.persistence.platform.server=org.eclipse.persistence.platform.server +org.eclipse.persistence.internal.databaseaccess=org.eclipse.persistence.internal.databaseaccess +org.eclipse.persistence.internal.helper=org.eclipse.persistence.internal.helper +org.eclipse.persistence.internal.security=org.eclipse.persistence.internal.security +org.eclipse.persistence.internal.sessions=org.eclipse.persistence.internal.sessions + +org.eclipse.persistence.annotations=org.eclipse.persistence.annotations +org.eclipse.persistence.descriptors=org.eclipse.persistence.descriptors +org.eclipse.persistence.descriptors.changetracking=org.eclipse.persistence.descriptors.changetracking +org.eclipse.persistence.queries=org.eclipse.persistence.queries +org.eclipse.persistence.indirection=org.eclipse.persistence.indirection +org.eclipse.persistence.internal.descriptors=org.eclipse.persistence.internal.descriptors +org.eclipse.persistence.internal.identitymaps=org.eclipse.persistence.internal.identitymaps +org.eclipse.persistence.internal.jpa=org.eclipse.persistence.internal.jpa +org.eclipse.persistence.internal.jpa.rs.metadata.model=org.eclipse.persistence.internal.jpa.rs.metadata.model +org.eclipse.persistence.internal.weaving=org.eclipse.persistence.internal.weaving +org.eclipse.persistence.jpa=org.eclipse.persistence.jpa +org.eclipse.persistence.platform.server.was=org.eclipse.persistence.platform.server.was +org.eclipse.persistence.internal.sessions.cdi=org.eclipse.persistence.internal.sessions.cdi +org.eclipse.persistence.platform.database=org.eclipse.persistence.platform.database +org.eclipse.persistence.sessions=org.eclipse.persistence.sessions +org.eclipse.persistence.tools.schemaframework=org.eclipse.persistence.tools.schemaframework +org.eclipse.persistence.transaction=org.eclipse.persistence.transaction + +com.sun.xml.internal.messaging.saaj.packaging.mime=com.sun.xml.messaging.saaj.packaging.mime +com.sun.xml.internal.messaging.saaj.packaging.mime.internet=com.sun.xml.messaging.saaj.packaging.mime.internet +com.sun.xml.internal.messaging.saaj.packaging.mime.util=com.sun.xml.messaging.saaj.packaging.mime.util +com.sun.xml.internal.messaging.saaj.soap=com.sun.xml.messaging.saaj.soap +com.sun.xml.internal.messaging.saaj.soap.dynamic=com.sun.xml.messaging.saaj.soap.dynamic +com.sun.xml.internal.messaging.saaj.soap.name=com.sun.xml.messaging.saaj.soap.name +com.sun.xml.internal.messaging.saaj.util=com.sun.xml.messaging.saaj.util +com.sun.xml.internal.messaging.saaj.util.stax=com.sun.xml.messaging.saaj.util.stax +com.sun.xml.internal.messaging.saaj.util.transform=com.sun.xml.messaging.saaj.util.transform diff --git a/rules/jakarta-versions.properties b/rules/jakarta-versions.properties new file mode 100644 index 0000000000..e43ebefeb4 --- /dev/null +++ b/rules/jakarta-versions.properties @@ -0,0 +1,223 @@ +# Taken from https://github.com/OpenLiberty/open-liberty/tree/30ca58383f9018227afd4b511bdedf33363b747e/dev/wlp-jakartaee-transform/rules + +com.ibm.wsspi.el=[4.0,5) +jakarta.activation=[2.0,3) +jakarta.annotation.security=[2.0,3) +jakarta.annotation.sql=[2.0,3) +jakarta.annotation=[2.0,3) +jakarta.batch.api=[2.0,3) +jakarta.batch.api.chunk=[2.0,3) +jakarta.batch.api.chunk.listener=[2.0,3) +jakarta.batch.api.listener=[2.0,3) +jakarta.batch.api.partition=[2.0,3) +jakarta.batch.operations=[2.0,3) +jakarta.batch.runtime=[2.0,3) +jakarta.batch.runtime.context=[2.0,3) +jakarta.decorator=[3.0,4.0) +jakarta.ejb=[4.0,5) +jakarta.ejb.embeddable=[4.0,5) +jakarta.ejb.spi=[4.0,5) +jakarta.el=[4.0,5) +jakarta.enterprise.concurrent=[2.0,3) +jakarta.enterprise.context.control=[3.0,4.0) +jakarta.enterprise.context.spi=[3.0,4.0) +jakarta.enterprise.context=[3.0,4.0) +jakarta.enterprise.event=[3.0,4.0) +jakarta.enterprise.inject.literal=[3.0,4.0) +jakarta.enterprise.inject.spi.configurator=[3.0,4.0) +jakarta.enterprise.inject.spi=[3.0,4.0) +jakarta.enterprise.inject=[3.0,4.0) +jakarta.enterprise.util=[3.0,4.0) +jakarta.faces=[3.0,4.0) +jakarta.faces.application=[3.0,4.0) +jakarta.faces.bean=[3.0,4.0) +jakarta.faces.component=[3.0,4.0) +jakarta.faces.component.behavior=[3.0,4.0) +jakarta.faces.context=[3.0,4.0) +jakarta.faces.convert=[3.0,4.0) +jakarta.faces.event=[3.0,4.0) +jakarta.faces.model=[3.0,4.0) +jakarta.faces.render=[3.0,4.0) +jakarta.faces.validator=[3.0,4.0) +jakarta.faces.view.facelets=[3.0,4.0) +jakarta.faces.webapp=[3.0,4.0) +jakarta.inject=[2.0,3.0) +jakarta.interceptor=[2.0,3.0) +jakarta.json.bind.adapter=[2.0,3.0) +jakarta.json.bind.annotation=[2.0,3.0) +jakarta.json.bind.config=[2.0,3.0) +jakarta.json.bind.serializer=[2.0,3.0) +jakarta.json.bind.spi=[2.0,3.0) +jakarta.json.bind=[2.0,3.0) +jakarta.json.spi=[2.0,3.0) +jakarta.json.stream=[2.0,3.0) +jakarta.json=[2.0,3.0) +jakarta.jms=[3.0,4) +jakarta.jws=[3.0,4) +jakarta.jws.soap=[3.0,4) +jakarta.persistence.criteria=[3.0,4) +jakarta.persistence.metamodel=[3.0,4) +jakarta.persistence.spi=[3.0,4) +jakarta.persistence=[3.0,4) +jakarta.resource.cci=[2.0,3) +jakarta.resource.spi.endpoint=[2.0,3) +jakarta.resource.spi.security=[2.0,3) +jakarta.resource.spi.work=[2.0,3) +jakarta.resource.spi=[2.0,3) +jakarta.resource=[2.0,3) +jakarta.security.auth.message=[2.0,3) +jakarta.security.auth.message.callback=[2.0,3) +jakarta.security.auth.message.config=[2.0,3) +jakarta.security.auth.message.module=[2.0,3) +jakarta.security.enterprise=[2.0,3) +jakarta.security.enterprise.authentication.mechanism.http=[2.0,3) +jakarta.security.enterprise.credential=[2.0,3) +jakarta.security.enterprise.identitystore=[2.0,3) +jakarta.security.jacc=[2.0,3) +jakarta.servlet.annotation=[5.0,6) +jakarta.servlet.descriptor=[5.0,6) +jakarta.servlet.http=[5.0,6) +jakarta.servlet.jsp.el=[3.0,4) +jakarta.servlet.jsp.jstl.core=[2.0,3) +jakarta.servlet.jsp.jstl.fmt=[2.0,3) +jakarta.servlet.jsp.jstl.sql=[2.0,3) +jakarta.servlet.jsp.jstl.tlv=[2.0,3) +jakarta.servlet.jsp.jstl=[2.0,3) +jakarta.servlet.jsp.resources=[3.0,4) +jakarta.servlet.jsp.tagext=[3.0,4) +jakarta.servlet.jsp=[3.0,4) +jakarta.servlet.resources=[5.0,6) +jakarta.servlet=[5.0,6) +jakarta.transaction=[2.0,3) +jakarta.validation=[3.0,4) +jakarta.validation.bootstrap=[3.0,4) +jakarta.validation.constraints=[3.0,4) +jakarta.validation.constraintvalidation=[3.0,4) +jakarta.validation.executable=[3.0,4) +jakarta.validation.groups=[3.0,4) +jakarta.validation.metadata=[3.0,4) +jakarta.validation.spi=[3.0,4) +jakarta.validation.valueextraction=[3.0,4) +jakarta.ws.rs=[3.0,4.0) +jakarta.ws.rs.client=[3.0,4.0) +jakarta.ws.rs.container=[3.0,4.0) +jakarta.ws.rs.core=[3.0,4.0) +jakarta.ws.rs.ext=[3.0,4.0) +jakarta.ws.rs.sse=[3.0,4.0) +jakarta.xml.bind.annotation.adapters=[3.0,4) +jakarta.xml.bind.annotation=[3.0,4) +jakarta.xml.bind.attachment=[3.0,4) +jakarta.xml.bind.helpers=[3.0,4) +jakarta.xml.bind.util=[3.0,4) +jakarta.xml.bind=[3.0,4) +jakarta.xml.soap=[3.0,4) +jakarta.xml.ws=[3.0,4) +jakarta.xml.ws.handler=[3.0,4) +jakarta.xml.ws.handler.soap=[3.0,4) +jakarta.xml.ws.http=[3.0,4) +jakarta.xml.ws.soap=[3.0,4) +jakarta.xml.ws.spi=[3.0,4) +jakarta.xml.ws.spi.http=[3.0,4) +jakarta.xml.ws.wsaddressing=[3.0,4) +jakarta.websocket=[2.0,3) +jakarta.websocket.server=[2.0,3) +org.apache.myfaces.cdi.util=[3.0,4) +org.apache.myfaces.config.annotation=[3.0,4) +org.apache.myfaces.ee=[3.0,4) +org.apache.myfaces.shared.util=[3.0,4) +org.apache.myfaces.spi=[3.0,4) +org.apache.myfaces.util=[3.0,4) +org.apache.myfaces.webapp=[3.0,4) +org.glassfish.jaxb.runtime=[3.0,4) +org.glassfish.jaxb.runtime.api=[3.0,4) +org.glassfish.jaxb.core.api.impl=[3.0,4) +org.glassfish.jaxb.core.marshaller=[3.0,4) +org.glassfish.jaxb.core.unmarshaller=[3.0,4) +org.glassfish.jaxb.runtime.util=[3.0,4) +org.glassfish.jaxb.core.v2.model.nav=[3.0,4) +org.glassfish.jaxb.runtime.v2=[3.0,4) +org.glassfish.jaxb.runtime.v2.model.annotation=[3.0,4) +org.glassfish.jaxb.runtime.v2.model.runtime=[3.0,4) +org.glassfish.jaxb.runtime.v2.runtime=[3.0,4) +org.glassfish.jaxb.runtime.v2.runtime.unmarshaller=[3.0,4) +org.glassfish.jaxb.runtime.v2.schemagen=[3.0,4) +org.glassfish.jaxb.runtime.v2.schemagen.xmlschema=[3.0,4) +org.glassfish.jaxb.runtime.v2.util=[3.0,4) +org.glassfish.jaxb=[3.0,4) +org.hibernate.validator=[7.0,8) +org.hibernate.validator.cdi.internal=[7.0,8) +org.hibernate.validator.cdi=[7.0,8) +org.hibernate.validator.internal.engine.valueextraction=[7.0,8) +org.hibernate.validator.internal.properties=[7.0,8) +org.hibernate.validator.internal.util.classhierarchy=[7.0,8) +org.hibernate.validator.internal.util.logging=[7.0,8) +org.hibernate.validator.internal.util.privilegedactions=[7.0,8) +org.hibernate.validator.internal.util=[7.0,8) +org.hibernate.validator.internal=[7.0,8) +org.hibernate.validator.spi.properties=[7.0,8) +org.jboss.weld.annotated.enhanced=[4.0,5) +org.jboss.weld.bean.builtin=[4.0,5) +org.jboss.weld.bean.proxy=[4.0,5) +org.jboss.weld.bean.proxy.util=[4.0,5) +org.jboss.weld.bean=[4.0,5) +org.jboss.weld.bootstrap.api.helpers=[4.0,5) +org.jboss.weld.bootstrap.api=[4.0,5) +org.jboss.weld.bootstrap.spi.helpers=[4.0,5) +org.jboss.weld.bootstrap.spi=[4.0,5) +org.jboss.weld.bootstrap=[4.0,5) +org.jboss.weld.config=[4.0,5) +org.jboss.weld.construction.api=[4.0,5) +org.jboss.weld.context=[4.0,5) +org.jboss.weld.context.api=[4.0,5) +org.jboss.weld.context.bound=[4.0,5) +org.jboss.weld.context.http=[4.0,5) +org.jboss.weld.contexts=[4.0,5) +org.jboss.weld.ejb.api=[4.0,5) +org.jboss.weld.ejb.spi=[4.0,5) +org.jboss.weld.exceptions=[4.0,5) +org.jboss.weld.executor=[4.0,5) +org.jboss.weld.injection.spi=[4.0,5) +org.jboss.weld.injection=[4.0,5) +org.jboss.weld.interceptor.spi.model=[4.0,5) +org.jboss.weld.manager.api=[4.0,5) +org.jboss.weld.manager=[4.0,5) +org.jboss.weld.metadata=[4.0,5) +org.jboss.weld.module.ejb=[4.0,5) +org.jboss.weld.module.jsf=[4.0,5) +org.jboss.weld.module.web.el=[4.0,5) +org.jboss.weld.module.web.servlet=[4.0,5) +org.jboss.weld.probe=[4.0,5) +org.jboss.weld.resolution=[4.0,5) +org.jboss.weld.resources.spi=[4.0,5) +org.jboss.weld.resources=[4.0,5) +org.jboss.weld.security.spi=[4.0,5) +org.jboss.weld.serialization.spi=[4.0,5) +org.jboss.weld.transaction.spi=[4.0,5) +org.jboss.weld.util.collections=[4.0,5) +org.jboss.weld=[4.0,5) + +org.eclipse.persistence.exceptions=[3.0,4) +org.eclipse.persistence.logging=[3.0,4) +org.eclipse.persistence.platform.server=[3.0,4) +org.eclipse.persistence.internal.databaseaccess=[3.0,4) +org.eclipse.persistence.internal.helper=[3.0,4) +org.eclipse.persistence.internal.security=[3.0,4) +org.eclipse.persistence.internal.sessions=[3.0,4) + +org.eclipse.persistence.annotations=[3.0,4) +org.eclipse.persistence.descriptors=[3.0,4) +org.eclipse.persistence.descriptors.changetracking=[3.0,4) +org.eclipse.persistence.queries=[3.0,4) +org.eclipse.persistence.indirection=[3.0,4) +org.eclipse.persistence.internal.descriptors=[3.0,4) +org.eclipse.persistence.internal.identitymaps=[3.0,4) +org.eclipse.persistence.internal.jpa=[3.0,4) +org.eclipse.persistence.internal.jpa.rs.metadata.model=[3.0,4) +org.eclipse.persistence.internal.weaving=[3.0,4) +org.eclipse.persistence.jpa=[3.0,4) +org.eclipse.persistence.platform.server.was=[3.0,4) +org.eclipse.persistence.internal.sessions.cdi=[3.0,4) +org.eclipse.persistence.platform.database=[3.0,4) +org.eclipse.persistence.sessions=[3.0,4) +org.eclipse.persistence.tools.schemaframework=[3.0,4) +org.eclipse.persistence.transaction=[3.0,4) diff --git a/settings.gradle b/settings.gradle index 5ef4d0bb86..948533a91e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -87,8 +87,15 @@ logger.lifecycle "Java versions for main code: " + gradle.ext.javaVersions.main logger.lifecycle "Java versions for tests: " + gradle.ext.javaVersions.test include 'hibernate-core' +include 'hibernate-core-jakarta' + include 'hibernate-testing' +include 'hibernate-testing-jakarta' +include 'hibernate-transaction-client' + include 'hibernate-envers' +include 'hibernate-envers-jakarta' + // todo (6.0): re-enable hibernate-spatial //include 'hibernate-spatial' @@ -122,6 +129,10 @@ include 'metamodel-generator' project(':metamodel-generator').projectDir = new File(rootProject.projectDir, "tooling/metamodel-generator") project(':metamodel-generator').name = 'hibernate-jpamodelgen' +include 'metamodel-generator-jakarta' +project(':metamodel-generator-jakarta').projectDir = new File(rootProject.projectDir, "tooling/metamodel-generator-jakarta") +project(':metamodel-generator-jakarta').name = 'hibernate-jpamodelgen-jakarta' + include 'hibernate-gradle-plugin' project(':hibernate-gradle-plugin').projectDir = new File(rootProject.projectDir, "tooling/hibernate-gradle-plugin") diff --git a/tooling/metamodel-generator-jakarta/hibernate-jpamodelgen-jakarta.gradle b/tooling/metamodel-generator-jakarta/hibernate-jpamodelgen-jakarta.gradle new file mode 100644 index 0000000000..13d32b6685 --- /dev/null +++ b/tooling/metamodel-generator-jakarta/hibernate-jpamodelgen-jakarta.gradle @@ -0,0 +1,68 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ + +description = 'Annotation Processor to generate JPA 3 static metamodel classes' + +apply from: rootProject.file( 'gradle/published-java-module.gradle' ) + +configurations { + jakartaeeTransformJars +} + +dependencies { + // JAXB + compile( libraries.jakarta_jaxb_api ) + compile( libraries.jakarta_jaxb_runtime ) + + jakartaeeTransformJars 'biz.aQute.bnd:biz.aQute.bnd.transform:5.1.1', + 'commons-cli:commons-cli:1.4', + 'org.slf4j:slf4j-simple:1.7.30', + 'org.slf4j:slf4j-api:1.7.26', + 'org.eclipse.transformer:org.eclipse.transformer:0.2.0', + 'org.eclipse.transformer:org.eclipse.transformer.cli:0.2.0' + testCompile fileTree(dir: 'libs', include: '*.jar') +} + +jar { + mustRunAfter project(':hibernate-jpamodelgen').tasks.jar + dependsOn project(':hibernate-jpamodelgen').tasks.jar + def baseDir = project(':hibernate-jpamodelgen').buildDir + def baseJars = fileTree(baseDir).matching {include 'libs/*.jar' } + inputs.files(baseJars).skipWhenEmpty() + outputs.dir project.buildDir + doLast { + new File(project.buildDir, "libs").mkdirs() + fileTree(project.buildDir).matching { include 'libs/*.jar' }.each { delete it } + + baseJars.each { bundleJar -> + def sourceJarPath = baseDir.path + '/libs/' + bundleJar.name + println 'Initial bundle jar name [ ' + sourceJarPath + ' ]' + + def finalBundleJarName = project.buildDir.path + '/libs/' + bundleJar.name.replaceAll( 'hibernate-jpamodelgen', 'hibernate-jpamodelgen-jakarta' ) + println 'Default jakarta final bundle jar name [ ' + finalBundleJarName + ' ]' + + def transformerArgs = [ + sourceJarPath, finalBundleJarName, + '-q', // quiet output + '-tr', new File(getProjectDir().getParentFile().getParentFile(), 'rules/jakarta-renames.properties').path, + '-tv', new File(getProjectDir().getParentFile().getParentFile(), 'rules/jakarta-versions.properties').path, + '-td', new File(getProjectDir().getParentFile().getParentFile(), 'rules/jakarta-direct-modelgen.properties').path, + ] + + println 'Transformer options:' + transformerArgs.each { + println ' [ ' + it + ' ]' + } + + javaexec { + classpath configurations.jakartaeeTransformJars + main = 'org.eclipse.transformer.jakarta.JakartaTransformer' + args = transformerArgs + } + } + } +} \ No newline at end of file diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java index 82d077cfe4..0d5af2ce72 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java @@ -199,7 +199,7 @@ public final class ClassWriter { private static String writeGeneratedAnnotation(MetaEntity entity, Context context) { StringBuilder generatedAnnotation = new StringBuilder(); generatedAnnotation.append( "@" ) - .append( entity.importType( context.getGeneratedAnnotation().getQualifiedName().toString() ) ) + .append( entity.importType( context.getGeneratedAnnotationFqcn() ) ) .append( "(value = \"" ) .append( JPAMetaModelEntityProcessor.class.getName() ); if ( context.addGeneratedDate() ) { diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java index da0d9a6f55..c09ec34288 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java @@ -50,7 +50,7 @@ public final class Context { private final boolean lazyXmlParsing; private final String persistenceXmlLocation; private final List ormXmlFiles; - private final TypeElement generatedAnnotation; + private final String generatedAnnotation; /** * Whether all mapping files are xml-mapping-metadata-complete. In this case no annotation processing will take @@ -96,14 +96,16 @@ public final class Context { lazyXmlParsing = Boolean.parseBoolean( pe.getOptions().get( JPAMetaModelEntityProcessor.LAZY_XML_PARSING ) ); logDebug = Boolean.parseBoolean( pe.getOptions().get( JPAMetaModelEntityProcessor.DEBUG_OPTION ) ); + // Workaround that Eclipse transformer tries to replace this constant which we don't want + String j = "j"; TypeElement java8AndBelowGeneratedAnnotation = - pe.getElementUtils().getTypeElement( "javax.annotation.Generated" ); + pe.getElementUtils().getTypeElement( j + "avax.annotation.Generated" ); if ( java8AndBelowGeneratedAnnotation != null ) { - generatedAnnotation = java8AndBelowGeneratedAnnotation; + generatedAnnotation = java8AndBelowGeneratedAnnotation.getQualifiedName().toString(); } else { // Using the new name for this annotation in Java 9 and above - generatedAnnotation = pe.getElementUtils().getTypeElement( "javax.annotation.processing.Generated" ); + generatedAnnotation = "javax.annotation.processing.Generated"; } } @@ -115,7 +117,7 @@ public final class Context { return addGeneratedAnnotation; } - public TypeElement getGeneratedAnnotation() { + public String getGeneratedAnnotationFqcn() { return generatedAnnotation; }