1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/hexagonframework-spring-data-ebean

Клонировать/Скачать
README.md 15 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 26.11.2024 23:55 5b08df1

Spring Data Ebean

Ebean — реализация Spring Data.

Build Status Gitter chat GitHub release License

MAVEN Central Link

简体中文

Основная цель проекта Spring Data — упростить создание приложений на базе Spring, использующих технологии доступа к данным. Этот модуль предоставляет расширенную поддержку слоёв доступа к данным на основе Ebean ORM.

Возможности

  • Реализация Ebean CRUD-методов для JPA-сущностей;
  • Динамическое формирование запросов на основе имён методов и аннотаций;
  • Поддержка сервиса канала запросов;
  • Прозрачное инициирование запросов Ebean с помощью методов запросов;
  • Реализация базовых классов домена, предоставляющих основные свойства;
  • Поддержка прозрачного аудита (создания, последнего изменения);
  • Возможность интеграции пользовательского кода репозитория;
  • Простая интеграция Spring с пользовательским пространством имён.

Реализованные сценарии

  1. Извлечение отдельной сущности на основе первичного ключа;
  2. Извлечение списка сущностей на основе условия;
  3. Сохранение новой отдельной сущности и возврат первичного ключа;
  4. Пакетная вставка нескольких сущностей одного типа и возврат сгенерированных ключей;
  5. Обновление существующей сущности — обновление всех полей сущности одновременно;
  6. Извлечение связи «многие к одному» (компания для отдела);
  7. Извлечение связи «один ко многим» (отделы для компании);
  8. Обновление сущностей в отношении «один ко многим» — добавление двух элементов, обновление двух элементов и удаление одного элемента — всё сразу;
  9. Сложный выбор — построение выбора, где условия основаны на некоторых логических условиях + добавление JOINs;
  10. Выполнение запроса с использованием простого оператора JDBC Statement (не PreparedStatement);
  11. Удаление отдельной сущности на основе первичного ключа.

Почему выбирают Ebean ORM

Условия для рассмотрения фреймворков:

  1. Фреймворк должен использовать, а не скрывать SQL-язык и СУБД, которую мы используем;
  2. Фреймворк может реализовать DDD;
  3. Может использовать аннотации JPA, но не должен быть полной реализацией JPA;
  4. Фреймворк должен быть достаточно зрелым для использования на «корпоративном уровне».

Субъективные плюсы и минусы каждого фреймворка

Ссылка: java-persistence-frameworks-comparison

Hibernate/JPA

JDBC Template

  • Плюсы
    • Чувствуется, что вы очень близки к самому JDBC;
    • Реализованы все сценарии без больших проблем — не было скрытых сюрпризов;
    • Очень простые пакетные операции;
    • Лёгкая настройка.
  • Минусы
    • Методы в JDBCDataRepositoryImpl не очень читаемы — это потому, что вам приходится встраивать SQL в код Java. Было бы лучше, если бы Java поддерживала многострочные строки.
    • Ведение журнала отладки могло бы быть лучше.

jOOQ

  • Плюсы
    • Очень гибкий, очень легко писать новые запросы, код очень читаемый;
    • После настройки он очень прост в использовании, отлично подходит для простых запросов;
    • Отличный вывод логгера отладки.
  • Минусы
    • Платная лицензия для определённых баз данных — будет сложно убедить менеджеров, что оно того стоит :)
    • Не так хорошо подходит для больших запросов — лучше использовать собственный SQL (см. сценарий 9).
    • Странный синтаксис пакетных операций (если вы не используете UpdatableRecord). Но это не так уж важно...

MyBatis

  • Плюсы

    • Написание SQL-операторов в XML-файле сопоставления кажется хорошим — легко работать с параметрами.
  • Минусы

    • Довольно много файлов для одного DAO. Реализация, DAO/Repository и XXXMapper и XXXMapper.xml
  • Не удаётся выполнять пакетные и непакетные операции в одном SqlSession.

  • Слишком много файлов маппинга XML.

  • Невозможно реализовать DDD.

EBean

  • Преимущества:
    • Всё выглядит очень хорошо — все сценарии реализованы с помощью очень читаемого кода.
    • Очень простые пакетные операции (на самом деле это только вопрос использования правильного метода :)).
    • Хотя есть методы, которые делают операции CRUD и запросы очень простыми, всё ещё существуют способы выполнения простого SQL и даже способ получить базовый объект транзакции JDBC, который можно использовать для основных операций JDBC. Это действительно хорошо.
  • Недостатки:
    • Запрос DTO не поддерживает сопоставление XML.
    • Необходимость «улучшения» сущностей — это было довольно неожиданно для меня, но на самом деле речь идёт только о правильной настройке среды (плагин IDE и плагин Gradle), и тогда вам не придётся об этом думать.

Быстрый старт

Создайте проект Maven, рекомендуется использовать Spring Boot и spring-data-ebean-spring-boot для создания веб-проекта.

Примеры: spring-boot-data-ebean-samples.

  1. Создайте модальный объект как сущность таблицы, сущность SQL или DTO:

Сущность таблицы:

@Entity
@Getter
@Setter
public class User {
  @Id
  @GeneratedValue
  private Integer id;
  private String firstname;
  private String lastname;
  @Column(nullable = false, unique = true) private String emailAddress;
}

Сущность SQL:

@Entity
@Sql
@Getter
@Setter
public class UserInfo {
  private String firstName;
  private String lastName;
  private String emailAddress;
}

POJO DTO:

@Getter
@Setter
public class UserDTO {
  private String firstName;
  private String lastName;
  private String emailAddress;
}
  1. Создайте интерфейс репозитория:
