#50 - Added example of using Spring Data JPA with EclipseLink.

original pull request: #68.
This commit is contained in:
Jeremy Rickard
2015-03-12 21:56:30 -06:00
committed by Oliver Gierke
parent 33a4433058
commit b092d6fb30
11 changed files with 815 additions and 1 deletions

View File

@@ -0,0 +1,7 @@
# Spring Data JPA - Eclipselink + Static Weaving Example
This project contains an example of using Eclipselink with static weaving with Spring Data. Static weaving is
accomplished with a maven plugin that requires a persistence.xml, so a persistence.xml exists in this project.
The persistence.xml is not actually used by the Spring Boot example and is only used at build time for the maven
plugin. To use the persistence.xml file, please see instructions on how to [use a traditional persistence.xm](http://docs.spring.io/spring-boot/docs/current/reference/html/howto-data-access.html#howto-use-traditional-persistence-xml).

81
jpa/eclipselink/pom.xml Normal file
View File

@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.data.examples</groupId>
<artifactId>spring-data-jpa-examples</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</parent>
<repositories>
<repository>
<id>com.ethlo.eclipselink.tools</id>
<url>http://ethlo.com/maven</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>com.ethlo.eclipselink.tools</id>
<url>http://ethlo.com/maven</url>
</pluginRepository>
</pluginRepositories>
<modelVersion>4.0.0</modelVersion>
<groupId>example.springdata.jpa</groupId>
<artifactId>eclipselink</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Spring Data JPA - Spring Data JPA w/ Eclipse Link and Static Weaving</name>
<description>Example Spring Data JPA Project using EclipseLink and Static Weaving</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>example.springdata.jpa.eclipselink.SpringDataJpaEclipseLinkApplication</start-class>
<java.version>1.8</java.version>
<eclipselink.version>2.6.0</eclipselink.version>
</properties>
<dependencies>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>${eclipselink.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- Static weaver for EclipseLink -->
<plugin>
<groupId>com.ethlo.persistence.tools</groupId>
<artifactId>eclipselink-maven-plugin</artifactId>
<version>1.1-SNAPSHOT</version>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>weave</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>${eclipselink.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,94 @@
/*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.jpa.eclipselink;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect;
import org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
* Spring Boot application with Spring Java Config annotations that use EclipseLink as the JPA Provider
* and turn on Static Weaving of the entity classes by disabling dynamic weaving and utilizing a maven
* build that includes a static weaving plugin.
*
* @author Jeremy Rickard
*/
@SpringBootApplication
@Configuration
@EnableJpaRepositories("example.springdata.jpa.eclipselink.repositories")
public class SpringDataJpaEclipseLinkApplication {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).build();
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean lemfb = new LocalContainerEntityManagerFactoryBean();
lemfb.setDataSource(dataSource());
lemfb.setJpaVendorAdapter(jpaVendorAdapter());
lemfb.setJpaDialect(eclipseLinkJpaDialect());
lemfb.setJpaPropertyMap(jpaProperties());
lemfb.setPackagesToScan("example.springdata.jpa.eclipselink.domain");
return lemfb;
}
@Bean
public EclipseLinkJpaDialect eclipseLinkJpaDialect() {
return new EclipseLinkJpaDialect();
}
/*
* Set this property to disable LoadTimeWeaver (i.e. Dynamic Weaving) for EclipseLink.
* Otherwise, you'll get: Cannot apply class transformer without LoadTimeWeaver specified
*/
@Bean
public Map<String, String> jpaProperties() {
Map<String, String> props = new HashMap<>();
props.put("eclipselink.weaving", "false");
return props;
}
@Bean
public JpaVendorAdapter jpaVendorAdapter() {
EclipseLinkJpaVendorAdapter jpaVendorAdapter = new EclipseLinkJpaVendorAdapter();
jpaVendorAdapter.setDatabase(Database.HSQL);
jpaVendorAdapter.setGenerateDdl(true);
return jpaVendorAdapter;
}
public static void main(String[] args) {
SpringApplication.run(SpringDataJpaEclipseLinkApplication.class, args);
}
}

View File

@@ -0,0 +1,27 @@
package example.springdata.jpa.eclipselink.domain;
/*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Jeremy Rickard
*/
public enum Gender {
FEMALE,
MALE
}

View File

@@ -0,0 +1,136 @@
/*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.jpa.eclipselink.domain;
/**
* Entity showing use of {@link org.eclipse.persistence.annotations.UuidGenerator} from
* the EclipseLink JPA Provider. Does not extend the AbstractPersistable because of the UUID generator
*
* @author Jeremy Rickard
*/
import org.eclipse.persistence.annotations.UuidGenerator;
import javax.persistence.*;
import java.util.List;
@Entity
public class Participant {
@Id
@UuidGenerator(name = "UUID")
@GeneratedValue(generator = "UUID")
private String uuid;
private String firstName;
private String lastName;
private String emailAddress;
private String phoneNumber;
private int age;
@Enumerated
private Gender gender;
@ManyToMany(mappedBy = "registrations")
private List<Race> raceRegistrations;
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
public List<Race> getRaceRegistrations() {
return raceRegistrations;
}
public void setRaceRegistrations(List<Race> raceRegistrations) {
this.raceRegistrations = raceRegistrations;
}
public boolean equals(Object obj) {
if (null == obj) {
return false;
} else if (this == obj) {
return true;
} else if (!this.getClass().equals(obj.getClass())) {
return false;
} else {
Participant that = (Participant) obj;
return null == this.getUuid() ? false : this.getUuid().equals(that.getUuid());
}
}
public int hashCode() {
byte hashCode = 17;
int hashCode1 = hashCode + (null == this.getUuid() ? 0 : this.getUuid().hashCode() * 31);
return hashCode1;
}
}

View File

@@ -0,0 +1,124 @@
/*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.jpa.eclipselink.domain;
/**
* Entity showing use of {@link org.eclipse.persistence.annotations.UuidGenerator} from
* the EclipseLink JPA Provider. Does not extend the AbstractPersistable because of the UUID generator
*
* @author Jeremy Rickard
*/
import org.eclipse.persistence.annotations.UuidGenerator;
import javax.persistence.*;
import java.util.Date;
import java.util.List;
@Entity
public class Race {
@Id
@UuidGenerator(name = "UUID")
@GeneratedValue(generator = "UUID")
private String uuid;
private double distance;
@Column(nullable = false)
@Temporal(TemporalType.DATE)
private Date date;
@Column(nullable = false)
private String name;
@Column(nullable = false, length = 5000)
private String description;
@ManyToMany
@JoinTable(name = "RACE_REG",
joinColumns = {@JoinColumn(name = "RACE_ID", referencedColumnName = "uuid")},
inverseJoinColumns = {@JoinColumn(name = "PART_ID", referencedColumnName = "uuid", unique = true)})
private List<Participant> registrations;
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public double getDistance() {
return distance;
}
public void setDistance(double distance) {
this.distance = distance;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public List<Participant> getRegistrations() {
return registrations;
}
public void setRegistrations(List<Participant> registrations) {
this.registrations = registrations;
}
public boolean equals(Object obj) {
if (null == obj) {
return false;
} else if (this == obj) {
return true;
} else if (!this.getClass().equals(obj.getClass())) {
return false;
} else {
Race that = (Race) obj;
return null == this.getUuid() ? false : this.getUuid().equals(that.getUuid());
}
}
public int hashCode() {
byte hashCode = 17;
int hashCode1 = hashCode + (null == this.getUuid() ? 0 : this.getUuid().hashCode() * 31);
return hashCode1;
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.jpa.eclipselink.repositories;
import example.springdata.jpa.eclipselink.domain.Participant;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
/**
* Repository to manage {@link example.springdata.jpa.eclipselink.domain.Participant} instances.
*
* @author Jeremy Rickard
*/
public interface ParticipantRepository extends CrudRepository<Participant, String> {
@Query("SELECT p from Participant p")
List<Participant> findAll();
List<Participant> findByLastName(String lastName);
List<Participant> findByAgeLessThan(int age);
List<Participant> findByAgeBetween(int age1, int age2);
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.jpa.eclipselink.repositories;
/**
* Repository to manage {@link example.springdata.jpa.eclipselink.domain.Race} instances.
*
* @author Jeremy Rickard
*/
import example.springdata.jpa.eclipselink.domain.Race;
import org.springframework.data.repository.CrudRepository;
import java.util.Date;
import java.util.List;
public interface RaceRepository extends CrudRepository<Race, String> {
List<Race> findByName(String name);
List<Race> findByDate(Date date);
List<Race> findByDateBefore(Date date);
List<Race> findByDistanceBetween(double start, double end);
}

View File

@@ -0,0 +1,264 @@
package example.springdata.jpa.eclipselink;
import example.springdata.jpa.eclipselink.domain.Gender;
import example.springdata.jpa.eclipselink.domain.Participant;
import example.springdata.jpa.eclipselink.domain.Race;
import example.springdata.jpa.eclipselink.repositories.ParticipantRepository;
import example.springdata.jpa.eclipselink.repositories.RaceRepository;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.*;
/**
* Test for Spring Data JPA EclipseLink w/ Static Weaving example
*
* @author Jeremy Rickard
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SpringDataJpaEclipseLinkApplication.class)
public class SpringDataJpaEclipseLinkApplicationTests {
@Autowired
RaceRepository raceRepository;
@Autowired
ParticipantRepository participantRepository;
Race pikesPeakAscent;
Race pikesPeakMarathon;
Race summerRoundUp;
Race gardenOfTheGods10Mile;
Participant one;
Participant two;
Participant three;
Date ascentStartDate;
SimpleDateFormat sdf;
double ascentDistanceInKM = 21.4364621;
@Before
public void setUp() throws Exception {
sdf = new SimpleDateFormat("MM/dd/yyyy HH:MM z");
ascentStartDate = sdf.parse("08/15/2015 07:00 MDT");
pikesPeakAscent = new Race();
pikesPeakAscent.setName("Pikes Peak Ascent");
pikesPeakAscent.setDistance(ascentDistanceInKM);
pikesPeakAscent.setDate(ascentStartDate);
pikesPeakAscent.setDescription("Started in 1956 as a challenge between smokers and non-smokers, " +
"the Pikes Peak Marathon is #3 on the list of longest running US marathons behind Boston and Yonkers.");
pikesPeakMarathon = new Race();
pikesPeakMarathon.setName("Pikes Peak Marathon");
pikesPeakMarathon.setDistance(ascentDistanceInKM * 2);
pikesPeakMarathon.setDate(ascentStartDate);
pikesPeakMarathon.setDescription("Started in 1956 as a challenge between smokers and non-smokers, " +
"the Pikes Peak Marathon is #3 on the list of longest running US marathons behind Boston and Yonkers.");
summerRoundUp = new Race();
summerRoundUp.setName("Summer Round Up");
summerRoundUp.setDescription("2nd Leg of the Triple Crown of Running");
summerRoundUp.setDate(sdf.parse("07/12/2015 07:00 MDT"));
summerRoundUp.setDistance(12.0);
gardenOfTheGods10Mile = new Race();
gardenOfTheGods10Mile.setName("Garden of the Gods 10 Miler");
gardenOfTheGods10Mile.setDescription("1st Leg of the Triple Crown of Running");
gardenOfTheGods10Mile.setDate(sdf.parse("06/15/2015 07:00 MDT"));
gardenOfTheGods10Mile.setDistance(16.0934);
one = new Participant();
one.setAge(25);
one.setEmailAddress("john.doe@gmail.com");
one.setFirstName("John");
one.setLastName("Doe");
one.setPhoneNumber("1-123-234-5679");
one.setGender(Gender.MALE);
two = new Participant();
two.setAge(21);
two.setEmailAddress("jane.doe@gmail.com");
two.setFirstName("Jane");
two.setLastName("Doe");
two.setPhoneNumber("1-123-234-5678");
two.setGender(Gender.FEMALE);
three = new Participant();
three.setAge(62);
three.setEmailAddress("sam.smith@gmail.com");
three.setFirstName("Samantha");
three.setLastName("Smith");
three.setPhoneNumber("1-234-911-5678");
three.setGender(Gender.FEMALE);
}
@Test
public void contextLoads() {
}
@Test
public void testInsertRace() {
pikesPeakAscent = raceRepository.save(pikesPeakAscent);
pikesPeakMarathon = raceRepository.save(pikesPeakMarathon);
summerRoundUp = raceRepository.save(summerRoundUp);
gardenOfTheGods10Mile = raceRepository.save(gardenOfTheGods10Mile);
assertNotNull(pikesPeakAscent.getUuid());
assertNotNull(pikesPeakMarathon.getUuid());
assertNotNull(summerRoundUp.getUuid());
assertNotNull(gardenOfTheGods10Mile.getUuid());
assertNotEquals(pikesPeakAscent.getUuid(), pikesPeakMarathon.getUuid());
}
@Test
public void testFindRacesByDates() {
pikesPeakAscent = raceRepository.save(pikesPeakAscent);
pikesPeakMarathon = raceRepository.save(pikesPeakMarathon);
summerRoundUp = raceRepository.save(summerRoundUp);
gardenOfTheGods10Mile = raceRepository.save(gardenOfTheGods10Mile);
List<Race> races = raceRepository.findByDate(ascentStartDate);
assertThat(races.contains(pikesPeakAscent), is(true));
assertThat(races.contains(pikesPeakMarathon), is(true));
races = raceRepository.findByDateBefore(ascentStartDate);
assertThat(races.contains(pikesPeakAscent), is(false));
assertThat(races.contains(pikesPeakMarathon), is(false));
}
@Test
public void testFindRacesByDistance() {
pikesPeakAscent = raceRepository.save(pikesPeakAscent);
pikesPeakMarathon = raceRepository.save(pikesPeakMarathon);
summerRoundUp = raceRepository.save(summerRoundUp);
gardenOfTheGods10Mile = raceRepository.save(gardenOfTheGods10Mile);
List<Race> races = raceRepository.findByDistanceBetween(20, 100);
assertThat(races.contains(pikesPeakAscent), is(true));
assertThat(races.contains(pikesPeakMarathon), is(true));
races = raceRepository.findByDistanceBetween(10, 19);
assertThat(races.contains(pikesPeakAscent), is(false));
assertThat(races.contains(pikesPeakMarathon), is(false));
}
@Test
public void testRaceByName() {
pikesPeakAscent = raceRepository.save(pikesPeakAscent);
pikesPeakMarathon = raceRepository.save(pikesPeakMarathon);
summerRoundUp = raceRepository.save(summerRoundUp);
gardenOfTheGods10Mile = raceRepository.save(gardenOfTheGods10Mile);
List<Race> races = raceRepository.findByName("Summer Round Up");
assertThat(races.contains(pikesPeakAscent), is(false));
assertThat(races.contains(pikesPeakMarathon), is(false));
assertThat(races.contains(summerRoundUp), is(true));
}
@Test
public void testInsertParticipant() {
one = participantRepository.save(one);
two = participantRepository.save(two);
three = participantRepository.save(three);
assertNotNull(one.getUuid());
assertNotNull(two.getUuid());
assertNotNull(three.getUuid());
assertNotEquals(one.getUuid(), two.getUuid());
assertNotEquals(two.getUuid(), three.getUuid());
assertThat(participantRepository.findAll().size(), is(3));
List<Participant> twentySomethings = participantRepository.findByAgeLessThan(40);
for (Participant participant : twentySomethings) {
System.err.println(participant.getUuid());
}
System.err.println(one.getUuid());
System.err.println(two.getUuid());
System.err.println(three.getUuid());
assertThat(twentySomethings.contains(one), is(true));
}
@Test
public void testFindByAgeLessThan() {
one = participantRepository.save(one);
two = participantRepository.save(two);
three = participantRepository.save(three);
List<Participant> twentySomethings = participantRepository.findByAgeLessThan(40);
assertThat(twentySomethings.contains(one), is(true));
assertThat(twentySomethings.contains(three), is(false));
}
@Test
public void testFindAgeBetween() {
one = participantRepository.save(one);
two = participantRepository.save(two);
three = participantRepository.save(three);
List<Participant> twentySomethings = participantRepository.findByAgeBetween(40, 70);
assertThat(twentySomethings.contains(one), is(false));
assertThat(twentySomethings.contains(three), is(true));
}
@Test
public void testFindByLastName() {
one = participantRepository.save(one);
two = participantRepository.save(two);
three = participantRepository.save(three);
List<Participant> theDoes = participantRepository.findByLastName("Doe");
assertThat(theDoes.contains(one), is(true));
assertThat(theDoes.contains(three), is(false));
}
@After
public void tearDown() {
participantRepository.deleteAll();
raceRepository.deleteAll();
}
}

View File

@@ -24,6 +24,7 @@
<module>jpa21</module>
<module>security</module>
<module>multiple-datasources</module>
<module>eclipselink</module>
</modules>
<dependencies>
@@ -45,4 +46,4 @@
</dependencies>
</project>
</project>