• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

spring-data-ebean: 超简单、超强大的ORM框架,OQL、SQL、ES多查询引擎,超越JPA、Hib ...

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称:

spring-data-ebean

开源软件地址:

https://gitee.com/hexagonframework/spring-data-ebean

开源软件介绍:

spring-data-ebean

Ebean implementation for spring data.

Build Status Gitter chatGitHub releaseLicense

MAVEN中央仓库链接

[QQ群: 635113788]

Spring Data项目的主要目标是使构建使用DDD仓储接口与实现的Spring应用程序变得更加容易。此模块是基于Ebean ORM(轻量级JPA)的仓储层实现。通过使用此模块,你可以在基于Ebean ORM下使用Spring Data模式带来的便利性。如果你还没有接触过Spring DataEbean ORM,建议先了解下该项目。

支持的一些特性

  • 对标准Entity支持完整CRUD操作,包括常用的查询操作
  • 支持通过接口中的注解生成对应的查询(orm查询、sql查询、命名orm查询、命名sql查询、dto查询)
  • 支持通过接口中的方法名生成对应的查询
  • 支持QueryChannel服务,用于CQRS
  • 提供基础属性的实体基类和面向领域编程DDD基类
  • 原生支持使用注解实现审计(如创建人、创建时间、修改人、最后修改时间)
  • 支持自定义编写基于Ebean的查询,方便而不失灵活性
  • 方便的与Spring集成
  • 支持MySQL、Oracle、SQL Server、H2、PostgreSQL等数据库

实现的场景

  1. 基于主键获取单个实体
  2. 根据条件获取实体的列表
  3. 保存新的单个实体并返回主键
  4. 批量插入相同类型的多个实体并返回生成的主键列表
  5. 更新单个现有实体——同时更新所有的实体字段
  6. 获取多对一关系(部门的所属公司)
  7. 获取一对多关系(公司的部门)
  8. 更新实体一对多的关系(公司的部门)-增加两个项目,更新两个项目和删除一个项目-所有只需一句代码/一次操作
  9. 复杂的选择-构造选择的条件基于一些布尔条件+加入一些连接
  10. 使用JDBC简单语句(非PreparedStatement)执行查询
  11. 基于主键移除单个实体

为什么选择Ebean ORM

基于JPA注解的轻量级ORM实现,支持Mybatis不支持的实体关联,但相比Hibernate/JPA具有Mybatis的查询灵活性,支持查询partial objects。对于实现领域模型仓储接口的聚合根实体保存(保存聚合根实体同时保存聚合根上的关联实体、值对象)和partial objects等技术要求,Ebean都非常适用。

我选择关系型数据持久化框架的基本原则:

  1. 拥抱SQL而非隐藏
  2. 可以实现面向领域编程
  3. 可以利用JPA注解,但不能是JPA的完整实现(这点我偏向于Ebean)
  4. 足够成熟以应对企业级应用(Ebean和Hibernate同时期作品,资格老,而且持续更新以满足更高需求)

框架优缺点比较

参考:java-persistence-frameworks-comparison

Hibernate/JPA

JDBC Template

  • 优点
    • 感觉自己非常接近JDBC本身
    • 实现了所有的场景而没有更大的问题-没有隐藏的惊喜
    • 非常容易的批量操作
    • 设置简单
  • 缺点
    • 在Java代码中内联SQL使得实现仓储接口的可读性不强。如果Java支持多行字符串,那就更好了
    • 调试日志可以更好

jOOQ

  • 优点
    • 非常流畅,很容易编写新的查询,代码非常易读
    • 一旦设置好,就很容易使用,非常适合简单的查询
    • 很棒的日志记录器调试输出
  • 缺点
    • 某些数据库的付费许可证——很难说服经理们相信它是值得的:)
    • 对于大的查询来说没有那么多的实用性——最好使用原生SQL(参见场景9)
    • 批量操作的怪异语法(如果您不使用UpdatableRecord)。但这没什么大不了的……