public interface UserRepository extends EbeanRepository<User, Long> {
    @Query("where emailAddress = :emailAddress order by id desc")
    User findUserByEmailAddressEqualsOql(@Param("emailAddress") String emailAddress);

    @Query("select (firstname,lastname,address) fetch manager (lastname) where lastname = :lastname order by id desc")
    List<User> findByLastnameOql(@Param("lastname") String lastname);

    @Query(nativeQuery = true, value = "select * from user where email_address = :emailAddress order by id desc")
    User findUserByEmailAddressEquals(@Param("emailAddress") String emailAddress);

    @Query(nativeQuery = true, value = "select * from user where lastname = :lastname order by id desc")
    List<User> findUsersByLastnameEquals(@Param("lastname") String lastname);

    @Query(nativeQuery = true, value = "update user set email_address = :newEmail where email_address = :oldEmail")
    @Modifying
    int changeUserEmailAddress(@Param("oldEmail") String oldEmail, @Param("newEmail") String newEmail);

    @Query("delete from user where emailAddress = :emailAddress")
    @Modifying
    int deleteUserByEmailAddressOql(@Param("emailAddress") String emailAddress);

    @Query(nativeQuery = true, value = "delete from user where email_address = :emailAddress")
    @Modifying
    int deleteUserByEmailAddress(@Param("emailAddress") String emailAddress);

    @Query(name = "withManagerById")
    List<User> findByLastnameNamedOql(@Param("lastname") String lastname);
    
    List<User> findAllByEmailAddressAndLastname(@Param("emailAddress") String emailAddress, @Param("lastname") String lastname);
}
  1. Варианты создания конфигурации именованного запроса в XML при использовании именованного запроса:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ebean xmlns="http://ebean-orm.github.io/xml/ns/ebean">
    <entity class="org.springframework.data.ebean.sample.domain.User">
        <named-query name="withManagerById">
            <query>
                select (firstname,lastname,address)
                fetch manager (lastname)
                where lastname = :lastname order by id desc
            </query>
        </named-query>
        <raw-sql name="byEmailAddressEquals"> ```
repository.deleteUserByEmailAddressOql("yuanxuegui@163.com");
assertEquals(1, result12);

// test find one sql query
User result13 = repository.findUserByEmailAddressEquals("yuanxuegui@163.com");
assertNull(result13);
}

@Test
public void testFindByMethodName() {
    List<User> result1 = repository.findAllByEmailAddressAndFullNameLastName("yuanxuegui@163.com", "Yuan");
    assertEquals(1, result1.size());
    assertEquals("Yuan", result1.get(0).getFullName().getLastName());
    assertThat(result1, hasItem(user));
}

@Test
public void testFindByExample() {
    User u = new User();
    u.setEmailAddress("YUANXUEGUI");
    List<User> result1 = repository.findAll(Example.of(u, ExampleMatcher.matchingAll()
            .withIgnoreCase(true)
            .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)));
    assertEquals(1, result1.size());
    assertEquals("Yuan", result1.get(0).getFullName().getLastName());
    assertThat(result1, hasItem(user));

    List<User> result2 = repository.findAll(Example.of(u, ExampleMatcher.matchingAll()
            .withIgnoreCase(false)
            .withStringMatcher(ExampleMatcher.StringMatcher.EXACT)));
    assertEquals(0, result2.size());
}

@Test
public void testAuditable() {
    User u = repository.findUserByEmailAddressEqualsOql("yuanxuegui@163.com");
    assertEquals("test", u.getCreatedBy());
    assertEquals("test", u.getLastModifiedBy());
}

@Test
public void testDomainEvent() {
    user.changeEmail("yuanxuegui@126.com");
    repository.save(user);
    User u = repository.findOneByProperty("emailAddress", "yuanxuegui@126.com");
    assertNotNull(u);
    assertEquals("yuanxuegui@126.com", u.getEmailAddress());
}

QueryObject UserQuery

@Data
@IncludeFields("emailAddress,fullName(lastName,firstName),age")
public class UserQuery {
    @ExprParam(expr = ExprType.CONTAINS)
    private String emailAddress;

    @ExprParam(name = "age", expr = ExprType.GE)
    private int ageStart;

    @ExprParam(name = "age", expr = ExprType.LE)
    private int ageEnd;
}

EbeanQueryChannelServiceIntegrationTests.java

package org.springframework.data.ebean.querychannel;

import io.ebean.Query;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.HashMap;
import java.util.Map;

import static org.junit.Assert.assertEquals;

/**
 * @author Xuegui Yuan
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SampleConfig.class)
public class EbeanQueryChannelServiceIntegrationTests {
    // Test fixture
    User user;
    @Autowired
    private EbeanQueryChannelService ebeanQueryChannelService;
    @Autowired
    private UserRepository repository;

    @Before
    public void initUser() {
        repository.deleteAll();
        user = new User("QueryChannel", "Test", "testquerychannel@163.com");
        user.setAge(29);
        user = repository.save(user);
    }


    @Test
    public void createSqlQueryMappingColumns() {
        String sql1 = "select first_name, last_name, email_address from user where last_name= :lastName";
        String sql2 = "select first_name as firstName, last_name as lastName, email_address as emailAddress from user where last_name= :lastName";
        Map<String, String> columnsMapping = new HashMap<>();
        columnsMapping.put("first_name", "firstName");
        columnsMapping.put("last_name", "lastName");

        Query<UserInfo> query1 =

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/hexagonframework-spring-data-ebean.git
git@api.gitlife.ru:oschina-mirror/hexagonframework-spring-data-ebean.git
oschina-mirror
hexagonframework-spring-data-ebean
hexagonframework-spring-data-ebean
master