博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于Hibernate的JPA2.0快速构建
阅读量:5984 次
发布时间:2019-06-20

本文共 7137 字,大约阅读时间需要 23 分钟。

hot3.png

前言

尽管现在开源的框架已经非常优秀,但是缺乏统一的标准有违软件开源的初衷,因此Sun公司的JCP组织发布了Java EE的JPA标准,并统一ORM规则、JPQL查询语言、子查询、高级查询和批量处理等操作。推出JPA规范有两点原因:一是,希望简化现有的SE和EE工作,特别是EJB3.0的推出,使得企业级项目的开发推向更高的层次(EJB3.0已经非常优秀,但是由于时间的问题,并且Spring已经占领了市场);二是,希望业界有一个统一的标准,就像当年JDBC推出一样,只实现接口,其余API的实现交给项目厂商或者组织去完成。

Hibernate JPA

实际项目开发应该尽量使用JPA的API编程,为什么要这样做?JPA是一个规范,不是产品,最终实现交给Hibernate这些ORM框架去实现,即使以后我们要改变ORM的底层,也只需要简单更改一下配置即可,JPA还是属于javax.persistence.*的包里面,稍微有些不同的是主键的生成策略不同的ORM规范有所差异,但基本原理还是一样。

下面将分hibernate实现和整合Spring实现两种案例说明JPA整合的好处。

Maven包管理

由于Spring、Hibernate和log4j的maven配置比较繁琐,这里只提供版本管理:

4.0.5.RELEASE
4.3.0.Final
1.6.6
1.2.12
UTF-8
1.4.1.RELEASE
1.0.1.Final

POJO实体

由于使用注解方式创建,因此本文将不创建orm.xml文件,并且JPA的注解也非常容易看懂,因此注解内容不做详述,下面创建一个用户实体对象,对应数据库中的表为t_user;

import javax.persistence.*;import java.io.Serializable;/** * @author Barudisshu */@Entity(name = "USER")@Table(name = "t_user",uniqueConstraints = {@UniqueConstraint(columnNames = {"username"})})public class UserInfo implements Serializable{    @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)    private Long id;    // 希望用户名是唯一的    @Basic    @Column(name = "username")    private String username;    @Basic    @Column(name = "password")    private String password;    // 如果Id生成策略被指定,不应该有带参数的构造函数    // 省略getter和setter方法}

因为@Id中的Id字段是唯一的,如果生成策略已经指定,使用persist(Object obj)方法时将抛出异常,因此,要么改为merge方法,要么去掉@GeneratedVale注解,因为persist会寻找游离态的实体是根据Id进行标识,如果没有则自行创建。

persistence.xml

默认persistence.xml文件处于根目录的META-INF文件下,并且名称固定,如果使用想使用Maven指定,需要配置ant插件:

maven-antrun-plugin
1.3
copy-test-persistence
process-test-resources
run
restore-persistence
prepare-package
run

OK,前面已经说过,只使用注解方式,不使用xml方式,所以persistence.xml使用类加载的方式。

org.hibernate.jpa.HibernatePersistenceProvider
ls.jpa.entity.UserInfo

注意:JPA2.0和JPA1.0有较大差别,JPA2.0是提供了类型安全的查询机制、丰富的表达式等功能,并且已经从EJB中独立开来。

单元测试

单元测试类不用显式加载persistence.xml文件,到底persistence.xml文件是如何加载的为什么名称是固定的?笔者找了很久,原来是是在org.hibernate.jpa.boot.internal.PersistenceXmlParser类下定义的,如果单纯从Persistence类下是找不到的,因为hibernate.jpa.boot包下会加载所有配置文件并转换为properties属性存储在Map中,然后通过工具类或者通过ClassLoader进行属性访问。下面为单元测试代码:

