EntityManagerFactory和ApplicationContext用法

时间:2014-12-28 13:25:30

标签: java spring hibernate jpa configuration

我想确保因为我使用的是@PersistenceContext,所以我不需要关闭任何连接,以避免泄漏和任何左开连接和性能不佳。 所以我的applicationContext.xml看起来如下(我定义了entitymanager工厂等。)

<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>

我的持久性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>

现在对于每个模型我都有一个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);
}
}

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

编辑: 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();
    } 
}

在组件中,我试图将实体自动装配:

public class SignupComponent {
    @Autowired
    EntityService entityService;

    //using it as follows for example: entityService.getEntity(entity_id);
}

2 个答案:

答案 0 :(得分:1)

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

<tx:annotation-driven/>

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

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

您的设置很好,Spring transaction manager and Hibernate connection providers负责打开和关闭连接。

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

  1. 正确初始化Spring Application Context。

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

    注入依赖项

    而不是:

    EntityService entityService = (EntityService) context.getBean("entityService");
    

    你应该:

    @Autowired
    private EntityService entityService;
    
    public void callService() {
         entityService.call();
    }
    
  3. 更新

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

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

      @RunWith(SpringJUnit4ClassRunner.class)
      @ContextConfiguration(locations = { "/applicationContext.xml" })
      
    2. 提升你的背景:

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

答案 1 :(得分:0)

让我看看我能否以普通弹簧设置的形式为您提供一些帮助。我使用了一些不同的库,但我认为您可以更好地了解如何设置Spring和Hibernate的配置......

就个人而言,我喜欢将所有单独的配置保存在不同的文件中。 ApplicationContext是主要配置,然后是数据,日志记录等等。这只是一个偏好,但它有助于保持清晰,因为Spring XML配置可以快速变得冗长。

  

应用程序上下文

的applicationContext.xml


    <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
                http://www.springframework.org/schema/mvc
                http://www.springframework.org/schema/mvc/spring-mvc.xsd">


    <!-- Configures the annotation-driven Spring MVC Controller programming model.
    Note that, with Spring 3.0, this tag works in Servlet MVC only!  -->
    <mvc:annotation-driven/>

    <!-- Activates various annotations to be detected in bean classes -->
    <context:annotation-config/>

    <!-- Scans the classpath for annotated components that will be auto-registered as Spring beans.
     For example @Controller and @Service. Make sure to set the correct base-package -->
    <context:component-scan base-package="com.farah"/>

    <mvc:resources mapping="/resources/**" location="/resources/"/>

    <!-- Imports datasource configuration -->
    <import resource="spring-data.xml"/>  

</beans>

请注意,我使用 Spring-Data-JPA ,这是一个来自Spring的优秀库,它为您提供了许多特性和功能,而无需再次编写所有必需的样板代码。

  

数据配置

弹簧data.xml中

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

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

    <context:component-scan base-package="com.farah.repository.impl"/>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>

        </property>

        <property name="jpaProperties">
            <map>
                <entry key="hibernate.hbm2ddl.auto" value="create-drop"/>
                <entry key="hibernate.show_sql" value="true"/>
            </map>
        </property>

        <property name="packagesToScan" value="com.farah.domain"/>
    </bean> 

    <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>

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

这里是Spring Data JPA为您做一些繁重工作的地方。如果您扩展 JpaRepository Interface ,则可以自动继承许多CRUD功能。要定义它,您只需为域对象创建一个存储库,如下所示。

  

存储库

AccountRepository


/**
 * Spring Data JPA repository for the Account entity.
 */
public interface AccountRepository extends JpaRepository<Account, Long> {

}

这将为您提供 JpaRepository Interface

中的所有方法

接下来,您可以为您的实体构建域对象。

  

帐户


/**
* An Account.
*/
@Entity
@Table( name = "T_ACCOUNT" )
public class Account implements Serializable {

    @Id
    @GeneratedValue( strategy = GenerationType.AUTO ) private Long id;
    @Column( name = "name" ) private String name;
    /**
     * Getters, Setters... 
     */
     ...
}

然后,您只需 @Inject 将您的存储库放入您的服务层。

  

ServiceFacade

的AccountService


@Transactional
@Service
public class AccountService {

    @Autowired
    private AccountRepository repository;

    public Boolean create( Account Account ) {
        ...
    }

    public Boolean update( Account Account ) {
       ...
    }

    public Boolean delete( Account Account ) {
        ...
    }
}