Guida a Ebean ORM

1. Introduzione

Ebean è uno strumento di mappatura relazionale a oggetti scritto in Java.

Supporta le annotazioni JPA standard per la dichiarazione di entità. Tuttavia, fornisce un'API molto più semplice per la persistenza. In effetti, uno dei punti che vale la pena menzionare dell'architettura Ebean è che è senza sessione, il che significa che non gestisce completamente le entità.

Oltre a ciò, include anche un'API di query e supporta la scrittura di query in SQL nativo. Ebean supporta tutti i principali fornitori di database come Oracle, Postgres, MySql, H2 ecc.

In questo tutorial, daremo uno sguardo a come possiamo creare, persistere e interrogare entità usando Ebean e H2.

2. Configurazione

Per iniziare, prendiamo le nostre dipendenze e alcune configurazioni di base.

2.1. Dipendenze di Maven

Prima di iniziare, importiamo le dipendenze richieste:

 io.ebean ebean 11.22.4   com.h2database h2 1.4.196   ch.qos.logback logback-classic 1.2.3 

Le ultime versioni di Ebean, H2 e Logback sono disponibili su Maven Central.

2.2. Miglioramenti

Ebean deve modificare i bean di entità in modo che possano essere gestiti dal server. Quindi, aggiungeremo un plugin Maven per fare quel lavoro:

 io.ebean ebean-maven-plugin 11.11.2   main process-classes  debug=1   enhance    

Dobbiamo anche fornire al plugin Maven i nomi dei pacchetti che contengono le entità e le classi che usano le transazioni. Per farlo creiamo il file ebean.mf:

entity-packages: com.baeldung.ebean.model transactional-packages: com.baeldung.ebean.app

2.3. Registrazione

Creiamo anche logback.xml e impostiamo i livelli di registrazione su alcuni pacchetti su TRACE in modo da poter vedere le istruzioni che vengono eseguite:

3. Configurazione di un server

Dobbiamo creare un'istanza EbeanServer per salvare entità o eseguire query su un database. Esistono due modi in cui è possibile creare un'istanza del server: utilizzando un file delle proprietà predefinito o eseguendolo a livello di programmazione.

3.1. Utilizzo di un file delle proprietà predefinito

Il file delle proprietà predefinito può essere di tipo properties o yaml . Ebean cercherà la configurazione nei file con i nomi application.properties , ebean.properties o application.yml .

Oltre a fornire i dettagli di connessione al database, possiamo anche istruire Ebean a creare ed eseguire istruzioni DDL.

Ora, diamo un'occhiata a una configurazione di esempio:

ebean.db.ddl.generate=true ebean.db.ddl.run=true datasource.db.username=sa datasource.db.password= datasource.db.databaseUrl=jdbc:h2:mem:customer datasource.db.databaseDriver=org.h2.Driver

3.2. Utilizzando ServerConfig

Successivamente, diamo un'occhiata a come possiamo creare lo stesso server a livello di programmazione utilizzando EbeanServerFactory e ServerConfig :