import ***;/** * @author Barudisshu */public class LogonTest {    private static final Logger logger = Logger.getLogger(LogonTest.class);    private static final String PERSISTENCE_UNIT_NAME = "person_pu";    @Test    public void simpleTests(){        // Obtaining an entity manager        EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);        EntityManager entityManager = factory.createEntityManager();        // Read the existing entries and write to console        TypedQuery
query = entityManager.createQuery("select u from USER u", UserInfo.class); List
userList = query.getResultList(); // List user name for (UserInfo userInfo : userList) { logger.info(userInfo.getUsername()); } logger.info("Size: " + userList.size()); // Simple transaction entityManager.getTransaction().begin(); UserInfo userInfo = new UserInfo(); userInfo.setUsername("Barudisshu"); userInfo.setPassword("88888888"); entityManager.persist(userInfo); entityManager.getTransaction().commit(); // Close the EM and EMF when done entityManager.close(); factory.close(); }}

Spring集成

单纯使用JPA很难满足业务上的需求,因此可以通过Spring进行集成,进而架构成为逻辑清晰的业务层次。首先添加相应的Maven管理包,如下:

org.springframework
spring-orm
${spring.version}
org.springframework
spring-aop
${spring.version}
org.springframework
spring-test
${spring.version}
org.springframework
spring-beans
${spring.version}
org.springframework.data
spring-data-jpa
${spring-data-jpa.version}

为了达到分层的架构,一下分别添加Dao层和Service层,代码清单如下:

Dao层,自动装配持久化上下文:

import ***;/** * @author Barudisshu */@Repositorypublic class UserDao {    @PersistenceContext    private EntityManager em;    @Transactional    public UserInfo save(UserInfo userInfo){        em.persist(userInfo);        return userInfo;    }}
Service层,创建服务:
import ***;/** * @author Barudisshu */@Servicepublic class UserService {    @Autowired    private UserDao userDao;    @Transactional    public UserInfo create(String name,String password){        UserInfo userInfo = new UserInfo();        userInfo.setUsername(name);        userInfo.setPassword(password);        return userDao.save(userInfo);    }}

上述代码没有使用JpaTemplate模版,自spring3.1之后就没有了,可能是JPA规范做得足够好的原因,就像自spring3.2.x之后不再支持HibernateTemplate一样。

Spring整合Hibernate时,Spring可以通过容器来管理Hibernate的SessionFactory;类似地,Spring整合JPA时,Spring可以通过容器管理JPA的EntityManagerFactory。Spring为JPA EntityManagerFactory管理提供了两种方式:

  1. LocalEntityManagerFactoryBean
  2. LocalContainerEntityManagerFactoryBean

LocalEntityMangerFactoryBean功能比较有限,只能通过persistence.xml内容的属性构建,因此不能使用Spring容器中已有的DataSource,也不能切换全局事务。而LocalContainerEntityManagerFactoryBean则刚好弥补了这方面的不足,并且可以使用Spring容器中已有的数据源,这样persistence.xml就不用编写任何数据源了。

OK,所有配置已经完成,下面进行简单的单元测试:
import ***;/** * @author Barudisshu */@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = {"classpath:spring-config.xml"})@Transactional@TransactionConfiguration(transactionManager = "txManager",defaultRollback = true)public class SimpleTest {    private static final Logger logger = Logger.getLogger(SimpleTest.class);    @Autowired    private UserService userService;    @Test    public void userTests(){        UserInfo userInfo = userService.create("Barudisshu","liter");        logger.info(JSON.toJSONString(userInfo));    }}

单元测试绿条通过后,打开数据库可以看到,已经自动为你创建t_user用户表:

Well done!

转载于:https://my.oschina.net/Barudisshu/blog/314843

你可能感兴趣的文章
因特网中和多媒体有关的协议
查看>>
哈希表
查看>>
Tell Me About Yourself - Best Answers and Examples
查看>>
吴志攀常务副校长在学院2011年春季毕业典礼上的讲话
查看>>
UVa 10618 Tango Tango Insurrection
查看>>
购物车
查看>>
正则表达式 捕获分组
查看>>
20165302 预备作业3 Linux安装及学习
查看>>
关联查询,将主表中多个字段中的值 与 字典表 进行映射替换。
查看>>
本地JAR包打入本地mvn仓库
查看>>
移动端网页布局中需要注意事项以及解决方法总结
查看>>
Delegate in Cocoa
查看>>
JQuery操作input
查看>>
软件测试——白盒测试
查看>>
threading多线程模块
查看>>
Android开发,Eclipse创建aidl接口时,出错
查看>>
头文件里面的ifndef /define/endif的作用
查看>>
二路归并排序算法实现-完整C语言程序
查看>>
Windows Phone 7, Android and iOS with Mono IV: Webservices
查看>>
bootstrap模态框Esc键不关闭
查看>>