`
jinnianshilongnian
  • 浏览: 21434353 次
  • 性别: Icon_minigender_1
博客专栏
5c8dac6a-21dc-3466-8abb-057664ab39c7
跟我学spring3
浏览量:2405044
D659df3e-4ad7-3b12-8b9a-1e94abd75ac3
Spring杂谈
浏览量:2997694
43989fe4-8b6b-3109-aaec-379d27dd4090
跟开涛学SpringMVC...
浏览量:5631469
1df97887-a9e1-3328-b6da-091f51f886a1
Servlet3.1规范翻...
浏览量:257571
4f347843-a078-36c1-977f-797c7fc123fc
springmvc杂谈
浏览量:1593160
22722232-95c1-34f2-b8e1-d059493d3d98
hibernate杂谈
浏览量:248971
45b32b6f-7468-3077-be40-00a5853c9a48
跟我学Shiro
浏览量:5847542
Group-logo
跟我学Nginx+Lua开...
浏览量:698161
5041f67a-12b2-30ba-814d-b55f466529d5
亿级流量网站架构核心技术
浏览量:780453
社区版块
存档分类
最新评论

【第八章】 对ORM的支持 之 8.4 集成JPA ——跟我学spring3

阅读更多

8.4  集成JPA

       JPA全称为Java持久性API(Java Persistence API),JPA是Java EE 5标准之一,是一个ORM规范,由厂商来实现该规范,目前有Hibernate、OpenJPA、TopLink、EclipseJPA等实现。

 

8.4.1  如何集成

       Spring目前提供集成Hibernate、OpenJPA、TopLink、EclipseJPA四个JPA标准实现。

       Spring通过使用如下Bean进行集成JPA(EntityManagerFactory):

  • LocalEntityManagerFactoryBean适用于那些仅使用JPA进行数据访问的项目,该FactoryBean将根据JPA PersistenceProvider自动检测配置文件进行工作,一般从“META-INF/persistence.xml”读取配置信息,这种方式最简单,但不能设置Spring中定义的DataSource,且不支持Spring管理的全局事务,而且JPA 实现商可能在JVM启动时依赖于VM agent从而允许它们进行持久化类字节码转换(不同的实现厂商要求不同,需要时阅读其文档),不建议使用这种方式;

         persistenceUnitName:指定持久化单元的名称;

         使用方式:

 

java代码:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="persistenceUnit"/>
</bean>
  • 从JNDI中获取用于从Java EE服务器获取指定的EntityManagerFactory,这种方式在进行Spring事务管理时一般要使用JTA事务管理;

      使用方式:

 

java代码:
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/jee
       http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
  <jee:jndi-lookup id="entityManagerFactory"  jndi-name="persistence/persistenceUnit"/>
</beans>

 

此处需要使用“jee”命名标签,且使用<jee:jndi-lookup>标签进行JNDI查找,“jndi-name”属性用于指定JNDI名字。

  • LocalContainerEntityManagerFactoryBean适用于所有环境的FactoryBean,能全面控制EntityManagerFactory配置,如指定Spring定义的DataSource等等。

         persistenceUnitManager:用于获取JPA持久化单元,默认实现DefaultPersistenceUnitManager用于解决多配置文件情况

 

         dataSource:用于指定Spring定义的数据源;

 

         persistenceXmlLocation:用于指定JPA配置文件,对于对配置文件情况请选择设置persistenceUnitManager属性来解决;

 

         persistenceUnitName:用于指定持久化单元名字;

 

         persistenceProvider:用于指定持久化实现厂商类;如Hibernate为org.hibernate.ejb.HibernatePersistence类;

 

         jpaVendorAdapter:用于设置实现厂商JPA实现的特定属性,如设置Hibernate的是否自动生成DDL的属性generateDdl;这些属性是厂商特定的,因此最好在这里设置;目前Spring提供HibernateJpaVendorAdapter、OpenJpaVendorAdapter、EclipseLinkJpaVendorAdapter、TopLinkJpaVendorAdapter、OpenJpaVendorAdapter四个实现。其中最重要的属性是“database”,用来指定使用的数据库类型,从而能根据数据库类型来决定比如如何将数据库特定异常转换为Spring的一致性异常,目前支持如下数据库(DB2DERBYH2HSQLINFORMIXMYSQLORACLEPOSTGRESQLSQL_SERVERSYBASE)。

 

         jpaDialect:用于指定一些高级特性,如事务管理,获取具有事务功能的连接对象等,目前Spring提供HibernateJpaDialect、OpenJpaDialect 、EclipseLinkJpaDialect、TopLinkJpaDialect、和DefaultJpaDialect实现,注意DefaultJpaDialect不提供任何功能,因此在使用特定实现厂商JPA实现时需要指定JpaDialect实现,如使用Hibernate就使用HibernateJpaDialect。当指定jpaVendorAdapter属性时可以不指定jpaDialect,会自动设置相应的JpaDialect实现;

 

         jpaProperties和jpaPropertyMap:指定JPA属性;如Hibernate中指定是否显示SQL的“hibernate.show_sql”属性,对于jpaProperties设置的属性自动会放进jpaPropertyMap中;

         loadTimeWeaver:用于指定LoadTimeWeaver实现,从而允许JPA 加载时修改相应的类文件。具体使用得参考相应的JPA规范实现厂商文档,如Hibernate就不需要指定loadTimeWeaver。

接下来学习一下Spring如何集成JPA吧:

1、准备jar包,从下载的hibernate-distribution-3.6.0.Final包中获取如下Hibernate需要的jar包从而支持JPA

 

lib\jpa\hibernate-jpa-2.0-api-1.0.0.Final.jar //用于支持JPA

 

2、对象模型定义,此处使用UserModel2

 

java代码:
package cn.javass.spring.chapter8;
//省略import
@Entity
@Table(name = "test")
public class UserModel2 {
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    @Column(name = "name")
    private String myName;
    //省略getter和setter
}

 

注意此处使用的所有注解都是位于javax.persistence包下,如使用@org.hibernate.annotations.Entity 而非@javax.persistence. Entity将导致JPA不能正常工作。

 

1、 JPA配置定义(chapter8/persistence.xml),定义对象和数据库之间的映射:

 

java代码:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
    xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence                      http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
    <persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL"/>
</persistence>
 

      在JPA配置文件中,我们指定要持久化单元名字,和事务类型,其他都将在Spring中配置。

 

2、 数据源定义,此处使用第7章的配置文件,即“chapter7/applicationContext-resources.xml”文件。

 

3、 EntityManagerFactory配置定义(chapter8/applicationContext-jpa.xml):

 

java代码:
  <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="persistenceXmlLocation" value="chapter8/persistence.xml"/>
    <property name="persistenceUnitName" value="persistenceUnit"/>
    <property name="persistenceProvider" ref="persistenceProvider"/>
    <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
    <property name="jpaDialect" ref="jpaDialect"/>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.show_sql">true</prop>
        </props>
    </property>
  </bean>
  <bean id="persistenceProvider" class="org.hibernate.ejb.HibernatePersistence"/>
 

 

 

java代码:
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
   <property name="generateDdl" value="false" />
   <property name="database" value="HSQL"/>
</bean>
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
  • LocalContainerEntityManagerFactoryBean:指定使用本地容器管理EntityManagerFactory,从而进行细粒度控制;
  • dataSource属性指定使用Spring定义的数据源;
  • persistenceXmlLocation指定JPA配置文件为chapter8/persistence.xml,且该配置文件非常简单,具体配置完全在Spring中进行;
  • persistenceUnitName指定持久化单元名字,即JPA配置文件中指定的;
  • persistenceProvider:指定JPA持久化提供商,此处使用Hibernate实现HibernatePersistence类;
  • jpaVendorAdapter:指定实现厂商专用特性,即generateDdl= false表示不自动生成DDL,database= HSQL表示使用hsqldb数据库;
  • jpaDialect:如果指定jpaVendorAdapter此属性可选,此处为HibernateJpaDialect;
  •  jpaProperties:此处指定“hibernate.show_sql =true”表示在日志系统debug级别下将打印所有生成的SQL。

 

4、 获取EntityManagerFactory

 

java代码:
package cn.javass.spring.chapter8;
//省略import
public class JPATest {
    private static EntityManagerFactory entityManagerFactory;
    @BeforeClass
    public static void setUpClass() {
        String[] configLocations = new String[] {
                "classpath:chapter7/applicationContext-resources.xml",
                "classpath:chapter8/applicationContext-jpa.xml"};
        ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocations);
        entityManagerFactory = ctx.getBean(EntityManagerFactory.class);
    }
}

 

此处我们使用了chapter7/applicationContext-resources.xml定义的“dataSource”数据源,通过ctx.getBean(EntityManagerFactory.class)获取EntityManagerFactory。

 

5、  通过EntityManagerFactory获取EntityManager进行创建和删除表:

 

java代码:
@Before
public void setUp() throws SQLException {
   //id自增主键从0开始
   String createTableSql = "create memory table test" + "(id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, " + "name varchar(100))";
   executeSql(createTableSql);
}
@After
public void tearDown() throws SQLException {
    String dropTableSql = "drop table test";
    executeSql(dropTableSql);
}

private void executeSql(String sql) throws SQLException {
  EntityManager em = entityManagerFactory.createEntityManager();
  beginTransaction(em);
  em.createNativeQuery(sql).executeUpdate();
  commitTransaction(em);
  closeEntityManager(em);
}
private void closeEntityManager(EntityManager em) {
  em.close();
}
private void rollbackTransacrion(EntityManager em) throws SQLException {
  if(em != null) {
     em.getTransaction().rollback();
  }         
}
private void commitTransaction(EntityManager em) throws SQLException {
   em.getTransaction().commit();
}
private void beginTransaction(EntityManager em) throws SQLException {
   em.getTransaction().begin();
}

使用EntityManagerFactory创建EntityManager,然后通过EntityManager对象的createNativeQuery创建本地SQL执行创建和删除表。

 

 

6、 使用EntityManagerFactory获取EntityManager对象进行持久化数据:

 

java代码:
@Test
public void testFirst() throws SQLException {
    UserModel2 model = new UserModel2();
    model.setMyName("test");
    EntityManager em = null;
    try {
        em = entityManagerFactory.createEntityManager();
        beginTransaction(em);
        em.persist(model);
        commitTransaction(em);
    } catch (SQLException e) {
        rollbackTransacrion(em);
        throw e;
    } finally {
      closeEntityManager(em);
    }
}

 

使用EntityManagerFactory获取EntityManager进行操作,看到这还能忍受冗长的代码和事务管理吗?Spring同样提供JpaTemplate模板类来简化这些操作。

大家有没有注意到此处的模型对象能自动映射到数据库,这是因为Hibernate JPA实现默认自动扫描类路径中的@Entity注解类及*.hbm.xml映射文件,可以通过更改Hibernate JPA属性“hibernate.ejb.resource_scanner”,并指定org.hibernate.ejb.packaging.Scanner接口实现来定制新的扫描策略。

 

8.4.2  使用JpaTemplate

JpaTemplate模板类用于简化事务管理及常见操作,类似于JdbcTemplate模板类,对于复杂操作通过提供JpaCallback回调接口来允许更复杂的操作。

       接下来示例一下JpaTemplate的使用:

1、修改Spring配置文件(chapter8/applicationContext-jpa.xml),添加JPA事务管理器:

 

java代码:
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
 
  • txManager:指定事务管理器,JPA使用JpaTransactionManager事务管理器实现,通过entityManagerFactory指定EntityManagerFactory;用于支持Java SE环境的JPA扩展的持久化上下文(EXTENDED Persistence Context

2、修改JPATest类,添加类变量ctx,用于后边使用其获取事务管理器使用:

 

java代码:
package cn.javass.spring.chapter8;
public class JPATest {
    private static EntityManagerFactory entityManagerFactory;
    private static ApplicationContext ctx;
    @BeforeClass
    public static void beforeClass() {
        String[] configLocations = new String[] {
                "classpath:chapter7/applicationContext-resources.xml",
                "classpath:chapter8/applicationContext-jpa.xml"};
        ctx = new ClassPathXmlApplicationContext(configLocations);
        entityManagerFactory = ctx.getBean(EntityManagerFactory.class);
}
}
 

 

3)JpaTemplate模板类使用:

 

java代码:
@Test
public void testJpaTemplate() {
final JpaTemplate jpaTemplate = new JpaTemplate(entityManagerFactory);
  final UserModel2 model = new UserModel2();
  model.setMyName("test1");
  PlatformTransactionManager txManager = ctx.getBean(PlatformTransactionManager.class);
  new TransactionTemplate(txManager).execute(
    new TransactionCallback<Void>() {
      @Override
      public Void doInTransaction(TransactionStatus status) {
        jpaTemplate.persist(model);
        return null;
      }
  });
  String COUNT_ALL = "select count(*) from UserModel";
  Number count = (Number) jpaTemplate.find(COUNT_ALL).get(0);
  Assert.assertEquals(1, count.intValue());
}
   
 
  • jpaTemplate:可通过new JpaTemplate(entityManagerFactory)方式创建;
  • txManager通过ctx.getBean(PlatformTransactionManager.class)获取事务管理器;
  • TransactionTemplate通过new TransactionTemplate(txManager)创建事务模板对象,并通过execute方法执行TransactionCallback回调中的doInTransaction方法中定义需要执行的操作,从而将由模板类通过txManager事务管理器来进行事务管理,此处是调用jpaTemplate对象的persist方法进行持久化;
  • jpaTemplate.persist():根据JPA规范,在JPA扩展的持久化上下文,该操作必须运行在事务环境,还有persist()、 merge()、remove()操作也必须运行在事务环境;
  • jpaTemplate.find()根据JPA规范,该操作无需运行在事务环境,还有find()、getReference()、 refresh()、detach()和查询操作都无需运行在事务环境。

 

此实例与Hibernate和Ibatis有所区别,通过JpaTemplate模板类进行如持久化等操作时必须有运行在事务环境中,否则可能抛出如下异常或警告:

  • “javax.persistence.TransactionRequiredException:Executing an update/delete query:表示没有事务支持,不能执行更新或删除操作;
  • 警告“delaying identity-insert due to no transaction in progress”:需要在日志系统启动debug模式才能看到,表示在无事务环境中无法进行持久化,而选择了延迟标识插入。

 

以上异常和警告是没有事务造成的,也是最让人困惑的问题,需要大家注意。

 

8.4.3  集成JPA及最佳实践

       类似于JdbcDaoSupport类,Spring对JPA也提供了JpaDaoSupport类来支持一致的数据库访问。JpaDaoSupport也是DaoSupport实现:

       接下来示例一下Spring集成JPA的最佳实践:

 

1、 定义Dao接口,此处使用cn.javass.spring.chapter7.dao. IUserDao

 

2、 定义Dao接口实现,此处是JPA实现:

 

java代码:
package cn.javass.spring.chapter8.dao.jpa;
//省略import
@Transactional(propagation = Propagation.REQUIRED)
public class UserJpaDaoImpl extends JpaDaoSupport implements IUserDao {
    private static final String COUNT_ALL_JPAQL = "select count(*) from UserModel";
    @Override
    public void save(UserModel model) {
        getJpaTemplate().persist(model);
    }
    @Override
    public int countAll() {
        Number count =
           (Number) getJpaTemplate().find(COUNT_ALL_JPAQL).get(0);
        return count.intValue();
    }
}

 

 

此处注意首先JPA实现放在dao.jpa包里,其次实现类命名如UserJpaDaoImpl,即×××JpaDaoImpl,当然如果自己有更好的命名规范可以遵循自己的,此处只是提个建议。

另外在类上添加了@Transactional注解表示该类的所有方法将在调用时需要事务支持,propagation传播属性为Propagation.REQUIRED表示事务是必需的,如果执行该类的方法没有开启事务,将开启一个新的事务。

 

3、进行资源配置,使用resources/chapter7/applicationContext-resources.xml

 

4、dao定义配置,在chapter8/applicationContext-jpa.xml中添加如下配置:

4.1首先添加tx命名空间用于支持事务:

 

java代码:
<?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"
    xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

 

4.2、为@Transactional注解事务开启事务支持:

 

 

java代码:
<tx:annotation-driven transaction-manager="txManager"/>

只为类添加@Transactional 注解是不能支持事务的,需要通过<tx:annotation-driven>标签来开启事务支持,其中txManager属性指定事务管理器。

 

 

4.3、配置DAO Bean:

 

java代码:
<bean id="abstractDao" abstract="true">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>   
<bean id="userDao"
      class="cn.javass.spring.chapter8.dao.jpa.UserJpaDaoImpl"
      parent="abstractDao"/> 

首先定义抽象的abstractDao,其有一个entityManagerFactory属性,从而可以让继承的子类自动继承entityManagerFactory属性注入;然后定义userDao,且继承abstractDao,从而继承entityManagerFactory注入;我们在此给配置文件命名为applicationContext-jpa.xml表示JPA实现。

 

 

5、最后测试一下吧(cn.javass.spring.chapter8. JPATest):

 

java代码:
@Test
public void testBestPractice() {
    String[] configLocations = new String[] {
            "classpath:chapter7/applicationContext-resources.xml",
            "classpath:chapter8/applicationContext-jpa.xml"};
    ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocations);
    IUserDao userDao = ctx.getBean(IUserDao.class);
    UserModel model = new UserModel();
    model.setMyName("test");
    userDao.save(model);
    Assert.assertEquals(1, userDao.countAll());
}

 

和Spring JDBC框架的最佳实践完全一样,除了使用applicationContext-jpa.xml代替了applicationContext-jdbc.xml,其他完全一样。也就是说,DAO层的实现替换可以透明化。

还有与集成其他ORM框架不同的是JPA在进行持久化或更新数据库操作时需要事务支持。

 

 

8.4.4  Spring+JPA的CRUD

Spring+JPA CRUD(增删改查)也相当简单,让我们直接看具体示例吧:

 

 

java代码:
@Test
public void testCRUD() {
    PlatformTransactionManager txManager = ctx.getBean(PlatformTransactionManager.class);
    final JpaTemplate jpaTemplate = new JpaTemplate(entityManagerFactory);
    TransactionTemplate tansactionTemplate = new TransactionTemplate(txManager);
    tansactionTemplate.execute(new TransactionCallback<Void>() {
        @Override
        public Void doInTransaction(TransactionStatus status) {
            UserModel model = new UserModel();
            model.setMyName("test");
            //新增
            jpaTemplate.persist(model);
            //修改
            model.setMyName("test2");
            jpaTemplate.flush();//可选
            //查询
            String sql = "from UserModel where myName=?";
            List result = jpaTemplate.find(sql, "test2");
            Assert.assertEquals(1, result.size());
            //删除
            jpaTemplate.remove(model);
            return null;
        }
    });
}
  • 对于增删改必须运行在事务环境,因此我们使用TransactionTemplate事务模板类来支持事务。
  • 持久化:使用JpaTemplate 类的persist方法持久化模型对象;
  • 更新:对于持久化状态的模型对象直接修改属性,调用flush方法即可更新到数据库,在一些场合时flush方法调用可选,如执行一个查询操作等,具体请参考相关文档;
  • 查询:可以使用find方法执行JPA QL查询;
  • 删除:使用remove方法删除一个持久化状态的模型对象。

       Spring集成JPA进行增删改查也相当简单,但本文介绍的稍微复杂一点,因为牵扯到编程式事务,如果采用声明式事务将和集成Hibernate方式一样简洁。

 

 

原创内容,转载请注明出处【http://sishuok.com/forum/blogPost/list/0/2500.html

27
7
分享到:
评论
10 楼 bbos1994 2016-01-09  
你好,我想问下,我用注解来定义实体,但是为什么还是需要在persistence.xml中定义class元素来声明实体类,,不声明就说找不到
9 楼 jayyunfei 2014-03-18  
我也有个问题啊,就是用spring4.0+JPA(Hibernate4.3)报错:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: org/jboss/logging/Logger
请问为什么必须要有jboss日志?
8 楼 jinnianshilongnian 2013-10-13  
tangduDream 写道
你好,我写的spring+jpa,可以在junit上跑,
但是放到jetty时,增删改就报错了,是没有运行在事务环境中?
配置文件中加了<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />

错误:
javax.persistence.TransactionRequiredException: Executing an update/delete query

发下详细的异常吧
7 楼 tangduDream 2013-10-13  
你好,我写的spring+jpa,可以在junit上跑,
但是放到jetty时,增删改就报错了,是没有运行在事务环境中?
配置文件中加了<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />

错误:
javax.persistence.TransactionRequiredException: Executing an update/delete query
6 楼 Ping_QC 2012-06-21  
你好,我写的spring+jpa,可以在junit上跑,
但是放到jetty时,增删改就报错了,是没有运行在事务环境中?
配置文件中加了<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />

错误:
javax.persistence.TransactionRequiredException: Executing an update/delete query
5 楼 jinnianshilongnian 2012-03-23  
nick.s.ni 写道
不会出现您说的每个Dao一个EM,而是每个事务一个

是嗎,Spring只提供了JpaTemplate,怎麼用是開發人員的事,如果不瞭解JPA,很容易出現問題。等我寫個案例給你看看。


你可以看下源码 是这样的  而且JpaTemplate是在execute时 才决定创建/使用线程绑定的EM的

4 楼 nick.s.ni 2012-03-23  
不会出现您说的每个Dao一个EM,而是每个事务一个

是嗎,Spring只提供了JpaTemplate,怎麼用是開發人員的事,如果不瞭解JPA,很容易出現問題。等我寫個案例給你看看。
3 楼 jinnianshilongnian 2012-03-23  
nick.s.ni 写道
JPA的實現我用的是EclipseLink(TopLink)實現,不會跟Hibernate混淆。你這篇應該直接提供

public class ProductDaoImpl implements ProductDao {
@PersistenceContext
private EntityManager em;
public Collection loadProductsByCategory(String category) {
Query query = em.createQuery("from Product as p where p.category = :category");
query.setParameter("category", category);
return query.getResultList();
}
}


其他的刪掉或是一句話帶過就好。



这个倒是 spring3.1也推荐用这种原生的方式,

这个我在注解配置那章(第12章)写的。

但文章肯定要提供所有场景。


使用JpaTemplate 也是没有问题的,不会出现您说的每个Dao一个EM,而是每个事务一个


2 楼 jinnianshilongnian 2012-03-23  
nick.s.ni 写道
spring 3已經不推薦使用JpaTemplate。
那看下spring 2.5.5中使用JpaTemplate的方式
第一種,使用JpaTemplate
<beans>
<bean id="myProductDao" class="product.ProductDaoImpl">
<property name="entityManagerFactory" ref="myEmf"/>
</bean>
</beans>


public class JpaProductDao implements ProductDao {
private JpaTemplate jpaTemplate;
public void setEntityManagerFactory(EntityManagerFactory emf) {
this.jpaTemplate = new JpaTemplate(emf);
}
public Collection loadProductsByCategory(final String category) throws DataAccessException {
return (Collection) this.jpaTemplate.execute(new JpaCallback() {
public Object doInJpa(EntityManager em) throws PersistenceException {
Query query = em.createQuery("from Product as p where p.category = :category");
query.setParameter("category", category);
List result = query.getResultList();
// do some further processing with the result list
return result;
}
});
}
}


第二種
繼承JpaDaoSupport
public class ProductDaoImpl extends JpaDaoSupport implements ProductDao {
public Collection loadProductsByCategory(String category) throws DataAccessException {
Map<String, String> params = new HashMap<String, String>();
params.put("category", category);
return getJpaTemplate().findByNamedParams("from Product as p where p.category = :category", params);
}
}


JpaDaoSupport中需要注入EMF,而EM是內部創建的
protected EntityManager createEntityManager() throws IllegalStateException {
		EntityManagerFactory emf = getEntityManagerFactory();
		Assert.state(emf != null, "No EntityManagerFactory specified");
		Map<String, Object> properties = getJpaPropertyMap();
		return (!CollectionUtils.isEmpty(properties) ? emf.createEntityManager(properties) : emf.createEntityManager());
	}


這不是代碼問題是使用問題,每個DAO都有一個EM,EM中有一定的數據緩存,根據EM的實現,對數據庫中的新增數據會更新,對修改后的數據在查詢時不會更新。
例如一個DAO進行連表查詢,另一個DAO中進行子表的CRUD,修改的信息在查詢中不會更新的。



nick.s.ni 写道
spring 3已經不推薦使用JpaTemplate。
那看下spring 2.5.5中使用JpaTemplate的方式
第一種,使用JpaTemplate
<beans>
<bean id="myProductDao" class="product.ProductDaoImpl">
<property name="entityManagerFactory" ref="myEmf"/>
</bean>
</beans>


public class JpaProductDao implements ProductDao {
private JpaTemplate jpaTemplate;
public void setEntityManagerFactory(EntityManagerFactory emf) {
this.jpaTemplate = new JpaTemplate(emf);
}
public Collection loadProductsByCategory(final String category) throws DataAccessException {
return (Collection) this.jpaTemplate.execute(new JpaCallback() {
public Object doInJpa(EntityManager em) throws PersistenceException {
Query query = em.createQuery("from Product as p where p.category = :category");
query.setParameter("category", category);
List result = query.getResultList();
// do some further processing with the result list
return result;
}
});
}
}


nick.s.ni 写道
spring 3已經不推薦使用JpaTemplate。
那看下spring 2.5.5中使用JpaTemplate的方式
第一種,使用JpaTemplate
<beans>
<bean id="myProductDao" class="product.ProductDaoImpl">
<property name="entityManagerFactory" ref="myEmf"/>
</bean>
</beans>


public class JpaProductDao implements ProductDao {
private JpaTemplate jpaTemplate;
public void setEntityManagerFactory(EntityManagerFactory emf) {
this.jpaTemplate = new JpaTemplate(emf);
}
public Collection loadProductsByCategory(final String category) throws DataAccessException {
return (Collection) this.jpaTemplate.execute(new JpaCallback() {
public Object doInJpa(EntityManager em) throws PersistenceException {
Query query = em.createQuery("from Product as p where p.category = :category");
query.setParameter("category", category);
List result = query.getResultList();
// do some further processing with the result list
return result;
}
});
}
}


第二種
繼承JpaDaoSupport
public class ProductDaoImpl extends JpaDaoSupport implements ProductDao {
public Collection loadProductsByCategory(String category) throws DataAccessException {
Map<String, String> params = new HashMap<String, String>();
params.put("category", category);
return getJpaTemplate().findByNamedParams("from Product as p where p.category = :category", params);
}
}


JpaDaoSupport中需要注入EMF,而EM是內部創建的
protected EntityManager createEntityManager() throws IllegalStateException {
		EntityManagerFactory emf = getEntityManagerFactory();
		Assert.state(emf != null, "No EntityManagerFactory specified");
		Map<String, Object> properties = getJpaPropertyMap();
		return (!CollectionUtils.isEmpty(properties) ? emf.createEntityManager(properties) : emf.createEntityManager());
	}


這不是代碼問題是使用問題,每個DAO都有一個EM,EM中有一定的數據緩存,根據EM的實現,對數據庫中的新增數據會更新,對修改后的數據在查詢時不會更新。
例如一個DAO進行連表查詢,另一個DAO中進行子表的CRUD,修改的信息在查詢中不會更新的。



第二種
繼承JpaDaoSupport
public class ProductDaoImpl extends JpaDaoSupport implements ProductDao {
public Collection loadProductsByCategory(String category) throws DataAccessException {
Map<String, String> params = new HashMap<String, String>();
params.put("category", category);
return getJpaTemplate().findByNamedParams("from Product as p where p.category = :category", params);
}
}


JpaDaoSupport中需要注入EMF,而EM是內部創建的
protected EntityManager createEntityManager() throws IllegalStateException {
		EntityManagerFactory emf = getEntityManagerFactory();
		Assert.state(emf != null, "No EntityManagerFactory specified");
		Map<String, Object> properties = getJpaPropertyMap();
		return (!CollectionUtils.isEmpty(properties) ? emf.createEntityManager(properties) : emf.createEntityManager());
	}


這不是代碼問題是使用問題,每個DAO都有一個EM,EM中有一定的數據緩存,根據EM的實現,對數據庫中的新增數據會更新,對修改后的數據在查詢時不會更新。
例如一個DAO進行連表查詢,另一個DAO中進行子表的CRUD,修改的信息在查詢中不會更新的。





這不是代碼問題是使用問題,每個DAO都有一個EM(这个如果是spring管理事务的,不是每个DAO一个,而是一个事务一个),EM中有一定的數據緩存(一级缓存),根據EM的實現,對數據庫中的新增數據會更新,對修改后的數據在查詢時不會更新(你这个查询是 修改之前?还是修改之后?(修改会自动清除二级缓存的,再次查询返回最新的数据))。

能否把您的用例发过来研究下 什么问题 admin@sishuok.com
1 楼 nick.s.ni 2012-03-23  
JPA的實現我用的是EclipseLink(TopLink)實現,不會跟Hibernate混淆。你這篇應該直接提供

public class ProductDaoImpl implements ProductDao {
@PersistenceContext
private EntityManager em;
public Collection loadProductsByCategory(String category) {
Query query = em.createQuery("from Product as p where p.category = :category");
query.setParameter("category", category);
return query.getResultList();
}
}


其他的刪掉或是一句話帶過就好。

相关推荐

    跟我学spring3(8-13)

    【第八章】 对ORM的支持 之 8.4 集成JPA ——跟我学spring3 【第九章】 Spring的事务 之 9.1 数据库事务概述 ——跟我学spring3 【第九章】 Spring的事务 之 9.2 事务管理器 ——跟我学spring3 【第九章】 Spring的...

    跟我学spring3(8-13).pdf

    对ORM的支持 之 8.1 概述 8.2 集成Hibernate3 8.3 集成iBATIS 8.4 集成JPA 9.1 数据库事务概述 9.2 事务管理器 9.3 编程式事务 9.4 声明式事务 10.1 概述 10.2 集成Struts1.x 10.3 集成Struts2.x 10.4 集成JSF 11.1 ...

    跟开涛学Spring

    1. spring 1.1 【第二章】 IoC 之 2.3 IoC的配置使用——跟我学Spring3 . . ....1.36 【第八章】 对ORM的支持 之 8.2 集成Hibernate3 ——跟我学spring3 . . . . . . . . . . . . . . . . . . .352

    跟我学Spring3(8.2)对ORM的支持之集成Hibe

    跟我学Spring3(8.2)对ORM的支持之集成Hibernate3Java开发Java经验技巧共11页.pdf.zip

    跟我学spring3(8-13)1

    1.1 【第八章】 对ORM的支持 之 8.1 概述 ——跟我学spring3 41.4 跟我学spring3 电子书下载 361.5 【第八章】 对ORM的支

    跟我学Spring3(8.1)对ORM的支持之概述Java

    跟我学Spring3(8.1)对ORM的支持之概述Java开发Java经验技巧共3页.pdf.zip

    python利用元类和描述器实现ORM模型(csdn)————程序.pdf

    python利用元类和描述器实现ORM模型(csdn)————程序

    spring Data jpa中文参考手册

    Spring Data JPA是Spring基于Hibernate开发的一个JPA框架。如果用过Hibernate或者MyBatis的话,就会知道对象关系映射(ORM)框架有多么方便。但是Spring Data JPA框架功能更进一步,为我们做了 一个数据持久层框架...

    Spring同时集成JPA与Mybatis.docx

    Spring对ORM的解决方案主要体现在以下方面: 11.统一的资源管理方式与异常管理:Spring使用各种ORM框架,资源管理及使用方式都是统一的;同时Spring会将各个ORM框架的异常转译到Spring异常体系下。 12.统一的事务...

    springboot同时整合JPA和mybatis的demo

    这个demo同时整合了springboot+JPA+mybatis这个两个orm框架。

    spring-orm.jar

    spring-orm.jar

    Spring高版本对ibatis的支持

    最近想在最新的Spring5.0中集成ibatis(不是mybatis),发现已经不在支持SqlmapClientTemplate和SqlmapClientFactoryBean,于是搞了这个工具jar来进行支持如下配置 &lt;bean id="sqlMapClient" class="org.spring...

    springDataJPA 概述.pdf

    Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封 装的一套 JPA 应用框架,可使开发者用极简的代码即可实现对数据库 的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩 展!学习并使用 ...

    JPA学习资料 JPA学习资料

    从目 前的 开发社区的反应上看,JPA 受到了极大的支持和赞扬,JPA 作为 ORM 领域标准化 整合者的目标应该不难实现。 JPA 通过 JDK 5.0 注解或 XML 描述对象-关系表的映射关系,并将运行期的实体 对象持久化到...

    study-orm-jpa:Java ORM标准JPA编程学习项目

    Java ORM标准JPA编程学习项目 ... 教科书示例: : 1.项目说明 ...Spring数据JPASpring训练营金英汉视频: [SpringCamp2013] Spring Data JPA 在Jaesung Park使用ORM-Spring Camp的设计和开发过程视频: [Sp

    CXF+Spring+JPA+JAX_WS API +Tomcat

    Java web service 入门示例,使用 JAX_WS API 开发,使用 CXF 发布,集成 Spring ,Spring orm 基于 JPA 开发 DAO, 并使用 Spring data jpa 简化 DAO 实现。

    sqltoy-orm是比JPA+MyBatis更加贴合项目的orm框架(依赖spring)

    sqltoy-orm是比JPA+MyBatis更加贴合项目的orm框架(依赖spring),具有jpa式的对象CRUD的同时具有比myBatis(plus)更直观简洁性能强大的查询功能。

    《精通Spring2.X企业应用开发详解》随书源码1-15章

    Spring容器高级主题 第6章 Spring AOP基础 第7章 基于@AspectJ和Schema的 第7章 AOP 第3篇 数据库访问 第8章 Spring对DAO的支持 第9章 Spring的事务管理 第10章 使用Spring JDBC访问数据库 ...

Global site tag (gtag.js) - Google Analytics