Beginning Spring学习笔记——第5章(二)Spring的JPA支持

来源:互联网 发布:佛山新能源汽车知豆 编辑:程序博客网 时间:2024/06/06 17:42

Spring的JPA支持的好处


  • 更容易且更强大的持久化单元配置,不必使用META-INF/persistence.xml
  • 更容易测试
  • 自动EntityManager管理,且可注入DAO Bean中
  • 常见的数据访问异常,异常层次结构变为Spring的
  • 集成事务管理

在Spring容器中配置JPA


Spring在同一个项目中提供三种不同方法配置EntityManagerFactory。

  • LocalEntityManagerFactoryBean
    最基础且功能最有限的方法,从META-INF/persistence.xml中读取JPA配置,不允许使用Spring管理的DataSource实例且不支持分布式事务管理
  • 通过JNDI进行EntityManagerFactory查找
    此时的Spring EntityManagerFactory Bean只不过是一个从JNDI获取的持久化单元委托
  • LocalContainerEntityFactoryBean,最强大和灵活的JPA配置方法,对EntityManagerFactory完全控制

使用LocalContainerEntityManagerFactoryBean配置和使用JPA

接上一节的Book和Student类创建配置类

@Configurationpublic class Ch5Configuration {    @Bean    public DataSource dataSource() {        DriverManagerDataSource dataSource = new DriverManagerDataSource();        dataSource.setDriverClassName("org.h2.Driver");        dataSource.setUrl("jdbc:h2:tcp://localhost/~/test");        dataSource.setUsername("sa");        dataSource.setPassword("");        return dataSource;    }    private Map<String,?> jpaProperties() {        Map<String,String> jpaPropertiesMap = new HashMap<String,String>();        jpaPropertiesMap.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");        jpaPropertiesMap.put("hibernate.hbm2ddl.auto", "update");        return jpaPropertiesMap;    }    @Bean    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {        LocalContainerEntityManagerFactoryBean factoryBean =             new LocalContainerEntityManagerFactoryBean();        factoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);        factoryBean.setDataSource(dataSource());        factoryBean.setPackagesToScan("com.wiley.beginningspring.ch5");        factoryBean.setJpaPropertyMap(jpaProperties());        return factoryBean;    }}

为使用Spring管理的DataSource和EntityManagerFactory,主函数中也要创建Spring容器

public class Main {    public static void main(String[] args) {        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(                Ch5Configuration.class);        EntityManagerFactory entityManagerFactory = applicationContext                .getBean(EntityManagerFactory.class);        EntityManager entityManager = entityManagerFactory                .createEntityManager();        EntityTransaction transaction = entityManager.getTransaction();        transaction.begin();        Student student = new Student();        student.setFirstName("Madoka");        student.setLastName("Kaname");        entityManager.persist(student);        transaction.commit();        entityManager.close();    }}

完成插入操作后查看数据库:
STUDENT
学生成功被插入。

基于纯JPA实现DAO


可以在字段或方法级别使用@PersistenceContext和@PersistenceUnit注解,前者表示对EntityManagerFactory的依赖,后者表示对EntityManager的依赖

使用@PersistenceUnit获取EntityManagerFactory

此时需要在Dao实现类中加入EntityManagerFactory字段并在其上放置@PersistenceUnit注解将entityManagerFactory注入到DAO类中。

public class StudentDaoJpaImpl {    @PersistenceUnit    private EntityManagerFactory entityManagerFactory;    public void save(Student student) {        EntityManager entityManager = entityManagerFactory                .createEntityManager();        EntityTransaction transaction = entityManager.getTransaction();        transaction.begin();        entityManager.persist(student);        transaction.commit();        entityManager.close();    }}

此时还要在配置文件中加入DAO类的Bean:

    @Bean    public StudentDaoJpaImpl studentDao() {        StudentDaoJpaImpl dao = new StudentDaoJpaImpl();        return dao;    }

然后在主函数里用该DAO类插入一个Student实例:

public class Main {    public static void main(String[] args) {        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(                Ch5Configuration.class);        StudentDaoJpaImpl dao = applicationContext.getBean(StudentDaoJpaImpl.class);        Student student = new Student();        student.setFirstName("Sayaka");        student.setLastName("Miki");        dao.save(student);    }}

运行程序发现插入成功
插入成功

使用@PersistenceContext获取EntityManager

此时要用@EnableTransactionManagement注解标识配置类启用Spring容器管理事务,新配置类为:

@Configuration@EnableTransactionManagementpublic class Ch5Configuration {    @Bean    public DataSource dataSource() {        DriverManagerDataSource dataSource = new DriverManagerDataSource();        dataSource.setDriverClassName("org.h2.Driver");        dataSource.setUrl("jdbc:h2:tcp://localhost/~/test");        dataSource.setUsername("sa");        dataSource.setPassword("");        return dataSource;    }    private Map<String,?> jpaProperties() {        Map<String,String> jpaPropertiesMap = new HashMap<String,String>();        jpaPropertiesMap.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");        jpaPropertiesMap.put("hibernate.hbm2ddl.auto", "update");        return jpaPropertiesMap;    }    @Bean    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {        LocalContainerEntityManagerFactoryBean factoryBean =             new LocalContainerEntityManagerFactoryBean();        factoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);        factoryBean.setDataSource(dataSource());        factoryBean.setPackagesToScan("com.wiley.beginningspring.ch5");        factoryBean.setJpaPropertyMap(jpaProperties());        return factoryBean;    }    @Bean    public StudentDaoJpaImpl studentDao() {        StudentDaoJpaImpl dao = new StudentDaoJpaImpl();        return dao;    }    @Bean    @Autowired    public PlatformTransactionManager transactionManager(        EntityManagerFactory entityManagerFactory) {        JpaTransactionManager transactionManager = new JpaTransactionManager();        transactionManager.setEntityManagerFactory(entityManagerFactory);        return transactionManager;    }    @Bean    public BookDao bookDao() {        BookDaoJpaImpl bean = new BookDaoJpaImpl();        return bean;    }    @Bean    public BookService bookService() {        BookServiceImpl bean = new BookServiceImpl();        bean.setBookDao(bookDao());        return bean;    }}

然后创建BookDao接口和它的实现类进行持久化操作。由于@PersistenceContext注解是与EntityManager绑定,因此被注入的是EntityManager实例。

public interface BookDao {    public void save(Book book);}public class BookDaoJpaImpl implements BookDao {    @PersistenceContext    private EntityManager entityManager;    @Override    public void save(Book book) {        entityManager.persist(book);    }}

再创建服务层的BookService接口和其实现类处理事务管理。

public interface BookService {    public void save(Book book);}@Transactionalpublic class BookServiceImpl implements BookService {    private BookDao bookDao;    public void setBookDao(BookDao bookDao) {        this.bookDao = bookDao;    }    @Override    public void save(Book book) {        bookDao.save(book);    }}

以上二者的Bean都已经定义在了新配置文件中完成了向服务层注入dao层。
最后在主函数中执行对bookService的Bean查找,对新的Book实体进行持久化操作。

public class Main {    public static void main(String[] args) {        ApplicationContext applicationContext =             new AnnotationConfigApplicationContext(Ch5Configuration.class);        BookService bookService = applicationContext.getBean(BookService.class);        Book book = new Book();        book.setName("The Order of Things");        bookService.save(book);    }}

运行得到结果,成功插入书籍
运行结果

处理和转换异常


只需要用@Repository注解标注DAO实现类,

@Repositorypublic class BookDaoJpaImpl implements BookDao {    @PersistenceContext    private EntityManager entityManager;    @Override    public void save(Book book) {        entityManager.persist(book);    }}

然后在配置类中加入PersistenceExceptionTranslationPostProcessor的Bean,

    @Bean    public static PersistenceExceptionTranslationPostProcessor         persistenceExceptionTranslationPostProcessor() {        PersistenceExceptionTranslationPostProcessor bean =         new PersistenceExceptionTranslationPostProcessor();        return bean;    }

就可以在服务层通过一个try-catch语句捕捉转化为DataAccessException的异常了。

    @Override    public void save(Book book) {        try{            //Perform some business logic here            bookDao.save(book);        } catch (DataAccessException ex) {            //handle the data access exception without depending on particular data access technology used beneath    }

在Spring环境中进一步配置JPA

JpaDialect

通过该接口可以配置如下高级功能:

  • 应用特定事务语义,比如自定义隔离级别或者事务超时
  • 获取事务性JDBC连接,以便向基于JDBC的DAO公开
  • 将PersistenceExcept转换到Spring DataAccessException的高级功能

默认实现为不提供任何上述功能的DefaultJpaDialect,使用上述功能需要指定特定方言类,比如HibernateJpaDialect。

JpaVendorAdapter

用于激活与供应商有关的高级功能,例如可以将LocalContainerEntityManagerFactoryBean中一下代码注释掉集中配置和管理:

    @Bean    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {        LocalContainerEntityManagerFactoryBean factoryBean =             new LocalContainerEntityManagerFactoryBean();        factoryBean.setDataSource(dataSource());        //factoryBean.setJpaPropertyMap(jpaProperties());        //factoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);        //factoryBean.setJpaDialect(new HibernateJpaDialect());        factoryBean.setJpaVendorAdapter(jpaVendorAdapter());        return factoryBean;    }    @Bean    public JpaVendorAdapter jpaVendorAdapter() {        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();        jpaVendorAdapter.setGenerateDdl(true);        jpaVendorAdapter.setDatabase(Database.H2);        return jpaVendorAdapter;    }

JPA加载时编制

在配置类上添加@EnableLoadTimeWeaving启用加载时编织

阅读全文
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 国二报名时民族错了怎么办 屁股凹陷下去一块已经萎缩了怎么办 我家孩子上高中了英语不好怎么办 驼背脖子向前倾怎么办用背背佳 屁股大又肥是骨盆前倾怎么办 手术40多天引起小腿变细了怎么办 老师教育学生学生跑出教室你怎么办 有矛盾舍友发朋友圈攻击我怎么办 飞机杯送的润滑油很快用完了怎么办 人笨记性不好内向反应迟钝该怎么办 洗衣机滋生了大量的霉菌在怎么办? 爸妈给兄弟买的房子贵很多怎么办 输了十几万 不敢跟爸妈讲怎么办 赌博欠2万不敢和爸妈讲怎么办 学校凳子坏了丢了 现在要查怎么办 我想写字可就是写的不好看怎么办 我的字写的很丑怎么办 大母指腱鞘炎好了之后又犯了怎么办 被蚊子咬了好大一个包怎么办 欠我钱的人跑了怎么办 下面旁边破了沙的疼怎么办 协助民警执法时质疑辅警身份怎么办 跑步每次腿落地小腿骨头疼怎么办 两年义务兵完了想继续当兵怎么办 保研联系老师说名额已满怎么办 在部队报函授不发毕业证怎么办 济南自考信息修改后原成绩怎么办 自考本科档案一直在自己手里怎么办 想考警校可身高差两公分怎么办 没读完初中现在想继续夜大怎么办 美国签证确认页姓和名写错了怎么办 单位不承认非法辞退说我旷工怎么办 工作了和同事在一起住宿舍怎么办 教会的事情商量是起冲突怎么办 转转购买的产品是坏的怎么办 二年级的学生反应太迟钝怎么办? 特别胖的人运动一半体力不支怎么办 怀孕了在胸透门口站了很久怎么办 自己觉的色弱但高考体检正常怎么办 高考体检不合格怎么办会影响录取吗 老婆起诉我离婚我不想离怎么办