MyBatis

  • 优点
    • 在XML映射文件里写SQL语句很爽
  • 缺点
    • 实现一个DAO、仓储要写很多文件(DAO/Repository、XXXMapper、XXXMapper.xml),方法多了比较繁琐
    • 无法在一个方法里做批处理,无法级联加载
    • 即使是简单的CRUD,都显得繁琐,导致存在各种弥补mybatis这一缺陷的第三方封装框架
    • 无法面向对象,无法实现DDD

EBean

  • 优点
    • 所有场景都实现非常完美,代码可读性高
    • 实现批处理超级简单
    • ORM查询、sql查询、DTO查询都非常简单
  • 缺点
    • DTO查询功能较新,有待增加XML mapping对DTO的支持
    • 必须“增强”实体,但实际上它基本上只是关于环境的设置(IDE插件和Gradle插件),然后你就不用去想它了。

快速开始

建立maven项目,建议使用spring boot和spring-data-ebean-spring-boot建立web项目

实例:spring-boot-data-ebean-samples

1、创建一个表格实体类或SQL实体类或DTO类:

表格实体:

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

SQL实体:

Sql实体:

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

POJO DTO:

@Getter@Setterpublic class UserDTO {  private String firstName;  private String lastName;  private String emailAddress;}

2、创建一个仓储接口

public interface UserRepository extends EbeanRepository<User, Long> {    @Query("where emailAddress = :emailAddress order by id desc")    User findUserByEmailAddressEqualsOql(@Param("emailAddress") String emailAddress);    /**     *  select fetch query细粒度控制查询字段     */    @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);    /**     * 命名ORM/SQL查询      */    @Query(name = "withManagerById")    List<User> findByLastnameNamedOql(@Param("lastname") String lastname);        List<User> findAllByEmailAddressAndLastname(@Param("emailAddress") String emailAddress, @Param("lastname") String lastname);}

3、 对于使用到的命名sql查询、命名orm查询,编写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">            <query>                select * from user                where email_address = :emailAddress                order by id desc            </query>        </raw-sql>    </entity>    <entity class="org.springframework.data.ebean.sample.domain.UserInfo">        <raw-sql name="userInfo">            <query>                select first_name, last_name, email_address from user            </query>        </raw-sql>        <raw-sql name="userInfoByEmail">            <query>                select first_name, last_name, email_address from user                where email_address = :emailAddress                order by id desc            </query>        </raw-sql>    </entity></ebean>

4、 编写你的使用代码:

UserRepositoryIntegrationTests.java

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(classes = SampleConfig.class)public class UserRepositoryIntegrationTests {    @Autowired    UserRepository repository;    @Test    public void sampleTestCase() {        User user = new User("Xuegui", "Yuan", "[email protected]");        user.setAge(29);        user = repository.save(user);        List<User> result1 = (List<User>) repository.findAll();        result1.forEach(it -> System.out.println(it));        assertEquals(1, result1.size());        assertEquals("Yuan", result1.get(0).getLastname());        assertThat(result1, hasItem(user));        List<User> result2  = repository.findByLastnameOql("Yuan");        assertEquals(1, result2.size());        assertEquals("Yuan", result2.get(0).getLastname());        assertThat(result2, hasItem(user));        List<User> result3 = repository.findUsersByLastnameEquals("Yuan");        assertEquals(1, result3.size());        assertEquals("Yuan", result3.get(0).getLastname());        User result4 = repository.findUserByEmailAddressEqualsOql("[email protected]");        assertEquals("[email protected]", result4.getEmailAddress());        User result5 = repository.findUserByEmailAddressEquals("[email protected]");        assertEquals("[email protected]", result5.getEmailAddress());        int result6 = repository.changeUserEmailAddress("[email protected]", "[email protected]");        assertEquals(1, result6);        List<User> result7  = repository.findByLastnameOql("Yuan");        assertEquals("[email protected]", result7.get(0).getEmailAddress());        int result8 = repository.deleteUserByEmailAddress("[email protected]");        assertEquals(1, result8);        User result9 = repository.findUserByEmailAddressEquals("[email protected]");        assertNull(result9);        user = new User("Xuegui", "Yuan", "[email protected]");        user.setAge(29);        user = repository.save(user);        User result10 = repository.findUserByEmailAddressEquals("[email protected]");        assertNotNull(result10);        int result11 = repository.deleteUserByEmailAddressOql("[email protected]");        assertEquals(1, result11);        User result12 = repository.findUserByEmailAddressEquals("[email protected]");        assertNull(result12);    }    @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).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());    }}

