返回介绍

Introduction to EclipseLink

发布于 2025-02-22 22:20:08 字数 25771 浏览 0 评论 0 收藏 0

In this tutorial, we learn the basics of EclipseLink. We use Derby and Spring Boot in our examples. The projects are built with NetBeans.

EclipseLink is an open source Eclipse Persistence Services Project from the Eclipse Foundation. The software provides an extensible framework that allows Java developers to interact with various data services, including databases, web services, Object XML mapping, and Enterprise Information Systems. EclipseLink is based on the TopLink product from which Oracle contributed the source code to create the EclipseLink project. EclipseLink is the reference implementation of the Java Persistence API.

The Java Persistence API (JPA) is a Java application programming interface specification that describes the management of relational data in applications using Java. Java Persistence Query Language (JPQL) is a platform-independent object-oriented query language. It is a part of the JPA specification. JPQL is used to make queries against entities stored in a relational database. It is heavily inspired by SQL, and its queries resemble SQL queries in syntax, but operate against JPA entity objects rather than directly with database tables.

Entity is a Java class that is to be persisted with JPA. It must be decorated with the javax.persistence.Entity annotation. In addition, it must have the @Id annotation, which defines the unique ID of the primary key of the entity, and the @GeneratedValue , which defines strategies for generation of primary keys. The @Table annotation specifies the database table to which the entity is mapped.

The persistence.xml is a standard configuration file in JPA. It has to be included in the META-INF directory inside the JAR file that contains the entity beans. In this file we define persistence units which define a set of all entity classes that are managed by entity manager instances in an application. EntityManager is a class that manages the persistent state of entities.

Reading data

The first example is a Java command line program, which retrieves all rows from the Cars table. We create a new NetBeans Java Maven project.

pom.xml

<?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">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.zetcode</groupId>
  <artifactId>Persistence</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>
  
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>
  
  <dependencies>
    
    <dependency>
      <groupId>org.eclipse.persistence</groupId>
      <artifactId>eclipselink</artifactId>
      <version>2.5.2</version>
    </dependency>
    
    <dependency>
      <groupId>org.apache.derby</groupId>
      <artifactId>derbyclient</artifactId>
      <version>10.12.1.1</version>
    </dependency>

  </dependencies>
  
</project>

In the pom.xml file, we define two dependencies: eclipselink and derbyclient.

Creating persistence.xml file
Figure: Creating persistence.xml file

To create the persistence.xml , we righ-click on the project file, select New — Other, and choose the Persistence category. There is a Persistence unit option.

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" 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">
  <persistence-unit name="cars-pu" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <class>com.zetcode.Car</class>
    <properties>
      <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/>
      <property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527/testdb"/>
      <property name="javax.persistence.jdbc.user" value="app"/>
      <property name="javax.persistence.jdbc.password" value="app"/>
    
      <property name="javax.persistence.schema-generation.database.action"
            value="drop-and-create"/>
      <property name="javax.persistence.sql-load-script-source" value="META-INF/sql/data.sql"/>      

    </properties>
  </persistence-unit>
  
</persistence>

In the persistence.xml file we define a persistence unit named cars-pu . We define a persistence provider, which is a Derby database. For Java SE, EclipseLink does not support automatic discovery of entities; therefore, we have to specify them with the <class> tag.

<class>com.zetcode.Car</class>

Here we specify that the Car class is an entity.

<property name="javax.persistence.schema-generation.database.action"
      value="drop-and-create"/>

With this property set, EclipseLink will drop and create a database table. The Cars table is created from the provided metadata.

<property name="javax.persistence.sql-load-script-source" value="META-INF/sql/data.sql"/>     

Here we specify the SQL file, which fills the table with data.

The persistence.xml file
Figure: The persistence.xml file

The persistence.xml file is located in the META-INF subdirectory

data.sql

INSERT INTO CARS(Name, Price) VALUES('Audi', 52642);
INSERT INTO CARS(Name, Price) VALUES('Mercedes', 57127);
INSERT INTO CARS(Name, Price) VALUES('Skoda', 9000);
INSERT INTO CARS(Name, Price) VALUES('Volvo', 29000);
INSERT INTO CARS(Name, Price) VALUES('Bentley', 350000);
INSERT INTO CARS(Name, Price) VALUES('Citroen', 21000);
INSERT INTO CARS(Name, Price) VALUES('Hummer', 41400);
INSERT INTO CARS(Name, Price) VALUES('Volkswagen', 21600);

This is the SQL to fill the Cars table with eight rows.

Car.java

package com.zetcode;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="Cars")
public class Car implements Serializable {
  
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long Id;
  private String name;
  private int price;

  public Long getId() {
    return Id;
  }

  public void setId(Long Id) {
    this.Id = Id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getPrice() {
    return price;
  }

  public void setPrice(int price) {
    this.price = price;
  }
}

This is our entity class. It is decorated with the @Entity annotation.

@Table(name="Cars")

The @Table annotation refers to the Cars table in the Derby database.

DBClient.java

package com.zetcode;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;

public class DBClient {

  public static void main(String[] args) {

    EntityManagerFactory emf = Persistence.createEntityManagerFactory("cars-pu");
    EntityManager eman = emf.createEntityManager();

    try {

      String sql = "SELECT c FROM Car c";

      Query query = eman.createQuery(sql);
      List<Car> cars = query.getResultList();

      for (Car car : cars) {
        System.out.printf("%d ", car.getId());
        System.out.printf("%s ", car.getName());
        System.out.println(car.getPrice());
      }
      
    } finally {

      eman.close();
      emf.close();
    }
  }
}

This is a Java console application, which retrieves all rows from the Cars table with the help of the entity manager.

EntityManagerFactory emf = Persistence.createEntityManagerFactory("cars-pu");

When using a JPA provider like EclipseLink outside JEE containers, we have to create an entity manager via the EntityManagerFactory . The factory is created with the Persistence.createEntityManagerFactory() method, taking the persistence unit name as a parameter.

EntityManager eman = emf.createEntityManager();

From the EntityManagerFactory , we create an EntityManager with the createEntityManager() method. The created EntityManager is an application-managed entity manager.

String sql = "SELECT c FROM Car c";

This looks like SQL code but it is not. It is an example of a Java Persistence Query Language (JPQL) statement. It returns all Car entities from the database table.

Query query = eman.createQuery(sql);

A Query object is created with the createQuery() method.

List<Car> cars = query.getResultList();

From the query object, we get the list of Car objects.

} finally {

  eman.close();
  emf.close();
}

For application-managed entity managers, we have to explicitly close the resources.

1 Audi 52642
2 Mercedes 57127
3 Skoda 9000
4 Volvo 29000
5 Bentley 350000
6 Citroen 21000
7 Hummer 41400
8 Volkswagen 21600

After we start Derby, build the application, and execute it, we get this output.

Saving a new row

In the second example, we save a new car object into the database. The pom.xml , persistence.xml , Car.java are identical to those used in the previous example.

DBClient2.java

package com.zetcode;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class DBClient2 {

  public static void main(String[] args) {

    EntityManagerFactory efact = Persistence.createEntityManagerFactory("cars-pu");
    EntityManager eman = efact.createEntityManager();

    try {

      eman.getTransaction().begin();

      Car car = new Car();
      car.setName("Toyota");
      car.setPrice(26700);

      eman.persist(car);
      eman.getTransaction().commit();
      
    } finally {
      
      eman.close();
      efact.close();
    }
  }
}

The example creates a new car object and saves it in the database.

eman.getTransaction().begin();

Automatic transaction management is not available outside JEE container; therefore, we have to manually create a new transaction.

Car car = new Car();
car.setName("Toyota");
car.setPrice(26700);

A new car entity is created. The ID will be generated by Derby.

eman.persist(car);

The persist() method saves the entity into the database.

eman.getTransaction().commit();

The transaction is committed.

Spring Boot example

In this example, we integrate EclipseLink in a Spring Boot application. Spring is a popular Java application framework. Spring Boot is a Spring's solution to create stand-alone, production-grade Spring based applications. It is a new solution to create Spring applications with minimal effort.

The sources for the following example are also available on author's Github repository .

