EntityManagerFactory 和 ApplicationContext 的使用

Far*_*kki 5 java configuration spring hibernate jpa

我想确保,由于我使用 @PersistenceContext,我不需要关闭任何连接,以避免泄漏和任何打开的连接以及性能不佳。所以我的 applicationContext.xml 如下所示(我在其中定义了实体管理器工厂等..)

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd">

<context:component-scan base-package="com.companyname.*" />

<tx:annotation-driven/>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceXmlLocation" value="classpath:com/urbanbuz/controller/persistence.xml" />
    <property name="persistenceUnitName" value="userPersistenceUnit" />
    <property name="dataSource" ref="dataSource" />
    <property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
    <property name="jpaDialect" ref="jpaDialect" />
</bean>

<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    <property name="database" value="MYSQL" />
    <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" />
    <property name="showSql" value="true"/>
</bean>

<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
    <property name="dataSource" ref="dataSource" />
    <property name="jpaDialect" ref="jpaDialect" />
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/ub" />
    <property name="username" value="root" />
    <property name="password" value="" />
</bean>
Run Code Online (Sandbox Code Playgroud)

我的持久化xml相应如下:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
version="1.0">
<persistence-unit name="userPersistenceUnit" transaction-type="RESOURCE_LOCAL" >
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 
    <class>com.urbanbuz.model.User</class>
    <class>com.urbanbuz.model.Account</class>
    <class>com.urbanbuz.model.AccountDetails</class>
    <class>com.urbanbuz.model.Posting</class>
    <class>com.urbanbuz.model.Journal</class>
</persistence-unit>
Run Code Online (Sandbox Code Playgroud)

现在,对于每个模型,我都有一个 DAO 和 Service 类,作为示例,我提供一个:

@Repository("accountDao")
@Transactional(propagation = Propagation.REQUIRED)
public class AccountDAO {
@PersistenceContext
private EntityManager entityManager;

public EntityManager getEntityManager() {
    return entityManager;
}

public void setEntityManager(EntityManager entityManager) {
    this.entityManager = entityManager;
}

// method inserts account into database
public void insert(Account account) {
    entityManager.persist(account);
}
}

@Service
public class AccountService {

private AccountDAO accountDAO;

public AccountDAO getAccountDao() {
    return accountDAO;
}

@Autowired
public void setAccountDao(AccountDAO accountDAO) {
    this.accountDAO = accountDAO;
}

public void addAccount(Account account) {
    getAccountDao().insert(account);
}
}
Run Code Online (Sandbox Code Playgroud)

因此,每当我需要访问数据库并执行任何操作时,我都会定义以下内容: ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml") ,然后定义上下文 EntityServiceEntityService = (EntityService) context.getBean("entityService") 并相应地调用需要的方法。我还需要进一步的特殊管理吗?

编辑:App.Java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/applicationContext.xml" })
public class App {
    public static void main(String[] args) {
     // here i just initialize an instance of the a component I have
     SignupComponent sc = new SignupComponent();
     // some code
     sc.signUp();
    } 
}
Run Code Online (Sandbox Code Playgroud)

在组件中,我尝试自动装配实体,如下所示:

public class SignupComponent {
    @Autowired
    EntityService entityService;

    //using it as follows for example: entityService.getEntity(entity_id);
}
Run Code Online (Sandbox Code Playgroud)

Vla*_*cea 2

您定义了注释:驱动两次:

<tx:annotation-driven/>
Run Code Online (Sandbox Code Playgroud)

<tx:annotation-driven transaction-manager="transactionManager" />
Run Code Online (Sandbox Code Playgroud)

两者都在做同样的事情,因为transactionManager无论如何都会调用默认事务管理器。

您的设置很好,Spring 事务管理器和 Hibernate 连接提供程序正在负责打开和关闭连接。

您需要解决的唯一问题是:

  1. 正确初始化 Spring 应用程序上下文。

    • 如果您有网络应用程序,则只需设置 WebApplicationinitializer即可
    • 如果这是一个独立的应用程序,您需要在引导加载类中初始化上下文。
    • 如果是测试,则使用Spring JUnit Runner,它代表您初始化上下文(并且可以在测试中重用它)
  2. 使用 @Autowired 注入依赖项

    代替:

    EntityService entityService = (EntityService) context.getBean("entityService");
    
    Run Code Online (Sandbox Code Playgroud)

    你应该有:

    @Autowired
    private EntityService entityService;
    
    public void callService() {
         entityService.call();
    }
    
    Run Code Online (Sandbox Code Playgroud)

更新

现在我看到了您的 App 类,这就是您需要做的:

  1. 删除用于测试的测试运行器配置:

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = { "/applicationContext.xml" })
    
    Run Code Online (Sandbox Code Playgroud)
  2. 增强你的背景:

    public static void main(String args[]) {
        AbstractApplicationContext context = new ClassPathXmlApplicationContext("/applicationContext.xml");
        context.registerShutdownHook();
        EntityService entityService = (EntityService) context.getBean("entityService");
    }
    
    Run Code Online (Sandbox Code Playgroud)