查询对象 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.data.ebean.sample.config.SampleConfig;import org.springframework.data.ebean.sample.domain.User;import org.springframework.data.ebean.sample.domain.UserInfo;import org.springframework.data.ebean.sample.domain.UserRepository;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", "[email protected]");        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 = ebeanQueryChannelService.createSqlQuery(UserInfo.class,                sql1);        Query<UserInfo> query2 = ebeanQueryChannelService.createSqlQuery(UserInfo.class,                sql2);        Query<UserInfo> query3 = ebeanQueryChannelService.createSqlQueryMappingColumns(UserInfo.class,                sql1, columnsMapping);        query1.setParameter("lastName", "Test");        query2.setParameter("lastName", "Test");        query3.setParameter("lastName", "Test");        UserInfo userInfo1 = query1.findOne();        UserInfo userInfo2 = query2.findOne();        UserInfo userInfo3 = query3.findOne();        assertEquals("QueryChannel", userInfo1.getFirstName());        assertEquals("[email protected]", userInfo1.getEmailAddress());        assertEquals("QueryChannel", userInfo2.getFirstName());        assertEquals("[email protected]", userInfo2.getEmailAddress());        assertEquals("QueryChannel", userInfo3.getFirstName());        assertEquals("[email protected]", userInfo3.getEmailAddress());    }    @Test    public void createNamedQuery() {        UserInfo userInfo = ebeanQueryChannelService.createNamedQuery(UserInfo.class,                "userInfoByEmail").setParameter("emailAddress",                "[email protected]").findOne();        assertEquals("QueryChannel", userInfo.getFirstName());        assertEquals("[email protected]", userInfo.getEmailAddress());    }    @Test    public void createNamedQueryWhere() {        UserInfo userInfo = ebeanQueryChannelService.createNamedQuery(UserInfo.class,                "userInfo").where()                .eq("emailAddress", "[email protected]").findOne();        assertEquals("QueryChannel", userInfo.getFirstName());        assertEquals("[email protected]", userInfo.getEmailAddress());    }    @Test    public void createDtoQuery() {        String sql = "select first_name, last_name, email_address from user where email_address = :emailAddress";        UserDTO userDTO = ebeanQueryChannelService.createDtoQuery(UserDTO.class, sql)                .setParameter("emailAddress", "[email protected]")                .findOne();        assertEquals("QueryChannel", userDTO.getFirstName());        assertEquals("[email protected]", userDTO.getEmailAddress());    }        @Test    public void query_queryObject() {        UserQuery userQuery = new UserQuery();        userQuery.setEmailAddress("[email protected]");        userQuery.setAgeStart(1);        userQuery.setAgeEnd(30);        UserDTO user = queryChannel.createQuery(User.class, userQuery)                .asDto(UserDTO.class)                .setRelaxedMode()                .findOne();        assertEquals("[email protected]", user.getEmailAddress());    }        @Test    public void applyQueryObject() {        UserQuery userQuery = new UserQuery();        userQuery.setEmailAddress("[email protected]");        userQuery.setAgeStart(1);        userQuery.setAgeEnd(30);        UserInfo userInfo = EbeanQueryChannelService.applyWhere(queryChannel.createNamedQuery(UserInfo.class,                "userInfo").where(), userQuery).findOne();        assertEquals("QueryChannel", userInfo.getFirstName());        assertEquals("[email protected]", userInfo.getEmailAddress());    }}

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap