Functional, not fully understood, but functional.
This commit is contained in:
parent
40f5c8b460
commit
1fa5250338
45 changed files with 4680 additions and 441 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,3 +1,5 @@
|
|||
build
|
||||
|
||||
.gradle
|
||||
gradlew*
|
||||
gradle/
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -39,6 +39,16 @@
|
|||
</option>
|
||||
</configuration>
|
||||
</facet>
|
||||
<facet type="jpa" name="JPA">
|
||||
<configuration>
|
||||
<setting name="validation-enabled" value="true" />
|
||||
<setting name="provider-name" value="" />
|
||||
<datasource-mapping>
|
||||
<factory-entry name="employee" />
|
||||
</datasource-mapping>
|
||||
<deploymentDescriptor name="persistence.xml" url="file://$MODULE_DIR$/../../src/main/resources/META-INF/persistence.xml" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
||||
<output url="file://$MODULE_DIR$/../../build/classes/main" />
|
||||
|
@ -50,8 +60,10 @@
|
|||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Gradle: javax.inject:javax.inject:1" level="project" />
|
||||
<orderEntry type="library" name="Gradle: commons-codec:commons-codec:1.10" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.google.guava:guava:21.0" level="project" />
|
||||
<orderEntry type="library" name="Gradle: joda-time:joda-time:2.9.9" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.github.rholder.fauxflake:fauxflake-core:1.1.0" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.projectlombok:lombok:1.16.16" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.postgresql:postgresql:42.0.0" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.eclipse.persistence:eclipselink:2.6.4" level="project" />
|
||||
|
|
|
@ -51,8 +51,10 @@
|
|||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="farsite_main" />
|
||||
<orderEntry type="library" name="Gradle: javax.inject:javax.inject:1" level="project" />
|
||||
<orderEntry type="library" name="Gradle: commons-codec:commons-codec:1.10" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.google.guava:guava:21.0" level="project" />
|
||||
<orderEntry type="library" name="Gradle: joda-time:joda-time:2.9.9" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.github.rholder.fauxflake:fauxflake-core:1.1.0" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.projectlombok:lombok:1.16.16" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.postgresql:postgresql:42.0.0" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.eclipse.persistence:eclipselink:2.6.4" level="project" />
|
||||
|
@ -68,6 +70,12 @@
|
|||
<orderEntry type="library" name="Gradle: org.zalando:logbook-core:1.1.1" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.github.javafaker:javafaker:0.13" level="project" />
|
||||
<orderEntry type="library" name="Gradle: junit:junit:4.12" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.mockito:mockito-all:1.10.19" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.assertj:assertj-core:2.6.0" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.github.stefanbirkner:system-rules:1.16.1" level="project" />
|
||||
<orderEntry type="library" name="Gradle: nl.jqno.equalsverifier:equalsverifier:1.7.8" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.hamcrest:hamcrest-core:1.3" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.quicktheories:quicktheories:0.13" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.eclipse.persistence:commonj.sdo:2.1.1" level="project" />
|
||||
<orderEntry type="library" name="Gradle: javax.validation:validation-api:1.1.0.Final" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.glassfish:javax.json:1.0.4" level="project" />
|
||||
|
@ -84,7 +92,6 @@
|
|||
<orderEntry type="library" name="Gradle: com.google.gag:gag:1.0.1" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.apache.commons:commons-lang3:3.5" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.github.mifmif:generex:1.0.2" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.hamcrest:hamcrest-core:1.3" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.google.protobuf:protobuf-java:2.6.1" level="project" />
|
||||
<orderEntry type="library" name="Gradle: io.netty:netty:3.6.1.Final" level="project" />
|
||||
<orderEntry type="library" name="Gradle: dk.brics.automaton:automaton:1.11-8" level="project" />
|
||||
|
|
50
NOTES
Normal file
50
NOTES
Normal file
|
@ -0,0 +1,50 @@
|
|||
http://wiki.eclipse.org/EclipseLink/Examples/JPA/Employee
|
||||
http://java-persistence-performance.blogspot.com/2013/06/cool-performance-features-of.html
|
||||
|
||||
pkill -9 crdb && rm -rf /tmp/far/* && (cd /tmp/far; crdb start --background --http-port=9090 --vmodule=executor=2; sleep 1) && echo "create database farsite;" | crdb sql && tail -f /tmp/far/cockroach-data/logs/crdb.log
|
||||
|
||||
|
||||
// jpa weaving
|
||||
def entitiesBasePackage = 'com.example.farsite.model'
|
||||
|
||||
compileJava {
|
||||
destinationDir file("$buildDir/compiled-classes")
|
||||
}
|
||||
|
||||
task copyNonPersistentClasses(type: Copy, dependsOn: compileJava) {
|
||||
from "$buildDir/compiled-classes"
|
||||
into sourceSets.main.output.classesDir
|
||||
exclude '**/' + entitiesBasePackage.replaceAll('\\.','/') + '/**'
|
||||
includeEmptyDirs = false
|
||||
}
|
||||
task copyPersistentClasses(type: Copy, dependsOn: compileJava) {
|
||||
from "$buildDir/compiled-classes"
|
||||
into "$buildDir/unwoven-persistent-classes"
|
||||
include '**/' + entitiesBasePackage.replaceAll('\\.','/') + '/**'
|
||||
includeEmptyDirs = false
|
||||
}
|
||||
task weaveJpaEntities(type: JavaExec, dependsOn: [copyPersistentClasses,processResources]) {
|
||||
main = 'org.eclipse.persistence.tools.weaving.jpa.StaticWeave'
|
||||
classpath configurations.weave.incoming.files
|
||||
args '-persistenceinfo'
|
||||
args processResources.destinationDir.absolutePath
|
||||
args '-classpath'
|
||||
args configurations.compile.incoming.files.asPath
|
||||
args '-loglevel'
|
||||
args 'INFO'
|
||||
args copyPersistentClasses.destinationDir.absolutePath
|
||||
args sourceSets.main.output.classesDir.absolutePath
|
||||
|
||||
inputs.files fileTree(copyPersistentClasses.destinationDir),fileTree(processResources.destinationDir).matching({pattern -> pattern.include('**/META-INF/persistence.xml')})
|
||||
outputs.dir sourceSets.main.output.classesDir
|
||||
}
|
||||
//classes.dependsOn copyNonPersistentClasses,weaveJpaEntities
|
||||
|
||||
dependencies
|
||||
weave group: 'org.eclipse.persistence', name: 'javax.persistence', version: '2.+'
|
||||
weave group: 'org.eclipse.persistence', name: 'org.eclipse.persistence.jpa', version: '2.+'
|
||||
|
||||
configurations
|
||||
weave
|
||||
|
||||
mainClassName = "com.example.farsite.Main"
|
46
build.gradle
46
build.gradle
|
@ -24,20 +24,19 @@ apply plugin: 'com.uber.okbuck'
|
|||
apply plugin: 'nebula.dependency-lock'
|
||||
apply plugin: 'application'
|
||||
|
||||
mainClassName = "com.example.farsite.Main"
|
||||
applicationDefaultJvmArgs = ["-Dgreeting.language=en"]
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
gradleVersion = '2.2'
|
||||
}
|
||||
|
||||
task execute(type:JavaExec) {
|
||||
classpath = sourceSets.main.runtimeClasspath
|
||||
main = project.hasProperty("mainClass") ? project.getProperty("mainClass") : "com.example.farsite.Main"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile 'junit:junit:4.12'
|
||||
main = project.hasProperty("mainClass") ? project.getProperty("mainClass") : "com.example.farsite.test.Main"
|
||||
}
|
||||
|
||||
jar {
|
||||
baseName = ''
|
||||
baseName = 'farsite'
|
||||
version = '0.0.1-SNAPSHOT'
|
||||
}
|
||||
|
||||
|
@ -65,12 +64,18 @@ dependencies {
|
|||
// Some Java Extras
|
||||
compile group: 'javax.inject', name: 'javax.inject', version: '1'
|
||||
|
||||
// Apache Commons
|
||||
compile group: 'commons-codec', name: 'commons-codec', version: '1.+'
|
||||
|
||||
// Google Guava, "For all the Goodness(TM)"
|
||||
compile group: 'com.google.guava', name: 'guava', version: '21.+'
|
||||
|
||||
// Joda Time, "Because time is hard(TM)"
|
||||
compile group: 'joda-time', name: 'joda-time', version: '2.+'
|
||||
|
||||
// Flake ID generation
|
||||
compile group: 'com.github.rholder.fauxflake', name: 'fauxflake-core', version: '1.+'
|
||||
|
||||
// Lombok, "Where less is more(TM)"
|
||||
compile group: 'org.projectlombok', name: 'lombok', version: '1.+'
|
||||
|
||||
|
@ -83,7 +88,6 @@ dependencies {
|
|||
compile group: 'org.eclipse.persistence', name: 'javax.persistence', version: '2.+'
|
||||
compile group: 'org.eclipse.persistence', name: 'org.eclipse.persistence.jpa', version: '2.+'
|
||||
|
||||
|
||||
// Dropwizard (aka. CodaHale) Metrics, "Measure all the things!(TM)"
|
||||
compile group: 'io.dropwizard.metrics', name: 'metrics-core', version: '3.+'
|
||||
compile group: 'io.dropwizard.metrics', name: 'metrics-jvm', version: '3.+'
|
||||
|
@ -96,11 +100,31 @@ dependencies {
|
|||
compile group: 'org.slf4j', name: 'log4j-over-slf4j', version: '1.+'
|
||||
compile group: 'org.zalando', name: 'logbook-core', version: '1.+'
|
||||
|
||||
// Fake data generator
|
||||
compile group: 'com.github.javafaker', name: 'javafaker', version: '0.+'
|
||||
|
||||
// Testing
|
||||
testCompile group: 'junit', name: 'junit', version: '4.+'
|
||||
testCompile group: 'org.mockito', name: 'mockito-all', version: '1.+'
|
||||
testCompile group: 'org.assertj', name: 'assertj-core', version: '2.+'
|
||||
testCompile group: 'com.github.stefanbirkner', name: 'system-rules', version: '1.+'
|
||||
testCompile group: 'nl.jqno.equalsverifier', name: 'equalsverifier', version: '1.+'
|
||||
testCompile group: 'org.hamcrest', name: 'hamcrest-core', version: '1.3'
|
||||
testCompile group: 'org.quicktheories', name: 'quicktheories', version: '0.+'
|
||||
}
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
gradleVersion = '2.2'
|
||||
task performJPAWeaving(type: JavaExec, dependsOn: "compileJava"){
|
||||
inputs.dir compileJava.destinationDir
|
||||
outputs.dir compileJava.destinationDir
|
||||
main "org.eclipse.persistence.tools.weaving.jpa.StaticWeave"
|
||||
args "-persistenceinfo",
|
||||
"src/main/resources",
|
||||
compileJava.destinationDir.getAbsolutePath(),
|
||||
compileJava.destinationDir.getAbsolutePath()
|
||||
classpath = configurations.compile
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile){
|
||||
doLast{
|
||||
tasks.performJPAWeaving.execute()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,10 @@
|
|||
"locked": "21.0",
|
||||
"requested": "21.+"
|
||||
},
|
||||
"commons-codec:commons-codec": {
|
||||
"locked": "1.10",
|
||||
"requested": "1.+"
|
||||
},
|
||||
"io.dropwizard.metrics:metrics-core": {
|
||||
"locked": "3.2.2",
|
||||
"requested": "3.+"
|
||||
|
@ -82,6 +86,10 @@
|
|||
"locked": "21.0",
|
||||
"requested": "21.+"
|
||||
},
|
||||
"commons-codec:commons-codec": {
|
||||
"locked": "1.10",
|
||||
"requested": "1.+"
|
||||
},
|
||||
"io.dropwizard.metrics:metrics-core": {
|
||||
"locked": "3.2.2",
|
||||
"requested": "3.+"
|
||||
|
@ -152,6 +160,10 @@
|
|||
"locked": "21.0",
|
||||
"requested": "21.+"
|
||||
},
|
||||
"commons-codec:commons-codec": {
|
||||
"locked": "1.10",
|
||||
"requested": "1.+"
|
||||
},
|
||||
"io.dropwizard.metrics:metrics-core": {
|
||||
"locked": "3.2.2",
|
||||
"requested": "3.+"
|
||||
|
@ -218,10 +230,18 @@
|
|||
"locked": "0.13",
|
||||
"requested": "0.+"
|
||||
},
|
||||
"com.github.stefanbirkner:system-rules": {
|
||||
"locked": "1.16.1",
|
||||
"requested": "1.+"
|
||||
},
|
||||
"com.google.guava:guava": {
|
||||
"locked": "21.0",
|
||||
"requested": "21.+"
|
||||
},
|
||||
"commons-codec:commons-codec": {
|
||||
"locked": "1.10",
|
||||
"requested": "1.+"
|
||||
},
|
||||
"io.dropwizard.metrics:metrics-core": {
|
||||
"locked": "3.2.2",
|
||||
"requested": "3.+"
|
||||
|
@ -252,7 +272,15 @@
|
|||
},
|
||||
"junit:junit": {
|
||||
"locked": "4.12",
|
||||
"requested": "4.12"
|
||||
"requested": "4.+"
|
||||
},
|
||||
"nl.jqno.equalsverifier:equalsverifier": {
|
||||
"locked": "1.7.8",
|
||||
"requested": "1.+"
|
||||
},
|
||||
"org.assertj:assertj-core": {
|
||||
"locked": "2.6.0",
|
||||
"requested": "2.+"
|
||||
},
|
||||
"org.eclipse.persistence:eclipselink": {
|
||||
"locked": "2.6.4",
|
||||
|
@ -266,6 +294,14 @@
|
|||
"locked": "2.6.4",
|
||||
"requested": "2.+"
|
||||
},
|
||||
"org.hamcrest:hamcrest-core": {
|
||||
"locked": "1.3",
|
||||
"requested": "1.3"
|
||||
},
|
||||
"org.mockito:mockito-all": {
|
||||
"locked": "1.10.19",
|
||||
"requested": "1.+"
|
||||
},
|
||||
"org.postgresql:postgresql": {
|
||||
"locked": "42.0.0",
|
||||
"requested": "42.+"
|
||||
|
@ -274,6 +310,10 @@
|
|||
"locked": "1.16.16",
|
||||
"requested": "1.+"
|
||||
},
|
||||
"org.quicktheories:quicktheories": {
|
||||
"locked": "0.13",
|
||||
"requested": "0.+"
|
||||
},
|
||||
"org.slf4j:log4j-over-slf4j": {
|
||||
"locked": "1.7.25",
|
||||
"requested": "1.+"
|
||||
|
@ -292,10 +332,18 @@
|
|||
"locked": "0.13",
|
||||
"requested": "0.+"
|
||||
},
|
||||
"com.github.stefanbirkner:system-rules": {
|
||||
"locked": "1.16.1",
|
||||
"requested": "1.+"
|
||||
},
|
||||
"com.google.guava:guava": {
|
||||
"locked": "21.0",
|
||||
"requested": "21.+"
|
||||
},
|
||||
"commons-codec:commons-codec": {
|
||||
"locked": "1.10",
|
||||
"requested": "1.+"
|
||||
},
|
||||
"io.dropwizard.metrics:metrics-core": {
|
||||
"locked": "3.2.2",
|
||||
"requested": "3.+"
|
||||
|
@ -326,7 +374,15 @@
|
|||
},
|
||||
"junit:junit": {
|
||||
"locked": "4.12",
|
||||
"requested": "4.12"
|
||||
"requested": "4.+"
|
||||
},
|
||||
"nl.jqno.equalsverifier:equalsverifier": {
|
||||
"locked": "1.7.8",
|
||||
"requested": "1.+"
|
||||
},
|
||||
"org.assertj:assertj-core": {
|
||||
"locked": "2.6.0",
|
||||
"requested": "2.+"
|
||||
},
|
||||
"org.eclipse.persistence:eclipselink": {
|
||||
"locked": "2.6.4",
|
||||
|
@ -340,6 +396,14 @@
|
|||
"locked": "2.6.4",
|
||||
"requested": "2.+"
|
||||
},
|
||||
"org.hamcrest:hamcrest-core": {
|
||||
"locked": "1.3",
|
||||
"requested": "1.3"
|
||||
},
|
||||
"org.mockito:mockito-all": {
|
||||
"locked": "1.10.19",
|
||||
"requested": "1.+"
|
||||
},
|
||||
"org.postgresql:postgresql": {
|
||||
"locked": "42.0.0",
|
||||
"requested": "42.+"
|
||||
|
@ -348,6 +412,10 @@
|
|||
"locked": "1.16.16",
|
||||
"requested": "1.+"
|
||||
},
|
||||
"org.quicktheories:quicktheories": {
|
||||
"locked": "0.13",
|
||||
"requested": "0.+"
|
||||
},
|
||||
"org.slf4j:log4j-over-slf4j": {
|
||||
"locked": "1.7.25",
|
||||
"requested": "1.+"
|
||||
|
|
184
farsite.ipr
184
farsite.ipr
|
@ -71,6 +71,127 @@
|
|||
<option name="languageVersion" value="1.1" />
|
||||
<option name="apiVersion" value="1.1" />
|
||||
</component>
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/farsite.iml" filepath="$PROJECT_DIR$/farsite.iml" />
|
||||
|
@ -133,6 +254,24 @@
|
|||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.mifmif/generex/1.0.2/d1f52c4efe0b20154faf35f8df5c08a234dc41db/generex-1.0.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.github.rholder.fauxflake:fauxflake-core:1.1.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.rholder.fauxflake/fauxflake-core/1.1.0/79755968bfe210f7e35f3193038dc30767e1c7b/fauxflake-core-1.1.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.rholder.fauxflake/fauxflake-core/1.1.0/b7ac69d18566c495cb4737ab600051e715406c18/fauxflake-core-1.1.0-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.github.stefanbirkner:system-rules:1.16.1">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.stefanbirkner/system-rules/1.16.1/cb9e42b003d0668f6445505c0f81dd9a244a05d5/system-rules-1.16.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.stefanbirkner/system-rules/1.16.1/ed9fd29e5a3e83887038d5fc4cf0cc931a1a4eff/system-rules-1.16.1-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: com.github.stephenc.jcip:jcip-annotations:1.0-1">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.stephenc.jcip/jcip-annotations/1.0-1/ef31541dd28ae2cefdd17c7ebf352d93e9058c63/jcip-annotations-1.0-1.jar!/" />
|
||||
|
@ -178,6 +317,15 @@
|
|||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.protobuf/protobuf-java/2.6.1/cf47bfc6a10f85d14bc4c078a48d163b5903a291/protobuf-java-2.6.1-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: commons-codec:commons-codec:1.10">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-codec/commons-codec/1.10/4b95f4897fa13f2cd904aee711aeafc0c5295cd8/commons-codec-1.10.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-codec/commons-codec/1.10/11fb3d88ae7e3b757d70237064210ceb954a5a04/commons-codec-1.10-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: dk.brics.automaton:automaton:1.11-8">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/dk.brics.automaton/automaton/1.11-8/6ebfa65eb431ff4b715a23be7a750cbc4cc96d0f/automaton-1.11-8.jar!/" />
|
||||
|
@ -286,6 +434,15 @@
|
|||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/junit/junit/4.12/a6c32b40bf3d76eca54e3c601e5d1470c86fcdfa/junit-4.12-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: nl.jqno.equalsverifier:equalsverifier:1.7.8">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/nl.jqno.equalsverifier/equalsverifier/1.7.8/a5dd63f30427b8ff868efa6e7d54f3c9fe365144/equalsverifier-1.7.8.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/nl.jqno.equalsverifier/equalsverifier/1.7.8/9aa3ffb236b046aa40102e487fca9e0acdc2d880/equalsverifier-1.7.8-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.apache.commons:commons-lang3:3.5">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-lang3/3.5/6c6c702c89bfff3cd9e80b04d668c5e190d588c6/commons-lang3-3.5.jar!/" />
|
||||
|
@ -295,6 +452,15 @@
|
|||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-lang3/3.5/f7d878153e86a1cdddf6b37850e00a9f8bff726f/commons-lang3-3.5-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.assertj:assertj-core:2.6.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.assertj/assertj-core/2.6.0/b532c3fc4f66bcfee4989a3514f1cd56203a33ad/assertj-core-2.6.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.assertj/assertj-core/2.6.0/86e8fd98e5ec52e93e3fa46d9bf5df7cca6d1bce/assertj-core-2.6.0-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.eclipse.persistence:commonj.sdo:2.1.1">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.eclipse.persistence/commonj.sdo/2.1.1/90d4c89ce0a69f58619f1a247bbf420122139ff5/commonj.sdo-2.1.1.jar!/" />
|
||||
|
@ -385,6 +551,15 @@
|
|||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-core/1.3/1dc37250fbc78e23a65a67fbbaf71d2e9cbc3c0b/hamcrest-core-1.3-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.mockito:mockito-all:1.10.19">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.mockito/mockito-all/1.10.19/539df70269cc254a58cccc5d8e43286b4a73bf30/mockito-all-1.10.19.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.mockito/mockito-all/1.10.19/8269667b73d9616600359a9b0ba1b1c7d0cf7a97/mockito-all-1.10.19-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.postgresql:postgresql:42.0.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.postgresql/postgresql/42.0.0/938ede0cdf862cc4eaba5023a86254783af1d261/postgresql-42.0.0.jar!/" />
|
||||
|
@ -403,6 +578,15 @@
|
|||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.projectlombok/lombok/1.16.16/c4b112e9645070ac05946084317cc5d01cf4ddcd/lombok-1.16.16-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.quicktheories:quicktheories:0.13">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.quicktheories/quicktheories/0.13/311a7ac8e80b4a4ec6dc0d9af81204713b54f180/quicktheories-0.13.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.quicktheories/quicktheories/0.13/37283aaf93ae4b34a16d6647dcf4b314da922196/quicktheories-0.13-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Gradle: org.slf4j:log4j-over-slf4j:1.7.25">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.slf4j/log4j-over-slf4j/1.7.25/a87bb47468f47ee7aabbd54f93e133d4215769c3/log4j-over-slf4j-1.7.25.jar!/" />
|
||||
|
|
1649
farsite.iws
1649
farsite.iws
File diff suppressed because it is too large
Load diff
|
@ -1,47 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
|
||||
<!-- https://jcp.org/aboutJava/communityprocess/final/jsr338/index.html -->
|
||||
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
|
||||
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
|
||||
version="2.1">
|
||||
|
||||
<persistence-unit name="people" transaction-type="JTA">
|
||||
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
|
||||
|
||||
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
||||
<properties>
|
||||
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
|
||||
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://127.0.0.1:26257/farsite?sslmode=disable" />
|
||||
<property name="javax.persistence.jdbc.user" value="root" />
|
||||
<property name="javax.persistence.jdbc.password" value="" />
|
||||
|
||||
<!-- EclipseLink should create the database schema automatically -->
|
||||
<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
|
||||
<property name="eclipselink.ddl-generation.output-mode" value="database" />
|
||||
|
||||
<property name="eclipselink.target-database" value="PostgreSQL"/>
|
||||
<property name="eclipselink.logging.level" value="FINE"/>
|
||||
<property name="eclipselink.logging.logger" value="JavaLogger"/>
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
|
||||
<persistence-unit name="todos" transaction-type="RESOURCE_LOCAL">
|
||||
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
|
||||
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
||||
<properties>
|
||||
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
|
||||
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://127.0.0.1:26257/farsite?sslmode=disable" />
|
||||
<property name="javax.persistence.jdbc.user" value="root" />
|
||||
<property name="javax.persistence.jdbc.password" value="" />
|
||||
|
||||
<!-- EclipseLink should create the database schema automatically -->
|
||||
<property name="eclipselink.ddl-generation" value="create-tables" />
|
||||
<property name="eclipselink.ddl-generation.output-mode" value="database" />
|
||||
|
||||
<property name="eclipselink.logging.level" value="FINE"/>
|
||||
<property name="eclipselink.logging.logger" value="JavaLogger"/>
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</persistence>
|
|
@ -1,36 +0,0 @@
|
|||
package com.example.farsite;
|
||||
|
||||
import com.example.farsite.model.Todo;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.Persistence;
|
||||
import javax.persistence.Query;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
private static final String PERSISTENCE_UNIT_NAME = "todos";
|
||||
private static EntityManagerFactory factory;
|
||||
|
||||
public static void main(String[] args) {
|
||||
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
|
||||
EntityManager em = factory.createEntityManager();
|
||||
// read the existing entries and write to console
|
||||
Query q = em.createQuery("select t from Todo t");
|
||||
List<Todo> todoList = q.getResultList();
|
||||
for (Todo todo : todoList) {
|
||||
System.out.println(todo);
|
||||
}
|
||||
System.out.println("Size: " + todoList.size());
|
||||
|
||||
// create new todo
|
||||
em.getTransaction().begin();
|
||||
Todo todo = new Todo();
|
||||
todo.setSummary("This is a test");
|
||||
todo.setDescription("This is a test");
|
||||
em.persist(todo);
|
||||
em.getTransaction().commit();
|
||||
|
||||
em.close();
|
||||
}
|
||||
}
|
24
src/main/java/com/example/farsite/model/AbstractModel.java
Normal file
24
src/main/java/com/example/farsite/model/AbstractModel.java
Normal file
|
@ -0,0 +1,24 @@
|
|||
package com.example.farsite.model;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
//import org.springframework.data.annotation.CreatedDate;
|
||||
//import org.springframework.data.annotation.LastModifiedDate;
|
||||
//import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
import com.example.farsite.util.SerialVersionUID;
|
||||
//import org.eclipse.persistence.descriptors.changetracking.ChangeTracker;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@EqualsAndHashCode
|
||||
@MappedSuperclass
|
||||
//EntityListeners(AuditingEntityListener.class)
|
||||
public abstract class AbstractModel <T extends Serializable> implements Model<T> { //, ChangeTracker {
|
||||
private static final long serialVersionUID = SerialVersionUID.compute(AbstractModel.class);
|
||||
|
||||
//@Getter @CreatedDate Date createdDate;
|
||||
//@Getter @LastModifiedDate Date modifiedDate;
|
||||
}
|
49
src/main/java/com/example/farsite/model/Address.java
Normal file
49
src/main/java/com/example/farsite/model/Address.java
Normal file
|
@ -0,0 +1,49 @@
|
|||
package com.example.farsite.model;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
import com.example.farsite.util.SerialVersionUID;
|
||||
import lombok.Data;
|
||||
import org.eclipse.persistence.annotations.Cache;
|
||||
import org.eclipse.persistence.annotations.ReturnInsert;
|
||||
|
||||
import static javax.persistence.FetchType.LAZY;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Cache(
|
||||
refreshOnlyIfNewer = true
|
||||
)
|
||||
public class Address extends AbstractModel<Long> {
|
||||
private static final long serialVersionUID = SerialVersionUID.compute(Address.class);
|
||||
|
||||
// PRIMARY KEY
|
||||
// @Id @GeneratedValue(strategy=GenerationType.IDENTITY) //@ReturnInsert(returnOnly=true)
|
||||
// @Column(unique=true, nullable=false)
|
||||
@Id @GeneratedValue(generator = "flake-seq")
|
||||
@Column(unique = true, nullable = false)
|
||||
private Long id;
|
||||
|
||||
// FIELDS
|
||||
private String city;
|
||||
private String country;
|
||||
@Basic(fetch=LAZY)
|
||||
private String province;
|
||||
private String postalCode;
|
||||
private String street;
|
||||
|
||||
// OPTIMISTIC CONCURRENCY CONTROL
|
||||
@Version
|
||||
private long version;
|
||||
|
||||
public Address() {
|
||||
}
|
||||
|
||||
public Address(String city, String country, String province, String postalCode, String street) {
|
||||
this.city = city;
|
||||
this.country = country;
|
||||
this.province = province;
|
||||
this.postalCode = postalCode;
|
||||
this.street = street;
|
||||
}
|
||||
}
|
127
src/main/java/com/example/farsite/model/Employee.java
Normal file
127
src/main/java/com/example/farsite/model/Employee.java
Normal file
|
@ -0,0 +1,127 @@
|
|||
package com.example.farsite.model;
|
||||
|
||||
import com.example.farsite.util.SerialVersionUID;
|
||||
import lombok.Data;
|
||||
import org.eclipse.persistence.annotations.Cache;
|
||||
import org.eclipse.persistence.annotations.CacheType;
|
||||
import org.eclipse.persistence.annotations.ChangeTracking;
|
||||
import org.eclipse.persistence.annotations.PrivateOwned;
|
||||
import org.eclipse.persistence.config.HintValues;
|
||||
import org.eclipse.persistence.config.QueryHints;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.eclipse.persistence.annotations.CacheCoordinationType.INVALIDATE_CHANGED_OBJECTS;
|
||||
import static org.eclipse.persistence.annotations.ChangeTrackingType.OBJECT;
|
||||
import static org.eclipse.persistence.config.CacheIsolationType.SHARED;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@SecondaryTable(name = "SALARY")
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = "Employee.findAll", query = "SELECT e FROM Employee e ORDER BY e.id"),
|
||||
@NamedQuery(name = "Employee.findByName", query = "SELECT e FROM Employee e WHERE e.firstName LIKE :firstName AND e.lastName LIKE :lastName"),
|
||||
@NamedQuery(name = "Employee.count", query = "SELECT COUNT(e) FROM Employee e"),
|
||||
@NamedQuery(name = "Employee.countByName", query = "SELECT COUNT(e) FROM Employee e WHERE e.firstName LIKE :firstName AND e.lastName LIKE :lastName"),
|
||||
// Query used in {@link IdInPaging}
|
||||
@NamedQuery(name = "Employee.idsIn", query = "SELECT e FROM Employee e WHERE e.id IN :IDS ORDER BY e.id",
|
||||
hints = { @QueryHint(name = QueryHints.QUERY_RESULTS_CACHE, value = HintValues.TRUE) }) })
|
||||
@Cache (type= CacheType.WEAK
|
||||
,isolation=SHARED
|
||||
,expiry=600000
|
||||
,alwaysRefresh=true
|
||||
,disableHits=true
|
||||
,coordinationType=INVALIDATE_CHANGED_OBJECTS
|
||||
)
|
||||
//@ChangeTracking(OBJECT)
|
||||
public class Employee extends AbstractModel<Long> {
|
||||
private static final long serialVersionUID = SerialVersionUID.compute(AbstractModel.class);
|
||||
|
||||
// PRIMARY KEY
|
||||
@Id @GeneratedValue(generator = "flake-seq")
|
||||
@Column(unique = true, nullable = false)
|
||||
private Long id;
|
||||
|
||||
// FIELDS
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
|
||||
/* NOTE:
|
||||
* Gender mapped using Basic with an ObjectTypeConverter to map between
|
||||
* single char code value in database to enum. JPA only supports mapping to
|
||||
* the full name of the enum or its ordinal value. */
|
||||
@Basic @Column(name = "GENDER") @Convert(converter = GenderConverter.class)
|
||||
private Gender gender = Gender.Male;
|
||||
|
||||
@Column(table = "SALARY")
|
||||
private double salary;
|
||||
|
||||
// OPTIMISTIC CONCURRENCY CONTROL
|
||||
@Version
|
||||
private Long version;
|
||||
|
||||
// RELATIONS
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "MANAGER_ID")
|
||||
private Employee manager;
|
||||
|
||||
@OneToMany(mappedBy = "manager")
|
||||
private List<Employee> managedEmployees = new ArrayList<Employee>();
|
||||
|
||||
@OneToMany(mappedBy = "owner", cascade = CascadeType.ALL, orphanRemoval = true)
|
||||
@PrivateOwned
|
||||
private List<PhoneNumber> phoneNumbers = new ArrayList<PhoneNumber>();
|
||||
|
||||
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
|
||||
@JoinColumn(name = "ADDRESS_ID")
|
||||
private Address address;
|
||||
|
||||
@Embedded
|
||||
@AttributeOverrides({ @AttributeOverride(name = "startDate", column = @Column(name = "START_DATE")),
|
||||
@AttributeOverride(name = "endDate", column = @Column(name = "END_DATE")) })
|
||||
private EmploymentPeriod period;
|
||||
|
||||
@ElementCollection
|
||||
@CollectionTable(name = "RESPONS")
|
||||
private List<String> responsibilities = new ArrayList<String>();
|
||||
|
||||
public Employee addManagedEmployee(Employee employee) {
|
||||
getManagedEmployees().add(employee);
|
||||
employee.setManager(this);
|
||||
return employee;
|
||||
}
|
||||
|
||||
public Employee removeManagedEmployee(Employee employee) {
|
||||
getManagedEmployees().remove(employee);
|
||||
employee.setManager(null);
|
||||
return employee;
|
||||
}
|
||||
|
||||
public PhoneNumber addPhoneNumber(PhoneNumber phoneNumber) {
|
||||
getPhoneNumbers().add(phoneNumber);
|
||||
phoneNumber.setOwner(this);
|
||||
return phoneNumber;
|
||||
}
|
||||
|
||||
public PhoneNumber addPhoneNumber(String type, String number) {
|
||||
PhoneNumber phoneNumber = new PhoneNumber(type, number);
|
||||
return addPhoneNumber(phoneNumber);
|
||||
}
|
||||
|
||||
public PhoneNumber removePhoneNumber(PhoneNumber phoneNumber) {
|
||||
getPhoneNumbers().remove(phoneNumber);
|
||||
phoneNumber.setOwner(null);
|
||||
return phoneNumber;
|
||||
}
|
||||
|
||||
public void addResponsibility(String responsibility) {
|
||||
getResponsibilities().add(responsibility);
|
||||
}
|
||||
|
||||
public void removeResponsibility(String responsibility) {
|
||||
getResponsibilities().remove(responsibility);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package com.example.farsite.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import static javax.persistence.TemporalType.DATE;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Temporal;
|
||||
|
||||
/**
|
||||
* Represents the period of time an employee has worked for the company. A null
|
||||
* endDate indicates that the employee is current.
|
||||
*/
|
||||
@Data
|
||||
@Embeddable
|
||||
public class EmploymentPeriod {
|
||||
|
||||
@Temporal(DATE)
|
||||
private Calendar startDate;
|
||||
@Temporal(DATE)
|
||||
private Calendar endDate;
|
||||
|
||||
public void setStartDate(int year, int month, int date) {
|
||||
if (this.startDate == null) {
|
||||
setStartDate(Calendar.getInstance());
|
||||
}
|
||||
getStartDate().set(year, month, date);
|
||||
}
|
||||
|
||||
public void setEndDate(int year, int month, int date) {
|
||||
if (this.endDate == null) {
|
||||
setEndDate(Calendar.getInstance());
|
||||
}
|
||||
getEndDate().set(year, month, date);
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
package com.example.farsite.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
public class Family {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.TABLE)
|
||||
private int id;
|
||||
private String description;
|
||||
|
||||
@OneToMany(mappedBy = "family")
|
||||
private final List<Person> members = new ArrayList<Person>();
|
||||
}
|
5
src/main/java/com/example/farsite/model/Gender.java
Normal file
5
src/main/java/com/example/farsite/model/Gender.java
Normal file
|
@ -0,0 +1,5 @@
|
|||
package com.example.farsite.model;
|
||||
|
||||
public enum Gender {
|
||||
Female, Male, ;
|
||||
}
|
36
src/main/java/com/example/farsite/model/GenderConverter.java
Normal file
36
src/main/java/com/example/farsite/model/GenderConverter.java
Normal file
|
@ -0,0 +1,36 @@
|
|||
package com.example.farsite.model;
|
||||
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.Converter;
|
||||
|
||||
@Converter(autoApply = true)
|
||||
public class GenderConverter implements AttributeConverter<Gender, String> {
|
||||
|
||||
@Override
|
||||
public String convertToDatabaseColumn(Gender gender) {
|
||||
switch (gender) {
|
||||
case Male:
|
||||
return "M";
|
||||
|
||||
case Female:
|
||||
return "F";
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid gender: " + gender);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Gender convertToEntityAttribute(String gender) {
|
||||
switch (gender) {
|
||||
case "M":
|
||||
return Gender.Male;
|
||||
|
||||
case "F":
|
||||
return Gender.Female;
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid gender code: " + gender);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
package com.example.farsite.model;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class Job {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.TABLE)
|
||||
private int id;
|
||||
private double salery;
|
||||
private String jobDescr;
|
||||
}
|
9
src/main/java/com/example/farsite/model/Model.java
Normal file
9
src/main/java/com/example/farsite/model/Model.java
Normal file
|
@ -0,0 +1,9 @@
|
|||
package com.example.farsite.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
public interface Model<T extends Serializable> {
|
||||
//Date getCreatedDate();
|
||||
//Date getModifiedDate();
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
package com.example.farsite.model;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
public class Person {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.TABLE)
|
||||
private String id;
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
|
||||
@ManyToOne
|
||||
private Family family;
|
||||
|
||||
@Transient
|
||||
private String nonsenseField = "";
|
||||
|
||||
@OneToMany
|
||||
private List<Job> jobList = new ArrayList<Job>();
|
||||
}
|
59
src/main/java/com/example/farsite/model/PhoneNumber.java
Normal file
59
src/main/java/com/example/farsite/model/PhoneNumber.java
Normal file
|
@ -0,0 +1,59 @@
|
|||
package com.example.farsite.model;
|
||||
|
||||
import com.example.farsite.util.SerialVersionUID;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Data @ToString(exclude="owner") @EqualsAndHashCode(exclude="owner")
|
||||
@Entity
|
||||
@Table(name = "PHONE")
|
||||
@IdClass(PhoneNumber.ID.class)
|
||||
public class PhoneNumber extends AbstractModel<Long> {
|
||||
private static final long serialVersionUID = SerialVersionUID.compute(PhoneNumber.class);
|
||||
|
||||
@Id @Column(name = "EMP_ID", updatable = false, insertable = false)
|
||||
private Long id;
|
||||
@Id @Column(updatable = false)
|
||||
private String type;
|
||||
|
||||
private String number;
|
||||
|
||||
@ManyToOne @JoinColumn(name = "EMP_ID")
|
||||
private Employee owner;
|
||||
|
||||
public PhoneNumber() {
|
||||
}
|
||||
|
||||
public PhoneNumber(String type, String number) {
|
||||
this();
|
||||
setType(type);
|
||||
setNumber(number);
|
||||
}
|
||||
|
||||
protected void setOwner(Employee employee) {
|
||||
this.owner = employee;
|
||||
if (employee != null) {
|
||||
this.id = employee.getId();
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class ID implements Serializable {
|
||||
private static final long serialVersionUID = SerialVersionUID.compute(PhoneNumber.ID.class);
|
||||
|
||||
public Long id;
|
||||
public String type;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package com.example.farsite.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
public class Todo {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
private String summary;
|
||||
private String description;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package com.example.farsite.util;
|
||||
|
||||
import org.eclipse.persistence.platform.database.PostgreSQLPlatform;
|
||||
import org.eclipse.persistence.queries.ValueReadQuery;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
|
||||
public class CockroachDBPlatform extends PostgreSQLPlatform {
|
||||
|
||||
public CockroachDBPlatform() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsIdentity() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsSequenceObjects()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBuildCallWithReturning()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean shouldPrintAliasForUpdate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isCockroachDB() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.example.farsite.util;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.eclipse.persistence.config.SessionCustomizer;
|
||||
import org.eclipse.persistence.internal.sessions.AbstractSession;
|
||||
import org.eclipse.persistence.sessions.Session;
|
||||
import org.eclipse.persistence.tools.profiler.PerformanceProfiler;
|
||||
|
||||
public class CrDBSessionCustomizer implements SessionCustomizer {
|
||||
|
||||
public void customize(Session session) throws Exception {
|
||||
|
||||
// Enable concurrent processing of result sets and concurrent loading of load groups.
|
||||
((AbstractSession)session).setIsConcurrent(true);
|
||||
|
||||
// Add sequence generators.
|
||||
Lists.newArrayList(
|
||||
new UUIDSequence("uuid-seq"),
|
||||
new PSRNSequence("psrn-seq"),
|
||||
new FlakeSequence("flake-seq"))
|
||||
.forEach(sequence -> {session.getLogin().addSequence(sequence);});
|
||||
}
|
||||
|
||||
}
|
74
src/main/java/com/example/farsite/util/FlakeSequence.java
Normal file
74
src/main/java/com/example/farsite/util/FlakeSequence.java
Normal file
|
@ -0,0 +1,74 @@
|
|||
package com.example.farsite.util;
|
||||
|
||||
import com.github.rholder.fauxflake.DefaultIdGenerator;
|
||||
import com.github.rholder.fauxflake.api.IdGenerator;
|
||||
import com.github.rholder.fauxflake.provider.SystemTimeProvider;
|
||||
import com.github.rholder.fauxflake.provider.twitter.SnowflakeEncodingProvider;
|
||||
import org.eclipse.persistence.internal.databaseaccess.Accessor;
|
||||
import org.eclipse.persistence.internal.sessions.AbstractSession;
|
||||
import org.eclipse.persistence.sequencing.Sequence;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* FlakeSequence is a decentralized, k-ordered unique ID generator that produces 64bit integers (Long).
|
||||
*
|
||||
* This is configured to mimic Twitter's Snowflake pattern.
|
||||
*/
|
||||
|
||||
public class FlakeSequence extends Sequence {
|
||||
IdGenerator idGenerator;
|
||||
|
||||
public FlakeSequence(String name) {
|
||||
super(name);
|
||||
long mid = Randomness.randomIntSecure(1024); // TODO(gburd): use a hash of the hostname?
|
||||
idGenerator = new DefaultIdGenerator(new SystemTimeProvider(), new SnowflakeEncodingProvider(mid));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getGeneratedValue(Accessor accessor, AbstractSession writeSession, String seqName) {
|
||||
while (true) {
|
||||
try {
|
||||
return idGenerator.generateId(10).asLong();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
// We waited more than 10ms to generate an Id, try again. This could be due to NTP
|
||||
// drift, leap seconds, GC pause, who knows.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector getGeneratedVector(Accessor accessor, AbstractSession writeSession, String seqName, int size) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnect() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnect() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldAcquireValueAfterInsert() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldAlwaysOverrideExistingValue(String seqName, Object existingValue) {
|
||||
return ((String) existingValue).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldUseTransaction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldUsePreallocation() {
|
||||
// NOTE: never pre-allocate, that would defeat the time-ordered nature of these IDs
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package com.example.farsite.util;
|
||||
|
||||
import org.eclipse.persistence.internal.databaseaccess.Accessor;
|
||||
import org.eclipse.persistence.internal.queries.DatabaseQueryMechanism;
|
||||
import org.eclipse.persistence.queries.Call;
|
||||
import org.eclipse.persistence.queries.DatabaseQuery;
|
||||
|
||||
public class GeneratedIdentityValue implements Call {
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Return the appropriate mechanism,
|
||||
* with the call set as necessary.
|
||||
*
|
||||
* @param query
|
||||
*/
|
||||
@Override public DatabaseQueryMechanism buildNewQueryMechanism(DatabaseQuery query) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Return the appropriate mechanism,
|
||||
* with the call added as necessary.
|
||||
*
|
||||
* @param query
|
||||
* @param mechanism
|
||||
*/
|
||||
@Override public DatabaseQueryMechanism buildQueryMechanism(DatabaseQuery query, DatabaseQueryMechanism mechanism) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Return a clone of the call.
|
||||
*/
|
||||
@Override public Object clone() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Return a string appropriate for the session log.
|
||||
*
|
||||
* @param accessor
|
||||
*/
|
||||
@Override public String getLogString(Accessor accessor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Return whether the call is finished returning
|
||||
* all of its results (e.g. a call that returns a cursor
|
||||
* will answer false).
|
||||
*/
|
||||
@Override public boolean isFinished() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The return type is one of, NoReturn, ReturnOneRow or ReturnManyRows.
|
||||
*/
|
||||
@Override public boolean isNothingReturned() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The return type is one of, NoReturn, ReturnOneRow or ReturnManyRows.
|
||||
*/
|
||||
@Override public boolean isOneRowReturned() {
|
||||
return false;
|
||||
}
|
||||
}
|
1439
src/main/java/com/example/farsite/util/MersenneTwisterFast.java
Normal file
1439
src/main/java/com/example/farsite/util/MersenneTwisterFast.java
Normal file
File diff suppressed because it is too large
Load diff
50
src/main/java/com/example/farsite/util/PSRNSequence.java
Normal file
50
src/main/java/com/example/farsite/util/PSRNSequence.java
Normal file
|
@ -0,0 +1,50 @@
|
|||
package com.example.farsite.util;
|
||||
|
||||
import org.eclipse.persistence.internal.databaseaccess.Accessor;
|
||||
import org.eclipse.persistence.internal.sessions.AbstractSession;
|
||||
import org.eclipse.persistence.sequencing.Sequence;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
public class PSRNSequence extends Sequence {
|
||||
|
||||
public PSRNSequence(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getGeneratedValue(Accessor accessor, AbstractSession writeSession, String seqName) {
|
||||
return Randomness.randomHexStringSecure(36);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector getGeneratedVector(Accessor accessor, AbstractSession writeSession, String seqName, int size) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnect() { }
|
||||
|
||||
@Override
|
||||
public void onDisconnect() { }
|
||||
|
||||
@Override
|
||||
public boolean shouldAcquireValueAfterInsert() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldAlwaysOverrideExistingValue(String seqName, Object existingValue) {
|
||||
return ((String) existingValue).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldUseTransaction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldUsePreallocation() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
50
src/main/java/com/example/farsite/util/Password.java
Normal file
50
src/main/java/com/example/farsite/util/Password.java
Normal file
|
@ -0,0 +1,50 @@
|
|||
//http://stackoverflow.com/a/11038230/366692
|
||||
package com.example.farsite.util;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import java.security.SecureRandom;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
public class Password {
|
||||
// The higher the number of iterations the more
|
||||
// expensive computing the hash is for us and
|
||||
// also for an attacker.
|
||||
private static final int iterations = 20*1000;
|
||||
private static final int saltLen = 32;
|
||||
private static final int desiredKeyLen = 256;
|
||||
|
||||
/** Computes a salted PBKDF2 hash of given plaintext password
|
||||
suitable for storing in a database.
|
||||
Empty passwords are not supported. */
|
||||
public static String getSaltedHash(String password) throws Exception {
|
||||
byte[] salt = SecureRandom.getInstance("SHA1PRNG").generateSeed(saltLen);
|
||||
// store the salt with the password
|
||||
return Base64.encodeBase64String(salt) + "$" + hash(password, salt);
|
||||
}
|
||||
|
||||
/** Checks whether given plaintext password corresponds
|
||||
to a stored salted hash of the password. */
|
||||
public static boolean check(String password, String stored) throws Exception{
|
||||
String[] saltAndPass = stored.split("\\$");
|
||||
if (saltAndPass.length != 2) {
|
||||
throw new IllegalStateException(
|
||||
"The stored password have the form 'salt$hash'");
|
||||
}
|
||||
String hashOfInput = hash(password, Base64.decodeBase64(saltAndPass[0]));
|
||||
return hashOfInput.equals(saltAndPass[1]);
|
||||
}
|
||||
|
||||
// using PBKDF2 from Sun, an alternative is https://github.com/wg/scrypt
|
||||
// cf. http://www.unlimitednovelty.com/2012/03/dont-use-bcrypt.html
|
||||
private static String hash(String password, byte[] salt) throws Exception {
|
||||
if (password == null || password.length() == 0)
|
||||
throw new IllegalArgumentException("Empty passwords are not supported.");
|
||||
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
|
||||
SecretKey key = f.generateSecret(new PBEKeySpec(
|
||||
password.toCharArray(), salt, iterations, desiredKeyLen)
|
||||
);
|
||||
return Base64.encodeBase64String(key.getEncoded());
|
||||
}
|
||||
}
|
190
src/main/java/com/example/farsite/util/Randomness.java
Normal file
190
src/main/java/com/example/farsite/util/Randomness.java
Normal file
|
@ -0,0 +1,190 @@
|
|||
package com.example.farsite.util;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public final class Randomness {
|
||||
private static final int NUM_SEEDS = 16;
|
||||
private static final SecureRandom SEED_PROVIDER = new SecureRandom();
|
||||
private static final Pattern DB_OBJECT_ID_PATTERN = Pattern.compile("[0-9a-f]{24}", Pattern.CASE_INSENSITIVE);
|
||||
private static final String BASE64_CHAR = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
private static final String OBJECT_ID_CHAR = "0123456789abcdef";
|
||||
private static final int[] BASE64_NUM = new int[256]; //maps base64 characters to 0-63, others to 0.
|
||||
|
||||
static {
|
||||
for(int i = 0; i < 64; ++i) {
|
||||
BASE64_NUM[BASE64_CHAR.charAt(i)] = i;
|
||||
}
|
||||
}
|
||||
|
||||
private static final ThreadLocal<ReseedingSecureRandom> SECURE_RANDOM = new ThreadLocal<ReseedingSecureRandom>() {
|
||||
@Override
|
||||
protected ReseedingSecureRandom initialValue() {
|
||||
return new ReseedingSecureRandom();
|
||||
}
|
||||
};
|
||||
|
||||
// Use the MersenneTwisterFast implementation for its performance and long period. The implementation is
|
||||
// not thread-safe so we keep an instance in thread-local storage.
|
||||
private static final ThreadLocal<MersenneTwisterFast> MERSENNE_TWISTER = new ThreadLocal<MersenneTwisterFast>() {
|
||||
@Override
|
||||
protected MersenneTwisterFast initialValue() {
|
||||
int[] seedInts = new int[NUM_SEEDS];
|
||||
for (int i = 0; i < NUM_SEEDS; i++) {
|
||||
seedInts[i] = SEED_PROVIDER.nextInt();
|
||||
}
|
||||
|
||||
return new MersenneTwisterFast(seedInts);
|
||||
}
|
||||
};
|
||||
|
||||
private Randomness() {}
|
||||
|
||||
/** Unsecure! */
|
||||
public static MersenneTwisterFast getMersenneTwister() {
|
||||
return MERSENNE_TWISTER.get();
|
||||
}
|
||||
|
||||
public static int randomIntSecure(int n) {
|
||||
if (n < 1) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
// NOTE: This is completely different from how java.util.Random#nextInt(int) does it
|
||||
return Math.abs(SECURE_RANDOM.get().nextInt()) % n;
|
||||
}
|
||||
|
||||
public static int[] randomIntsSecure(int count) {
|
||||
int[] ints = new int[count];
|
||||
for (int i = 0; i < ints.length; ++i) {
|
||||
ints[i] = SECURE_RANDOM.get().nextInt();
|
||||
}
|
||||
return ints;
|
||||
}
|
||||
|
||||
public static int[] randomIntsUnsecure(int count) {
|
||||
MersenneTwisterFast mt = getMersenneTwister();
|
||||
int[] ints = new int[count];
|
||||
for (int i = 0; i < ints.length; ++i) {
|
||||
ints[i] = mt.nextInt();
|
||||
}
|
||||
return ints;
|
||||
}
|
||||
|
||||
public static byte[] randomBytesSecure(int size /* in bytes */) {
|
||||
byte[] bytes = new byte[size];
|
||||
SECURE_RANDOM.get().nextBytes(bytes);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static byte[] randomBytesUnsecure(int size /* in bytes */) {
|
||||
byte[] bytes = new byte[size];
|
||||
getMersenneTwister().nextBytes(bytes);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static String randomHexStringSecure(int lengthBytes) {
|
||||
StringBuilder str = new StringBuilder();
|
||||
ReseedingSecureRandom sr = SECURE_RANDOM.get();
|
||||
for (int i = 0; i < lengthBytes; i++) {
|
||||
str.append(Integer.toHexString(sr.nextInt(16)));
|
||||
}
|
||||
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
public static boolean isValidDBObjectId(String stringId) {
|
||||
return stringId != null && DB_OBJECT_ID_PATTERN.matcher(stringId).matches()
|
||||
&& stringId.toLowerCase().equals(stringId);
|
||||
}
|
||||
|
||||
public static String toValidDBObjectId(String stringId) {
|
||||
if (isValidDBObjectId(stringId)) {
|
||||
return stringId;
|
||||
}
|
||||
if (stringId.length() < 24) {
|
||||
throw new AssertionError("Can't convert to valid DBObjectId " + stringId);
|
||||
}
|
||||
StringBuilder hexString = new StringBuilder();
|
||||
for (int i = 0; i < 24; ++i) {
|
||||
byte bt = (byte) stringId.charAt(i);
|
||||
String hs = Integer.toHexString(bt & 0x0F).toLowerCase();
|
||||
hexString.append(hs);
|
||||
}
|
||||
return hexString.toString();
|
||||
}
|
||||
|
||||
public static String treeNodeId() {
|
||||
return treeNodeId('\u0000');
|
||||
}
|
||||
|
||||
public static String treeNodeId(char prefix) {
|
||||
return treeNodeId(prefix, getMersenneTwister());
|
||||
}
|
||||
|
||||
public static String treeNodeId(char prefix, MersenneTwisterFast twister) {
|
||||
final int prefixLength = prefix == '\u0000' ? 0 : 1;
|
||||
final int numChars = prefixLength + 16; // 16 * 6 is 96 bits of entropy
|
||||
char[] chars = new char[numChars];
|
||||
if (prefixLength == 1) {
|
||||
chars[0] = prefix;
|
||||
}
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
chars[prefixLength + i] = BASE64_CHAR.charAt(twister.nextInt(64));
|
||||
}
|
||||
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
/** Not secure! */
|
||||
public static String alphaString(int length) {
|
||||
MersenneTwisterFast mt = getMersenneTwister();
|
||||
char[] chars = new char[length];
|
||||
for (int i = 0; i < length; ++i) {
|
||||
chars[i] = BASE64_CHAR.charAt(mt.nextInt(52));
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
public static String alphaNumericStringSecure(int length) {
|
||||
ReseedingSecureRandom sr = SECURE_RANDOM.get();
|
||||
char[] chars = new char[length];
|
||||
for (int i = 0; i < length; ++i) {
|
||||
chars[i] = BASE64_CHAR.charAt(sr.nextInt(62));
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
public static String elementId() {
|
||||
MersenneTwisterFast mt = getMersenneTwister();
|
||||
char[] chars = new char[24];
|
||||
for (int i = 0; i < 24; ++i) {
|
||||
chars[i] = OBJECT_ID_CHAR.charAt(mt.nextInt(16));
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
public static String alphaNumericString(int length) {
|
||||
MersenneTwisterFast mt = getMersenneTwister();
|
||||
char[] chars = new char[length];
|
||||
for (int i = 0; i < length; ++i) {
|
||||
chars[i] = BASE64_CHAR.charAt(mt.nextInt(62));
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
/** Returns a feature id without the ordinal */
|
||||
public static String featureId() {
|
||||
return "F" + alphaNumericString(14);
|
||||
}
|
||||
|
||||
public static char toBase64Char(int position) {
|
||||
return BASE64_CHAR.charAt(position % 64);
|
||||
}
|
||||
|
||||
public static int fromBase64Char(char character) {
|
||||
return BASE64_NUM[character];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.example.farsite.util;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
final class ReseedingSecureRandom {
|
||||
/** How frequently does reseeding happen. This is not strict */
|
||||
private static final int RESEED_AT = 100000;
|
||||
|
||||
/** Atomic integer that keeps track of number of calls */
|
||||
private final AtomicInteger count_ = new AtomicInteger(0);
|
||||
/** Secure random */
|
||||
private volatile SecureRandom secureRandom_;
|
||||
|
||||
ReseedingSecureRandom() {
|
||||
secureRandom_ = new SecureRandom();
|
||||
}
|
||||
|
||||
void nextBytes(byte[] bytes) {
|
||||
getSecureRandom().nextBytes(bytes);
|
||||
}
|
||||
|
||||
int nextInt() {
|
||||
return getSecureRandom().nextInt();
|
||||
}
|
||||
|
||||
int nextInt(int n) {
|
||||
return getSecureRandom().nextInt(n);
|
||||
}
|
||||
|
||||
private SecureRandom getSecureRandom() {
|
||||
int currentCount = count_.incrementAndGet();
|
||||
if ((currentCount % RESEED_AT) == 0) {
|
||||
// Reset to 0, next caller should not come into this "if" and might use the old secure random which is fine
|
||||
count_.set(0);
|
||||
secureRandom_ = new SecureRandom();
|
||||
}
|
||||
|
||||
return secureRandom_;
|
||||
}
|
||||
}
|
49
src/main/java/com/example/farsite/util/SamplePopulation.java
Normal file
49
src/main/java/com/example/farsite/util/SamplePopulation.java
Normal file
|
@ -0,0 +1,49 @@
|
|||
package com.example.farsite.util;
|
||||
|
||||
import com.example.farsite.model.Address;
|
||||
import com.example.farsite.model.Employee;
|
||||
import com.example.farsite.model.Gender;
|
||||
import com.github.javafaker.Faker;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Examples illustrating the use of JPA with the employee domain
|
||||
* com.example.farsite.model.
|
||||
*
|
||||
* @see com.example.farsite.jpa.model.ExampleTest
|
||||
*/
|
||||
public class SamplePopulation {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SamplePopulation.class);
|
||||
|
||||
Faker fake = new Faker();
|
||||
|
||||
/**
|
||||
* Create the specified number of random sample employees.
|
||||
*/
|
||||
public void createNewEmployees(EntityManager em, int quantity) {
|
||||
for (int index = 0; index < quantity; index++) {
|
||||
em.persist(createRandomEmployee());
|
||||
}
|
||||
}
|
||||
|
||||
public Employee createRandomEmployee() {
|
||||
Random r = new Random();
|
||||
|
||||
Employee emp = new Employee();
|
||||
emp.setGender(Gender.values()[r.nextInt(2)]);
|
||||
emp.setFirstName(fake.name().firstName());
|
||||
emp.setLastName(fake.name().lastName());
|
||||
emp.addPhoneNumber("HOME", fake.phoneNumber().phoneNumber().toString());
|
||||
emp.addPhoneNumber("WORK", fake.phoneNumber().phoneNumber().toString());
|
||||
emp.addPhoneNumber("MOBILE", fake.phoneNumber().cellPhone().toString());
|
||||
|
||||
emp.setAddress(new Address(fake.address().city(), fake.address().country(), "", fake.address().zipCode(), fake.address().streetAddress()));
|
||||
|
||||
return emp;
|
||||
}
|
||||
}
|
104
src/main/java/com/example/farsite/util/SerialVersionUID.java
Normal file
104
src/main/java/com/example/farsite/util/SerialVersionUID.java
Normal file
|
@ -0,0 +1,104 @@
|
|||
package com.example.farsite.util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class SerialVersionUID {
|
||||
|
||||
/**
|
||||
* Compute a UID for the serialization version of a class.
|
||||
*
|
||||
* The Java object serialization standard defines an algorithm for computing the default serialVersionUID of a
|
||||
* class: http://docs.oracle.com/javase/6/docs/platform/serialization/spec/class.html#4100. This method computes a
|
||||
* serialVersionUID value model classes. For example, the com.example.model.User class should specify the following:
|
||||
*
|
||||
* <code><pre>
|
||||
* private static final long serialVersionUID = SerialVersionUID.computeUID(User.class);
|
||||
* </pre></code>
|
||||
*
|
||||
* Java provides a way to access and possibly compute a default value for serialVersionUID using
|
||||
* java.io.ObjectStreamClass. If a class has no serialVersionID, the
|
||||
* {@link java.io.ObjectStreamClass#getSerialVersionUID()} computes a default value according to the algorithm
|
||||
* defined by the object serialization standard. However, we do not use this method because there is no clean way to
|
||||
* access the private method computeDefaultSUID that performs the computation.
|
||||
*
|
||||
* Therefore, this method is based on, but different from the implementation of
|
||||
* java.io.ObjectStreamClass#computeDefaultSIUD(Class<?>). This implementation does not factor various elements of
|
||||
* the default computation into the resulting hash because the goal is to characterize versions of the class which
|
||||
* are compatible for serialization and deserialization of their fields even if method signatures change. We don't
|
||||
* want the addition of a method or a constructor to change the computed value. Therefore, this method uses only
|
||||
* some of the internal logic of the default algorithm: it implements steps 1, 4, 8 and 9 of the standard algorithm
|
||||
* and omits steps 2, 3, 5, 6 and 8.
|
||||
*
|
||||
* Like the standard algorithm, this implementation writes various elements of the class definition to a
|
||||
* DataOutputStream and then computes a SHA-1 digest of the stream and returns a hash based on the digest. Unlike
|
||||
* the standard algorithm, this implementation does not include interface, method and constructor signatures.
|
||||
*
|
||||
* @param clazz
|
||||
* The class
|
||||
* @return A version UID.
|
||||
*/
|
||||
public static long compute(final Class<?> clazz) {
|
||||
try {
|
||||
ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
|
||||
DataOutputStream dataOut = new DataOutputStream(bytesOut);
|
||||
|
||||
// #1
|
||||
dataOut.writeUTF(clazz.getName());
|
||||
|
||||
// #4
|
||||
List<Field> sorted = Arrays.asList(clazz.getDeclaredFields());
|
||||
sorted.sort(new Comparator<Field>() {
|
||||
|
||||
@Override
|
||||
public int compare(Field field1, Field field2) {
|
||||
return field1.getName().compareTo(field2.getName());
|
||||
}
|
||||
|
||||
});
|
||||
for (final Field field : sorted) {
|
||||
int mods = field.getModifiers() &
|
||||
(Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED |
|
||||
Modifier.STATIC | Modifier.FINAL | Modifier.VOLATILE |
|
||||
Modifier.TRANSIENT);
|
||||
if (((mods & Modifier.PRIVATE) == 0) ||
|
||||
((mods & (Modifier.STATIC | Modifier.TRANSIENT)) == 0))
|
||||
// Don't include private static or
|
||||
// private transient fields
|
||||
{
|
||||
dataOut.writeUTF(field.getName());
|
||||
dataOut.writeInt(mods);
|
||||
dataOut.writeUTF(field.getType().getName());
|
||||
}
|
||||
}
|
||||
dataOut.flush();
|
||||
|
||||
// #8
|
||||
MessageDigest md = MessageDigest.getInstance("SHA");
|
||||
byte[] hashBytes = md.digest(bytesOut.toByteArray());
|
||||
|
||||
// #9
|
||||
long hash = 0L;
|
||||
for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
|
||||
hash = (hash << 8) | (hashBytes[i] & 0xFF);
|
||||
}
|
||||
return hash;
|
||||
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new InternalError(ex);
|
||||
}
|
||||
catch (NoSuchAlgorithmException ex) {
|
||||
throw new SecurityException(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
55
src/main/java/com/example/farsite/util/UUIDSequence.java
Normal file
55
src/main/java/com/example/farsite/util/UUIDSequence.java
Normal file
|
@ -0,0 +1,55 @@
|
|||
package com.example.farsite.util;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.eclipse.persistence.config.SessionCustomizer;
|
||||
import org.eclipse.persistence.internal.databaseaccess.Accessor;
|
||||
import org.eclipse.persistence.internal.sessions.AbstractSession;
|
||||
import org.eclipse.persistence.sequencing.Sequence;
|
||||
import org.eclipse.persistence.sessions.Session;
|
||||
|
||||
public class UUIDSequence extends Sequence {
|
||||
|
||||
public UUIDSequence(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getGeneratedValue(Accessor accessor, AbstractSession writeSession, String seqName) {
|
||||
return UUID.randomUUID().toString().toUpperCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector getGeneratedVector(Accessor accessor, AbstractSession writeSession, String seqName, int size) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnect() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnect() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldAcquireValueAfterInsert() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldAlwaysOverrideExistingValue(String seqName, Object existingValue) {
|
||||
return ((String) existingValue).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldUseTransaction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldUsePreallocation() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
66
src/main/resources/META-INF/persistence.xml
Normal file
66
src/main/resources/META-INF/persistence.xml
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
|
||||
<!-- https://jcp.org/aboutJava/communityprocess/final/jsr338/index.html -->
|
||||
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
|
||||
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
|
||||
version="2.1">
|
||||
|
||||
<persistence-unit name="employee" transaction-type="RESOURCE_LOCAL">
|
||||
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
||||
<class>com.example.farsite.model.Address</class>
|
||||
<class>com.example.farsite.model.Employee</class>
|
||||
<class>com.example.farsite.model.EmploymentPeriod</class>
|
||||
<class>com.example.farsite.model.Gender</class>
|
||||
<class>com.example.farsite.model.GenderConverter</class>
|
||||
<class>com.example.farsite.model.PhoneNumber</class>
|
||||
<properties>
|
||||
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
|
||||
<property name="eclipselink.session.customizer" value="com.example.farsite.util.CrDBSessionCustomizer"/>
|
||||
|
||||
<!-- EclipseLink should create the database schema automatically -->
|
||||
<property name="eclipselink.ddl-generation" value="create-or-extend-tables"/>
|
||||
<property name="eclipselink.ddl-generation.output-mode" value="database"/>
|
||||
<property name="javax.persistence.schema-generation.database.action" value="create"/>
|
||||
<property name="eclipselink.target-database" value="com.example.farsite.util.CockroachDBPlatform"/>
|
||||
|
||||
<property name="eclipselink.logging.logger" value="JavaLogger"/>
|
||||
<property name="eclipselink.logging.timestamp" value="false"/>
|
||||
<property name="eclipselink.logging.thread" value="false"/>
|
||||
<property name="eclipselink.logging.session" value="false"/>
|
||||
<property name="eclipselink.logging.exceptions" value="false"/>
|
||||
<property name="eclipselink.logging.connection" value="false"/>
|
||||
<property name="eclipselink.logging.level.metadata" value="WARNING"/>
|
||||
<property name="eclipselink.logging.parameters" value="true"/>
|
||||
|
||||
<property name="eclipselink.profiler" value="org.eclipse.persistence.tools.profiler.PerformanceProfiler"/>
|
||||
|
||||
<!-- Optimization - statement caching -->
|
||||
<property name="eclipselink.jdbc.cache-statements" value="true"/>
|
||||
<!-- Optimization - batch writing -->
|
||||
<property name="eclipselink.jdbc.batch-writing" value="JDBC"/>
|
||||
<property name="eclipselink.jdbc.batch-writing.size" value="1000"/>
|
||||
<!-- Optimization - disable caching for batch insert (caching only improves reads, so only adds overhead for inserts) -->
|
||||
<property name="eclipselink.cache.shared.default" value="false"/>
|
||||
<!-- Except for XXX which is shared by orders
|
||||
<property name="eclipselink.cache.shared.Customer" value="true"/> TODO(gburd): ? -->
|
||||
<!-- Optimization - turn logging off
|
||||
<property name="eclipselink.logging.level" value="off" /> -->
|
||||
<property name="eclipselink.logging.level" value="FINE"/>
|
||||
<!-- Optimization - close EntityManager on commit, to avoid cost of resume -->
|
||||
<property name="eclipselink.persistence-context.close-on-commit" value="true"/>
|
||||
<!-- Optimization - avoid auto flush cost on query execution -->
|
||||
<property name="eclipselink.persistence-context.flush-mode" value="commit"/>
|
||||
<!-- Optimization - avoid cost of persist on commit -->
|
||||
<property name="eclipselink.persistence-context.persist-on-commit" value="false"/>
|
||||
<!-- Optimization - -->
|
||||
<property name="eclipselink.jdbc.bind-parameters" value="true"/>
|
||||
<!-- Optimization - create indexes for all foreign key fields -->
|
||||
<property name="eclipselink.ddl-generation.index-foreign-keys" value="true"/>
|
||||
<!-- Optimization - enable query caching -->
|
||||
<property name="eclipselink.cache.query-results" value="true"/>
|
||||
<!-- <property name="eclipselink.cache.database-event-listener" value="DCN"/> -->
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</persistence>
|
|
@ -1,107 +0,0 @@
|
|||
package com.example.farsite.model;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.Persistence;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class JpaTest {
|
||||
|
||||
private static final String PERSISTENCE_UNIT_NAME = "people";
|
||||
private EntityManagerFactory factory;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
|
||||
EntityManager em = factory.createEntityManager();
|
||||
|
||||
// Begin a new local transaction so that we can persist a new entity
|
||||
em.getTransaction().begin();
|
||||
|
||||
// read the existing entries
|
||||
Query q = em.createQuery("select m from Person m");
|
||||
// Persons should be empty
|
||||
|
||||
// do we have entries?
|
||||
boolean createNewEntries = (q.getResultList().size() == 0);
|
||||
|
||||
// No, so lets create new entries
|
||||
if (createNewEntries) {
|
||||
assertTrue(q.getResultList().size() == 0);
|
||||
Family family = new Family();
|
||||
family.setDescription("Family for the Knopfs");
|
||||
em.persist(family);
|
||||
for (int i = 0; i < 40; i++) {
|
||||
Person person = new Person();
|
||||
person.setFirstName("Jim_" + i);
|
||||
person.setLastName("Knopf_" + i);
|
||||
em.persist(person);
|
||||
// now persists the family person relationship
|
||||
family.getMembers().add(person);
|
||||
em.persist(person);
|
||||
em.persist(family);
|
||||
}
|
||||
}
|
||||
|
||||
// Commit the transaction, which will cause the entity to
|
||||
// be stored in the database
|
||||
em.getTransaction().commit();
|
||||
|
||||
// It is always good practice to close the EntityManager so that
|
||||
// resources are conserved.
|
||||
em.close();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkAvailablePeople() {
|
||||
|
||||
// now lets check the database and see if the created entries are there
|
||||
// create a fresh, new EntityManager
|
||||
EntityManager em = factory.createEntityManager();
|
||||
|
||||
// Perform a simple query for all the Message entities
|
||||
Query q = em.createQuery("select m from Person m");
|
||||
|
||||
// We should have 40 Persons in the database
|
||||
assertTrue(q.getResultList().size() == 40);
|
||||
|
||||
em.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkFamily() {
|
||||
EntityManager em = factory.createEntityManager();
|
||||
// Go through each of the entities and print out each of their
|
||||
// messages, as well as the date on which it was created
|
||||
Query q = em.createQuery("select f from Family f");
|
||||
|
||||
// We should have one family with 40 persons
|
||||
assertTrue(q.getResultList().size() == 1);
|
||||
assertTrue(((Family) q.getSingleResult()).getMembers().size() == 40);
|
||||
em.close();
|
||||
}
|
||||
|
||||
@Test(expected = javax.persistence.NoResultException.class)
|
||||
public void deletePerson() {
|
||||
EntityManager em = factory.createEntityManager();
|
||||
// Begin a new local transaction so that we can persist a new entity
|
||||
em.getTransaction().begin();
|
||||
Query q = em
|
||||
.createQuery("SELECT p FROM Person p WHERE p.firstName = :firstName AND p.lastName = :lastName");
|
||||
q.setParameter("firstName", "Jim_1");
|
||||
q.setParameter("lastName", "Knopf_!");
|
||||
Person user = (Person) q.getSingleResult();
|
||||
em.remove(user);
|
||||
em.getTransaction().commit();
|
||||
Person person = (Person) q.getSingleResult();
|
||||
// Begin a new local transaction so that we can persist a new entity
|
||||
|
||||
em.close();
|
||||
}
|
||||
}
|
38
src/test/java/com/example/farsite/test/ConfigTest.java
Normal file
38
src/test/java/com/example/farsite/test/ConfigTest.java
Normal file
|
@ -0,0 +1,38 @@
|
|||
package com.example.farsite.test;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ConfigTest {
|
||||
|
||||
@Test
|
||||
public void bootstrap() {
|
||||
EntityManager em = getEmf().createEntityManager();
|
||||
|
||||
em.close();
|
||||
}
|
||||
|
||||
private static EntityManagerFactory emf;
|
||||
|
||||
public static EntityManagerFactory getEmf() {
|
||||
return emf;
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void createEMF() {
|
||||
emf = PersistenceTesting.createEMF(true);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void closeEMF() {
|
||||
if (emf != null && emf.isOpen()) {
|
||||
emf.close();
|
||||
}
|
||||
emf = null;
|
||||
}
|
||||
|
||||
}
|
12
src/test/java/com/example/farsite/test/ExampleTest.java
Normal file
12
src/test/java/com/example/farsite/test/ExampleTest.java
Normal file
|
@ -0,0 +1,12 @@
|
|||
package com.example.farsite.test;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class ExampleTest {
|
||||
|
||||
@Test
|
||||
public void testMain() throws Exception {
|
||||
Main.main(null);
|
||||
}
|
||||
|
||||
}
|
108
src/test/java/com/example/farsite/test/Main.java
Normal file
108
src/test/java/com/example/farsite/test/Main.java
Normal file
|
@ -0,0 +1,108 @@
|
|||
package com.example.farsite.test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.TypedQuery;
|
||||
|
||||
import com.example.farsite.model.Employee;
|
||||
import com.example.farsite.model.Gender;
|
||||
import com.example.farsite.util.SamplePopulation;
|
||||
|
||||
/**
|
||||
* Examples illustrating the use of JPA with the employee domain
|
||||
* com.example.farsite.jpa.model.
|
||||
*
|
||||
* @see ExampleTest
|
||||
*/
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
EntityManagerFactory emf = PersistenceTesting.createEMF(true);
|
||||
Main example = new Main();
|
||||
|
||||
try {
|
||||
EntityManager em = emf.createEntityManager();
|
||||
|
||||
em.getTransaction().begin();
|
||||
new SamplePopulation().createNewEmployees(em, 1000);
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
|
||||
// Add employee with 555 area code to satisfy a test query
|
||||
em.getTransaction().begin();
|
||||
Employee e = new Employee();
|
||||
e.setFirstName("John");
|
||||
e.setLastName("Doe");
|
||||
e.setGender(Gender.Male);
|
||||
e.addPhoneNumber("HOME", "555-5552222");
|
||||
em.persist(e);
|
||||
Long id = e.getId();
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
|
||||
example.queryAllEmployees(em);
|
||||
em.clear();
|
||||
|
||||
example.queryEmployeeLikeAreaCode55(em);
|
||||
em.clear();
|
||||
|
||||
example.modifyEmployee(em, id);
|
||||
em.clear();
|
||||
|
||||
example.deleteEmployee(em, id);
|
||||
em.clear();
|
||||
|
||||
em.close();
|
||||
|
||||
} finally {
|
||||
emf.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void queryAllEmployees(EntityManager em) {
|
||||
List<Employee> results = em.createQuery("SELECT e FROM Employee e", Employee.class).getResultList();
|
||||
|
||||
System.out.println("Query All Results: " + results.size());
|
||||
|
||||
results.forEach(e -> System.out.println("\t>" + e));
|
||||
}
|
||||
|
||||
public void queryEmployeeLikeAreaCode55(EntityManager em) {
|
||||
System.out.println("\n\n --- Query Employee.phoneNumbers.areaCode LIKE '55%' ---");
|
||||
|
||||
TypedQuery<Employee> query = em.createQuery("SELECT e FROM Employee e JOIN e.phoneNumbers phones WHERE phones.number LIKE '55%'", Employee.class);
|
||||
List<Employee> emps = query.getResultList();
|
||||
|
||||
emps.forEach(e -> System.out.println("> " + e));
|
||||
}
|
||||
|
||||
public void modifyEmployee(EntityManager em, Long id) {
|
||||
System.out.println("\n\n --- Modify Employee ---");
|
||||
em.getTransaction().begin();
|
||||
|
||||
Employee emp = em.find(Employee.class, id);
|
||||
emp.setSalary(1);
|
||||
|
||||
TypedQuery<Employee> query = em.createQuery("SELECT e FROM Employee e WHERE e.id = :ID AND e.firstName = :FNAME", Employee.class);
|
||||
query.setParameter("ID", id);
|
||||
query.setParameter("FNAME", emp.getFirstName());
|
||||
emp = query.getSingleResult();
|
||||
|
||||
em.getTransaction().commit();
|
||||
|
||||
}
|
||||
|
||||
public void deleteEmployee(EntityManager em, Long id) {
|
||||
em.getTransaction().begin();
|
||||
|
||||
em.remove(em.find(Employee.class, id));
|
||||
em.flush();
|
||||
|
||||
//em.getTransaction().rollback();
|
||||
em.getTransaction().commit();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package com.example.farsite.test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.Persistence;
|
||||
|
||||
import org.eclipse.persistence.config.PersistenceUnitProperties;
|
||||
|
||||
/**
|
||||
* Persistence testing helper which creates an EMF providing testing overrides
|
||||
* to use direct JDBC instead of a data source
|
||||
*/
|
||||
public class PersistenceTesting {
|
||||
|
||||
public static EntityManagerFactory createEMF(boolean replaceTables) {
|
||||
Map<String, Object> props = new HashMap<String, Object>();
|
||||
|
||||
// Ensure the persistence.xml provided data source are ignored for Java
|
||||
// SE testing
|
||||
props.put(PersistenceUnitProperties.NON_JTA_DATASOURCE, "");
|
||||
props.put(PersistenceUnitProperties.JTA_DATASOURCE, "");
|
||||
props.put(PersistenceUnitProperties.TRANSACTION_TYPE, "RESOURCE_LOCAL");
|
||||
|
||||
// Configure the use of embedded derby for the tests allowing system
|
||||
// properties of the same name to override
|
||||
if (true) {
|
||||
setProperty(props, PersistenceUnitProperties.JDBC_DRIVER, "org.postgresql.Driver");
|
||||
setProperty(props, PersistenceUnitProperties.JDBC_URL, "jdbc:postgresql://127.0.0.1:26257/farsite");
|
||||
setProperty(props, PersistenceUnitProperties.JDBC_USER, "root");
|
||||
setProperty(props, PersistenceUnitProperties.JDBC_PASSWORD, "");
|
||||
} else {
|
||||
setProperty(props, PersistenceUnitProperties.JDBC_DRIVER, "org.postgresql.Driver");
|
||||
setProperty(props, PersistenceUnitProperties.JDBC_URL, "jdbc:postgresql://127.0.0.1:5432/farsite");
|
||||
setProperty(props, PersistenceUnitProperties.JDBC_USER, "postgres");
|
||||
setProperty(props, PersistenceUnitProperties.JDBC_PASSWORD, "postgres");
|
||||
}
|
||||
|
||||
// Ensure weaving is used
|
||||
props.put(PersistenceUnitProperties.WEAVING, "false"); // TODO(gburd): true, -javaagent:toplink-essentials-agent.jar
|
||||
|
||||
if (replaceTables) {
|
||||
props.put(PersistenceUnitProperties.DDL_GENERATION, PersistenceUnitProperties.DROP_AND_CREATE);
|
||||
props.put(PersistenceUnitProperties.DDL_GENERATION_MODE, PersistenceUnitProperties.DDL_DATABASE_GENERATION);
|
||||
}
|
||||
|
||||
return Persistence.createEntityManagerFactory("employee", props);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the system property value if it exists, otherwise use the default
|
||||
* value.
|
||||
*/
|
||||
private static void setProperty(Map<String, Object> props, String key, String defaultValue) {
|
||||
String value = defaultValue;
|
||||
if (System.getProperties().containsKey(key)) {
|
||||
value = System.getProperty(key);
|
||||
}
|
||||
props.put(key, value);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue