Functional, not fully understood, but functional.

This commit is contained in:
Greg Burd 2017-04-05 15:50:37 -04:00
parent 40f5c8b460
commit 1fa5250338
45 changed files with 4680 additions and 441 deletions

2
.gitignore vendored
View file

@ -1,3 +1,5 @@
build
.gradle
gradlew*
gradle/

View file

@ -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" />

View file

@ -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
View 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"

View file

@ -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()
}
}

View file

@ -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.+"

View file

@ -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!/" />

File diff suppressed because it is too large Load diff

View file

@ -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>

View file

@ -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();
}
}

View 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;
}

View 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;
}
}

View 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);
}
}

View file

@ -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);
}
}

View file

@ -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>();
}

View file

@ -0,0 +1,5 @@
package com.example.farsite.model;
public enum Gender {
Female, Male, ;
}

View 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);
}
}
}

View file

@ -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;
}

View 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();
}

View file

@ -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>();
}

View 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;
}
}

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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);});
}
}

View 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;
}
}

View file

@ -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;
}
}

File diff suppressed because it is too large Load diff

View 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;
}
}

View 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());
}
}

View 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];
}
}

View file

@ -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_;
}
}

View 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;
}
}

View 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());
}
}
}

View 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;
}
}

View 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>

View file

@ -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();
}
}

View 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;
}
}

View 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);
}
}

View 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();
}
}

View file

@ -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);
}
}