资讯专栏INFORMATION COLUMN

使用Java编程引导JPA

ymyang / 2249人阅读

摘要:从好的方面来说,只需使用普通的就可以在不使用文件的情况下引导实现。请注意,为简洁起见,我们省略了类案例结论在本文中,我们展示了如何使用的接口和的类的自定义实现以编程方式引导实体管理器,而不必依赖传统的文件。

案例概述

大多数JPA驱动的应用程序大量使用“persistence.xml”文件来获取JPA实现,例如Hibernate或OpenJPA。

我们的方法提供了一种集中式机制,用于配置一个或多个持久性单元 和相关的持久性上下文。

虽然这种方法本身并不是错误的,但它并不适用于需要多带带测试使用不同持久性单元的应用程序组件的用例。

从好的方面来说,只需使用普通的Java就可以在不使用“persistence.xml”文件的情况下引导JPA实现。

在本文中,我们将看到如何使用Hibernate完成此任务。

实现PersistenceUnitInfo接口

在典型的“基于xml”的JPA配置中,JPA实现自动负责实现PersistenceUnitInfo接口。

使用通过解析“persistence.xml”文件收集的所有数据,持久性提供程序使用此实现来创建实体管理器工厂。从这个工厂,我们可以获得一个实体。

由于我们不依赖于“persistence.xml”文件,我们需要做的第一件事就是提供我们自己的PersistenceUnitInfo实现。我们将Hibernate用于持久性提供程序:

public class HibernatePersistenceUnitInfo implements PersistenceUnitInfo {
     
    public static String JPA_VERSION = "2.1";
    private String persistenceUnitName;
    private PersistenceUnitTransactionType transactionType
      = PersistenceUnitTransactionType.RESOURCE_LOCAL;
    private List managedClassNames;
    private List mappingFileNames = new ArrayList<>();
    private Properties properties;
    private DataSource jtaDataSource;
    private DataSource nonjtaDataSource;
    private List transformers = new ArrayList<>();
     
    public HibernatePersistenceUnitInfo(
      String persistenceUnitName, List managedClassNames, Properties properties) {
        this.persistenceUnitName = persistenceUnitName;
        this.managedClassNames = managedClassNames;
        this.properties = properties;
    }
 
    // standard setters / getters   
}

简而言之,HibernatePersistenceUnitInfo类只是一个普通的数据容器,它存储绑定到特定持久性单元的配置参数。这包括持久性单元名称,管理实体类的名称,事务类型,JTA和非JTA数据源等。

使用Hibernate的EntityManagerFactoryBuilderImpl类创建实体管理器工厂

现在我们已经实现了自定义PersistenceUnitInfo实现,我们需要做的最后一件事就是获得一个实体管理器工厂。

Hibernate使用EntityManagerFactoryBuilderImpl类(构建器模式的简洁实现)使这个过程变得轻而易举。

为了提供更高级别的抽象,让我们创建一个包含EntityManagerFactoryBuilderImpl功能的类。

首先,让我们展示使用Hibernate的EntityManagerFactoryBuilderImpl类和 HibernatePersistenceUnitInf类创建实体管理器工厂和实体管理器的方法 :

public class JpaEntityManagerFactory {
    private String DB_URL = "jdbc:mysql://databaseurl";
    private String DB_USER_NAME = "username";
    private String DB_PASSWORD = "password";
    private Class[] entityClasses;
     
    public JpaEntityManagerFactory(Class[] entityClasses) {
        this.entityClasses = entityClasses;
    }
     
    public EntityManager getEntityManager() {
        return getEntityManagerFactory().createEntityManager();
    }
     
    protected EntityManagerFactory getEntityManagerFactory() {
        PersistenceUnitInfo persistenceUnitInfo = getPersistenceUnitInfo(
          getClass().getSimpleName());
        Map configuration = new HashMap<>();
        return new EntityManagerFactoryBuilderImpl(
          new PersistenceUnitInfoDescriptor(persistenceUnitInfo), configuration)
          .build();
    }
     
    protected HibernatePersistenceUnitInfo getPersistenceUnitInfo(String name) {
        return new HibernatePersistenceUnitInfo(name, getEntityClassNames(), getProperties());
    }
 
    // additional methods
}

接下来,让我们看一下提供EntityManagerFactoryBuilderImpl和HibernatePersistenceUnitInfo所需参数的方法 。

这些参数包括托管实体类,实体类的名称,Hibernate的配置属性和MysqlDataSource对象:

public class JpaEntityManagerFactory {
    //...
     
    protected List getEntityClassNames() {
        return Arrays.asList(getEntities())
          .stream()
          .map(Class::getName)
          .collect(Collectors.toList());
    }
     
    protected Properties getProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
        properties.put("hibernate.id.new_generator_mappings", false);
        properties.put("hibernate.connection.datasource", getMysqlDataSource());
        return properties;
    }
     
    protected Class[] getEntities() {
        return entityClasses;
    }
     
    protected DataSource getMysqlDataSource() {
        MysqlDataSource mysqlDataSource = new MysqlDataSource();
        mysqlDataSource.setURL(DB_URL);
        mysqlDataSource.setUser(DB_USER_NAME);
        mysqlDataSource.setPassword(DB_PASSWORD);
        return mysqlDataSource;
    }
}