ServerConfig cfg = new ServerConfig(); Properties properties = new Properties(); properties.put("ebean.db.ddl.generate", "true"); properties.put("ebean.db.ddl.run", "true"); properties.put("datasource.db.username", "sa"); properties.put("datasource.db.password", ""); properties.put("datasource.db.databaseUrl","jdbc:h2:mem:app2"; properties.put("datasource.db.databaseDriver", "org.h2.Driver"); cfg.loadFromProperties(properties); EbeanServer server = EbeanServerFactory.create(cfg);

3.3. Istanza server predefinita

Una singola istanza EbeanServer viene mappata a un singolo database. A seconda delle nostre esigenze, potremmo creare anche più di un'istanza EbeanServer .

Se viene creata solo una singola istanza del server, per impostazione predefinita, viene registrata come istanza del server predefinita. È possibile accedervi ovunque nell'applicazione utilizzando un metodo statico sulla classe Ebean :

EbeanServer server = Ebean.getDefaultServer();

Nel caso in cui siano presenti più database, è possibile registrare una delle istanze del server come predefinita:

cfg.setDefaultServer(true);

4. Creazione di entità

Ebean fornisce il supporto completo per le annotazioni JPA e funzionalità aggiuntive utilizzando le proprie annotazioni.

Creiamo poche entità utilizzando sia annotazioni JPA che Ebean. Innanzitutto, creeremo un BaseModel che contiene proprietà comuni tra le entità :

@MappedSuperclass public abstract class BaseModel { @Id protected long id; @Version protected long version; @WhenCreated protected Instant createdOn; @WhenModified protected Instant modifiedOn; // getters and setters }

Qui abbiamo usato l' annotazione JPA MappedSuperClass per definire BaseModel. E due annotazioni Ebean io.ebean.annotation.WhenCreated e io.ebean.annotation.WhenModified per scopi di controllo.

Successivamente, creeremo due entità Customer e Address che estendono BaseModel :

@Entity public class Customer extends BaseModel { public Customer(String name, Address address) { super(); this.name = name; this.address = address; } private String name; @OneToOne(cascade = CascadeType.ALL) Address address; // getters and setters } 
@Entity public class Address extends BaseModel{ public Address(String addressLine1, String addressLine2, String city) { super(); this.addressLine1 = addressLine1; this.addressLine2 = addressLine2; this.city = city; } private String addressLine1; private String addressLine2; private String city; // getters and setters }

In Cliente , abbiamo definito una mappatura uno a uno con Indirizzo e aggiunto il tipo di cascata impostato su TUTTO in modo che anche le entità figlio vengano aggiornate insieme alle entità padre.

5. Operazioni di base CRUD

In precedenza abbiamo visto come configurare EbeanServer e creato due entità. Ora, eseguiamo alcune operazioni CRUD di base su di essi.

Useremo l'istanza del server predefinito per persistere e accedere ai dati. La classe Ebean fornisce anche metodi statici per persistere e accedere ai dati che inviano la richiesta all'istanza del server predefinita:

Address a1 = new Address("5, Wide Street", null, "New York"); Customer c1 = new Customer("John Wide", a1); EbeanServer server = Ebean.getDefaultServer(); server.save(c1); c1.setName("Jane Wide"); c1.setAddress(null); server.save(c1); Customer foundC1 = Ebean.find(Customer.class, c1.getId()); Ebean.delete(foundC1);

Innanzitutto, creiamo un oggetto Customer e utilizziamo l'istanza del server predefinito per salvarlo utilizzando save () .

Next, we're updating the customer details and saving it again using save().

Finally, we're using the static method find() on Ebean to fetch the customer and delete it using delete().

6. Queries

Query APIs can also be used to create an object graph with filters and predicates. We can either use Ebean or EbeanServer to create and execute queries.

Let's look at a query which finds a Customer by city and returns a Customer and Address object with only some fields populated:

Customer customer = Ebean.find(Customer.class) .select("name") .fetch("address", "city") .where() .eq("city", "San Jose") .findOne();

Here, with find() we indicate that we want to find entities of type Customer. Next, we use select() to specify the properties to populate in the Customer object.

Later, we use fetch() to indicate that we want to fetch the Address object belonging to the Customer and that we want to fetch the city field.

Finally, we add a predicate and restrict the size of the result to 1.

7. Transactions

Ebean executes each statement or query in a new transaction by default.

Although this may not be an issue in some cases. There are times when we may want to execute a set of statements within a single transaction.

In questi casi, se annotiamo il metodo con io.ebean.annotations.Transactional, tutte le istruzioni all'interno del metodo verranno eseguite all'interno della stessa transazione:

@Transactional public static void insertAndDeleteInsideTransaction() { Customer c1 = getCustomer(); EbeanServer server = Ebean.getDefaultServer(); server.save(c1); Customer foundC1 = server.find(Customer.class, c1.getId()); server.delete(foundC1); }

8. Creazione del progetto

Infine, possiamo costruire il progetto Maven usando il comando:

compile io.ebean:ebean-maven-plugin:enhance

9. Conclusione

Per riassumere, abbiamo esaminato le funzionalità di base di Ebean che possono essere utilizzate per persistere e interrogare entità in un database relazionale.

Infine, questo codice è disponibile su Github.