学习Spring Data Jpa
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习Spring Data Jpa相关的知识,希望对你有一定的参考价值。
首先,抛开Spring,先来谈谈JPA。
1.JPA是什么?
JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
说到底还是一个ORM框架,不过是Sun为了希望整合所有的ORM框架而推出的规范,总的来说没有什么大的区别。依旧是是开发者从复杂的SQL与JDBC中脱离出来。
2.实际中使用JPA
首先在数据库中建库与表,mysql中脚本如下
1 CREATE DATABASE jpa; 2 USE jpa; 3 CREATE TABLE `user` ( 4 `id` bigint(20) NOT NULL AUTO_INCREMENT, 5 `firstName` varchar(45) NOT NULL, 6 `phoneNo` varchar(45) NOT NULL, 7 `lastName` varchar(45) NOT NULL, 8 `birthday` date NOT NULL, 9 PRIMARY KEY (`id`), 10 UNIQUE KEY `id_UNIQUE` (`id`), 11 UNIQUE KEY `phoneNo_UNIQUE` (`phoneNo`) 12 ) ENGINE=InnoDB DEFAULT CHARSET=UTF-8;
JPA标准配置文件,使用Hibernate实现 含每行注释(注意 一定要放置在src下的META-INF目录下,十分坑爹!!)
1 <?xml version="1.0" encoding="UTF-8"?> 2 3 <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> 6 7 <!-- 8 Name属性用于定义持久化单元的名字 (name必选,空值也合法); 9 transaction-type 指定事务类型(可选) 10 --> 11 <persistence-unit name="TestJPAUnit" transaction-type="RESOURCE_LOCAL"> 12 13 <!-- 描述信息.(可选) 14 <description> </description> 15 --> 16 <!-- javax.persistence.PersistenceProvider接口的一个实现类(可选) 17 <provider> </provider> 18 --> 19 <!-- Jta-data-source和 non-jta-data-source用于分别指定持久化提供商使用的JTA和/或non-JTA数据源的全局JNDI名称(可选) 20 <jta-data-source>java:/MySqlDS</jta-data-source> 21 <non-jta-data-source> </non-jta-data-source> 22 --> 23 <!-- 声明orm.xml所在位置.(可选) 24 <mapping-file>product.xml</mapping-file> 25 --> 26 <!-- 以包含persistence.xml的jar文件为基准的相对路径,添加额外的jar文件.(可选) 27 <jar-file>../lib/model.jar</jar-file> 28 --> 29 <!-- 显式列出实体类,在Java SE 环境中应该显式列出.(可选) 30 <class>com.domain.User</class> 31 <class>com.domain.Product</class> 32 --> 33 <!-- 声明是否扫描jar文件中标注了@Enity类加入到上下文.若不扫描,则如下:(可选) 34 <exclude-unlisted-classes/> 35 --> 36 <!-- 厂商专有属性(可选) --> 37 <properties> 38 <!-- hibernate.hbm2ddl.auto= create-drop / create / update --> 39 <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" /> 40 <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" /> 41 <property name="hibernate.connection.username" value="remote" /> 42 <property name="hibernate.connection.password" value="feiyue" /> 43 <property name="hibernate.connection.url" value="jdbc:mysql://192.168.182.131:3306/jpa" /> 44 <property name="hibernate.max_fetch_depth" value="3" /> 45 <property name="hibernate.show_sql" value="true" /> 46 <property name="hibernate.hbm2ddl.auto" value="update"/> 47 </properties> 48 49 </persistence-unit> 50 51 </persistence>
使用Maven搭建一个测试环境,Maven的使用在这里不再赘述,这里显示所依赖的jar包
<dependencies> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.1.9.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>4.1.9.Final</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.25</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.2</version> </dependency> </dependencies>
搭建一个测试项目 如图
Entity 实体类 User.java
1 package com.demo.bean; 2 3 // Generated 2016-3-22 17:50:11 by Hibernate Tools 4.0.0 4 5 import java.util.Date; 6 import javax.persistence.Column; 7 import javax.persistence.Entity; 8 import javax.persistence.GeneratedValue; 9 import static javax.persistence.GenerationType.IDENTITY; 10 import javax.persistence.Id; 11 import javax.persistence.Table; 12 import javax.persistence.Temporal; 13 import javax.persistence.TemporalType; 14 import javax.persistence.UniqueConstraint; 15 16 /** 17 * User generated by hbm2java 18 */ 19 @Entity 20 @Table(name = "user", catalog = "jpa", uniqueConstraints = @UniqueConstraint(columnNames = "phoneNo")) 21 public class User implements java.io.Serializable { 22 23 /** 24 * 25 */ 26 private static final long serialVersionUID = -2126972038126149900L; 27 private Long id; 28 private String firstName; 29 private String phoneNo; 30 private String lastName; 31 private Date birthday; 32 33 public User() { 34 } 35 36 public User(String firstName, String phoneNo, String lastName, Date birthday) { 37 this.firstName = firstName; 38 this.phoneNo = phoneNo; 39 this.lastName = lastName; 40 this.birthday = birthday; 41 } 42 43 @Id 44 @GeneratedValue(strategy = IDENTITY) 45 @Column(name = "id", unique = true, nullable = false) 46 public Long getId() { 47 return this.id; 48 } 49 50 public void setId(Long id) { 51 this.id = id; 52 } 53 54 @Column(name = "firstName", nullable = false, length = 45) 55 public String getFirstName() { 56 return this.firstName; 57 } 58 59 public void setFirstName(String firstName) { 60 this.firstName = firstName; 61 } 62 63 @Column(name = "phoneNo", unique = true, nullable = false, length = 45) 64 public String getPhoneNo() { 65 return this.phoneNo; 66 } 67 68 public void setPhoneNo(String phoneNo) { 69 this.phoneNo = phoneNo; 70 } 71 72 @Column(name = "lastName", nullable = false, length = 45) 73 public String getLastName() { 74 return this.lastName; 75 } 76 77 public void setLastName(String lastName) { 78 this.lastName = lastName; 79 } 80 81 @Temporal(TemporalType.DATE) 82 @Column(name = "birthday", nullable = false, length = 10) 83 public Date getBirthday() { 84 return this.birthday; 85 } 86 87 public void setBirthday(Date birthday) { 88 this.birthday = birthday; 89 } 90 91 @Override 92 public String toString(){ 93 return "User:"+ 94 "Id:"+id+" Name:"+firstName+" "+lastName+""; 95 } 96 97 }
Junit4 测试客户端,这里只简单的操作了保存与创建简单的HQL查询。JPATest.java
1 package com.demo.client; 2 3 import java.util.Date; 4 import java.util.List; 5 6 import javax.persistence.EntityManager; 7 import javax.persistence.EntityManagerFactory; 8 import javax.persistence.Persistence; 9 10 import org.junit.Test; 11 12 import com.demo.bean.User; 13 14 public class JPATest { 15 16 @Test 17 public void testSave(){ 18 EntityManagerFactory factory = Persistence.createEntityManagerFactory("TestJPAUnit"); 19 EntityManager em = factory.createEntityManager(); 20 em.getTransaction().begin(); 21 User user = new User(); //user为new状态 22 user.setBirthday(new Date()); 23 user.setFirstName("Khalid"); 24 user.setLastName("Khalid"); 25 user.setPhoneNo("+8618888888889"); 26 em.persist(user);//持久化user实例 27 em.getTransaction().commit();//提交事务 28 em.close(); 29 factory.close(); 30 } 31 32 @Test 33 public void testQuery(){ 34 EntityManagerFactory factory = Persistence.createEntityManagerFactory("TestJPAUnit"); 35 EntityManager em = factory.createEntityManager(); 36 @SuppressWarnings("unchecked") 37 List<User> user=em.createQuery("from User").getResultList(); 38 System.out.println(user); 39 } 40 }
运行客户端就可以啦~~其实并没有什么特别的- -。
3.Spring对JPA的支持
前人总结的很好,我就不在赘述了
Spring 框架对 JPA 提供的支持主要体现在如下几个方面:
-
首先,它使得 JPA 配置变得更加灵活。JPA 规范要求,配置文件必须命名为 persistence.xml,并存在于类路径下的 META-INF 目录中。该文件通常包含了初始化 JPA 引擎所需的全部信息。Spring 提供的 LocalContainerEntityManagerFactoryBean 提供了非常灵活的配置,persistence.xml 中的信息都可以在此以属性注入的方式提供。
-
其次,Spring 实现了部分在 EJB 容器环境下才具有的功能,比如对 @PersistenceContext、@PersistenceUnit 的容器注入支持。
-
第三,也是最具意义的,Spring 将 EntityManager 的创建与销毁、事务管理等代码抽取出来,并由其统一管理,开发者不需要关心这些,业务方法中只剩下操作领域对象的代码,事务管理和 EntityManager 创建、销毁的代码都不再需要开发者关心了。
4.使用SpringDataJPA 让一切变得最为简单
使用Spring Data JPA框架,它会帮助你简化Spring唯一没有控制到的DAO层,甚至让你完全不用编写DAO层繁琐的业务逻辑,你仅仅需要做的只有声明接口。
不多说直接上代码!!!
首先依旧是建库与表
1 CREATE DATABASE sdjpa; 2 USE sdjpa; 3 CREATE TABLE `user` ( 4 `id` bigint(20) NOT NULL AUTO_INCREMENT, 5 `firstName` varchar(45) NOT NULL, 6 `phoneNo` varchar(45) NOT NULL, 7 `lastName` varchar(45) NOT NULL, 8 `birthday` date NOT NULL, 9 PRIMARY KEY (`id`), 10 UNIQUE KEY `id_UNIQUE` (`id`), 11 UNIQUE KEY `phoneNo_UNIQUE` (`phoneNo`) 12 ) ENGINE=InnoDB DEFAULT CHARSET=UTF-8;
既然是Spring,applicationContext.xml内有关SpringDataJPA的相关配置
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xmlns:tx="http://www.springframework.org/schema/tx" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:jpa="http://www.springframework.org/schema/data/jpa" 6 xmlns:task="http://www.springframework.org/schema/task" 7 xmlns:aop="http://www.springframework.org/schema/aop" 8 xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd 9 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 10 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd 11 http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd 12 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd 13 http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd" 14 default-lazy-init="true"> 15 16 17 <!-- 如果spring用了jpa,并且类型为LocalContainerEntityManagerFactoryBean,则组件注册在此配置文件出现即可,其余配置文件可忽略 18 使用component来替代annotation 自动注册bean, 并保证@Required、@Autowired的属性被注入\ --> 19 <context:component-scan base-package="com.**.client,com.demo.dao"/> 20 21 <!-- 数据源--> 22 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> 23 <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 24 <property name="url" value="jdbc:mysql://192.168.182.131/sdjpa"/> 25 <property name="username" value="root" /> 26 <property name="password" value="feiyue" /> 27 </bean> 28 29 <!-- Hibernate对Jpa的实现 --> 30 <bean id="hibernateJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/> 31 32 <!-- 定义实体管理器工厂 33 Jpa配置 LocalContainerEntityManagerFactoryBean这个选项Spring扮演了容器的角色。完全掌管JPA --> 34 <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 35 <!-- 指定数据源 --> 36 <property name="dataSource" ref="dataSource"/> 37 <!-- 指定Jpa持久化实现厂商类,这里以Hibernate为例 --> 38 <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter"/> 39 <!-- 指定Entity实体类包路径 --> 40 <property name="packagesToScan" > 41 <array> 42 <value>com.**.bean</value> 43 </array> 44 </property> 45 <!-- 指定JPA属性;如Hibernate中指定是否显示SQL的是否显示、方言等 --> 46 <property name="jpaProperties"> 47 <props> 48 <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop> 49 <!-- EJB3规范的命名实现 例如 firstName 会被映射为 first_name 建议取消 50 <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop> 51 --> 52 <prop key="hibernate.show_sql">true</prop> 53 <prop key="hibernate.format_sql">true</prop> 54 <!-- 也可以配置为update 自动生成表 我这里在数据库已经建好了 就设置为validate--> 55 <prop key="hibernate.hbm2ddl.auto">update</prop> 56 </props> 57 </property> 58 </bean> 59 60 <!-- 重要配置:启用扫描并自动创建代理的功能 --> 61 <jpa:repositories base-package="com.**.dao" entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager"/> 62 63 64 65 <!-- Jpa 事务管理器 --> 66 <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 67 <property name="entityManagerFactory" ref="entityManagerFactory"/> 68 </bean> 69 70 <!-- 开启注解事务 --> 71 <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" /> 72 73 74 <!-- 启动对@AspectJ(面向切面)注解的支持 --> 75 <aop:aspectj-autoproxy /> 76 77 </beans>
依旧是Maven,这次的依赖库
1 <dependencies> 2 <dependency> 3 <groupId>log4j</groupId> 4 <artifactId>log4j</artifactId> 5 <version>1.2.17</version> 6 </dependency> 7 8 <dependency> 9 <groupId>com.fasterxml.jackson.core</groupId> 10 <artifactId>jackson-databind</artifactId> 11 <version>2.4.5</version> 12 </dependency> 13 14 <dependency> 15 <groupId>com.fasterxml.jackson.core</groupId> 16 <artifactId>jackson-annotations</artifactId> 17 <version>2.4.5</version> 18 </dependency>
以上是关于学习Spring Data Jpa的主要内容,如果未能解决你的问题,请参考以下文章
Spring Data 系列学习Spring Data JPA 基础查询
学习Spring-Data-Jpa(二十)---@EnableJpaRepositories