为简单起见,我们在JpaEntityManagerFactory类中对数据库连接参数进行了硬编码。但是,在生产中,我们应该将它们存储在多带带的属性文件中。

此外,getMysqlDataSource()方法返回一个完全初始化的MysqlDataSource对象。

我们这样做只是为了让事情更容易理解。在一种更实际、松耦合的设计中,我们将使用EntityManagerFactoryBuilderImpl的withDataSource()方法注入数据源对象,而不是在类中创建它。

使用实体管理器执行CRUD操作

最后,让我们看看如何使用JpaEntityManagerFactory实例获取JPA实体管理器并执行CRUD操作。(请注意,为简洁起见,我们省略了User类):

public static void main(String[] args) {
    EntityManager entityManager = getJpaEntityManager();
    User user = entityManager.find(User.class, 1);
     
    entityManager.getTransaction().begin();
    user.setName("John");
    user.setEmail("john@domain.com");
    entityManager.merge(user);
    entityManager.getTransaction().commit();
     
    entityManager.getTransaction().begin();
    entityManager.persist(new User("Monica", "monica@domain.com"));
    entityManager.getTransaction().commit();
  
    // additional CRUD operations
}
 
private static class EntityManagerHolder {
    private static final EntityManager ENTITY_MANAGER = new JpaEntityManagerFactory(
      new Class[]{User.class})
      .getEntityManager();
}
 
public static EntityManager getJpaEntityManager() {
    return EntityManagerHolder.ENTITY_MANAGER;
}
案例结论

在本文中,我们展示了如何使用JPA的PersistenceUnitInfo接口和Hibernate的EntityManagerFactoryBuilderImpl类的自定义实现以编程方式引导JPA实体管理器,而不必依赖传统的“persistence.xml”文件。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/73187.html

相关文章

  • Java中的DAO模式

    摘要:此的功能是从应用程序中隐藏在底层存储机制中执行操作所涉及的所有复杂性。这正是模式试图解决的问题。将模式与一起使用开发人员普遍认为的发布将模式的功能降级为零,因为该模式只是实体经理提供的另一层抽象和复杂性。在这种情况下,模式有其自己的位置。 案例概述 数据访问对象(DAO)模式是一种结构模式,它允许我们使用抽象API将应用程序/业务层与持久层(通常是关系数据库,但它可以是任何其他持久性机...

    TIGERB 评论0 收藏0
  • Spring Boot 2.1.0 已发布,7 个重大更新!

    摘要:距离重磅正式发布已经过去大半年了,而在月底就发布了,我们来看下都更新了什么,每一个技术人都值得关注。性能提升应用程序性能改进性能作为团队持续努力的一部分,性能提升在中取得了一些重大进展。 距离《重磅:Spring Boot 2.0 正式发布!》已经过去大半年了,而 Spring Boot 2.1.0 在 10 月底就发布了,我们来看下 Spring Boot 2.1.0 都更新了什么,...

    Forest10 评论0 收藏0
  • 几个数据持久化框架Hibernate、JPA、Mybatis、JOOQ和JDBC Template的

    摘要:不管是还是,表之间的连接查询,被映射为实体类之间的关联关系,这样,如果两个实体类之间没有实现关联关系,你就不能把两个实体或者表起来查询。 因为项目需要选择数据持久化框架,看了一下主要几个流行的和不流行的框架,对于复杂业务系统,最终的结论是,JOOQ是总体上最好的,可惜不是完全免费,最终选择JDBC Template。 Hibernate和Mybatis是使用最多的两个主流框架,而JOO...

    xietao3 评论0 收藏0
  • Day 17: 使用 JBoss Forge 和 OpenShift 构建部署 JAVA EE 6

    摘要:会警告该插件未签名。以上命令告诉创建一个名为的项目,使用包。的工具使从部署应用非常方便。域名构成了分配给应用的的一部分。这将为我们创建一个应用容器,自动配置和。同时将创建一个私有的仓库并克隆到本地。 编者注:我们发现了有趣的系列文章《30天学习30种新技术》,正在翻译,一天一篇更新,年终礼包。下面是第 17 天的内容。 今天的30天学习30种新技术挑战,我决定学习一下JBoss ...

    YacaToy 评论0 收藏0
  • 初探Kotlin+SpringBoot联合编程

    摘要:是一门最近比较流行的静态类型编程语言,而且和一样同属系。这个生成的构造函数是合成的,因此不能从或中直接调用,但可以使用反射调用。 showImg(https://segmentfault.com/img/remote/1460000012958496); Kotlin是一门最近比较流行的静态类型编程语言,而且和Groovy、Scala一样同属Java系。Kotlin具有的很多静态语言...

    xiaokai 评论0 收藏0

发表评论

0条评论

ymyang

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<