Spring Boot project
Figure: Spring Boot project

This is the Spring Boot project in NetBeans.

pom.xml

<?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">
  
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.zetcode</groupId>
  <artifactId>SpringBootEclipseLink</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>
  
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.3.5.RELEASE</version>
    <relativePath />
  </parent>  
  
  <dependencies>
    
    <dependency>
      <groupId>org.eclipse.persistence</groupId>
      <artifactId>eclipselink</artifactId>
      <version>2.5.2</version>
    </dependency>
   
    <dependency>
      <groupId>org.apache.derby</groupId>
      <artifactId>derbyclient</artifactId>
      <version>10.12.1.1</version>
    </dependency>    
    
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
      <exclusions>
        <exclusion>
          <artifactId>hibernate-entitymanager</artifactId>
          <groupId>org.hibernate</groupId>
        </exclusion>
      </exclusions>
    </dependency>         
                       
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
      <groupId>org.eclipse.persistence</groupId>
      <artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId>
      <version>2.5.2</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
  <name>SpringBootEclipseLink</name>      
</project>

This is the Maven project file. We have dependencies for EclipseLink, Derby, and Spring Boot.

application.properties

# Derby
spring.datasource.driverClassName=org.apache.derby.jdbc.ClientDriver
spring.datasource.url=jdbc:derby://localhost:1527/testdb
spring.datasource.username=app
spring.datasource.password=app

In the application.properties file, we define the datasource for Derby.

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" 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">
  
  <persistence-unit name="cars-pu" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <class>com.zetcom.Car</class>     
    <properties>
      <property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527/testdb"/>
      <property name="javax.persistence.jdbc.user" value="app"/>
      <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/>
      <property name="javax.persistence.jdbc.password" value="app"/>
      <property name="javax.persistence.schema-generation.database.action"
            value="drop-and-create"/>
      <property name="javax.persistence.sql-load-script-source" value="META-INF/sql/data.sql"/>     
    </properties>
  </persistence-unit>
  
</persistence>

In the persistence.xml file, we create a persistence unit. It is called cars-pu . We also let the EclipseLink create a database table for us.

data.sql

INSERT INTO CARS(Name, Price) VALUES('Audi', 52642)
INSERT INTO CARS(Name, Price) VALUES('Mercedes', 57127)
INSERT INTO CARS(Name, Price) VALUES('Skoda', 9000)
INSERT INTO CARS(Name, Price) VALUES('Volvo', 29000)
INSERT INTO CARS(Name, Price) VALUES('Bentley', 350000)
INSERT INTO CARS(Name, Price) VALUES('Citroen', 21000)
INSERT INTO CARS(Name, Price) VALUES('Hummer', 41400)
INSERT INTO CARS(Name, Price) VALUES('Volkswagen', 21600)

EclipseLink will use this SQL file to fill the automatically created table with data.

AppConf.java

package com.zetcode.conf;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConf {

  @Bean
  public EntityManager entityManager(EntityManagerFactory entityManagerFactory) {
    return entityManagerFactory.createEntityManager();
  }
  
  @Bean
  public EntityManagerFactory createEntityManagerFactory() {
    return Persistence.createEntityManagerFactory("cars-pu");
  }
}

Two beans are created in AppConf : EntityManagerFactory and EntityManager . The EntityManager will be injected into the CarsServiceImpl .

Car.java

package com.zetcode.bean;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;

@Entity
@Table(name="Cars")
@NamedQueries({
  @NamedQuery(name = "Car.findAll", query = "SELECT c FROM Car c"),
  @NamedQuery(name = "Car.findByName", query = "SELECT c FROM Car c WHERE c.name = :name")
})
public class Car {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long Id;
  private String name;
  private int price;

  public Long getId() {
    return Id;
  }

  public void setId(Long Id) {
    this.Id = Id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getPrice() {
    return price;
  }

  public void setPrice(int price) {
    this.price = price;
  }
}

This is our Entity bean.

@NamedQueries({
  @NamedQuery(name = "Car.findAll", query = "SELECT c FROM Car c"),
  @NamedQuery(name = "Car.findByName", query = "SELECT c FROM Car c WHERE c.name = :name")
})

The class is annotated with named queries, which are JPQL statements for retrieving all car objects and finding a car by its name.

CarsService.java

package com.zetcode.service;

import com.zetcode.bean.Car;
import java.util.List;

public interface CarsService {

  public void saveCar(Car car);
  public Car findCarByName(String name);
  public List<Car> findAll();
}

In the CarsService interface, we define the contract methods for accessing the database via entity manager.

CarsServiceImpl.java

package com.zetcode.service;

import com.zetcode.bean.Car;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.springframework.stereotype.Component;

@Component
public class CarsServiceImpl implements CarsService {

  @PersistenceContext
  EntityManager em;

  @Override
  public void saveCar(Car car) {

    em.getTransaction().begin();
    em.persist(car);
    em.getTransaction().commit();
  }

  @Override
  public Car findCarByName(String name) {

    Query query = em.createNamedQuery("Car.findByName");

    query.setParameter("name", name);
    Car car = (Car) query.getSingleResult();

    return car;
  }

  @Override
  public List<Car> findAll() {

    Query query = em.createNamedQuery("Car.findAll");
    
    List<Car> cars = query.getResultList();

    return cars;
  }
}

The CarsServiceImpl is a business service class which implements the methods for saving a car, finding a car by its name, and retrieving all cars from a database.

@PersistenceContext
EntityManager em;

The EntityManager is injected into the class with the @PersistenceContext annotation.

@Override
public void saveCar(Car car) {

  em.getTransaction().begin();
  em.persist(car);
  em.getTransaction().commit();
}

The saveCar() method saves a car into the database with the EntityManager's persist() method. The persist() method is placed inside the manually created transaction.

@Override
public Car findCarByName(String name) {

  Query query = em.createNamedQuery("Car.findByName");

  query.setParameter("name", name);
  Car car = (Car) query.getSingleResult();

  return car;
}

The findCarByName() method finds a car by its name. The createNamedQuery() creates a named query; it refers to the named query defined in the Car entity class. A parameter is set to the named query with the setParameter() method.

@Override
public List<Car> findAll() {

  Query query = em.createNamedQuery("Car.findAll");
  
  List<Car> cars = query.getResultList();

  return cars;
}

A named query Car.findAll is created. The getResultList() of the query returns a list of retrieved cars.

MyRunner.java

package com.zetcode.client;

import com.zetcode.bean.Car;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.stereotype.Component;
import com.zetcode.service.CarsService;

@Component
public class MyRunner implements CommandLineRunner {

  @Autowired
  private CarsService crs;

  @Override
  public void run(String... args) throws Exception {
    
    try {
      Car car = crs.findCarByName("Citroen");
      System.out.printf("ID: %d%n", car.getId());
      System.out.printf("Name: %s%n", car.getName());
      System.out.printf("Price: %d%n", car.getPrice());
      
    } catch (EmptyResultDataAccessException e) {
      System.out.println("Car was not found");
    }

    List<Car> cars = crs.findAll();
    
    for (Car car: cars) {
      System.out.printf("%d ", car.getId());
      System.out.printf("%s ", car.getName());
      System.out.println(car.getPrice());
    }
  }
}

The MyRunner is a command line runner for the Spring Boot CLI application. We look for a Citroen car and retrieve all cars from the database.

@Autowired
private CarsService crs;

The CarsService bean is injected into the MyRunner class.

Car car = crs.findCarByName("Citroen");

The service's findCarByName() looks for a car named Citroen.

List<Car> cars = crs.findAll();

The service's findAll() method retrieves all cars from the database.

SpringDBCLIApp.java

package com.zetcode.client;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;

@EnableAutoConfiguration
@ComponentScan(basePackages="com.zetcode")
public class SpringDBCLIApp {

  public static void main(String[] args) {

    SpringApplication.run(SpringDBCLIApp.class, args);
  }
}

The SpringDBCLIApp sets up the Spring Boot CLI application.

In this tutorial, we have presented the EclipseLink JPA provider. ZetCode has the following related tutorials: Spring JdbcTemplate tutorial , Java tutorial , and Introduction to EJBs .

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文