在与spring 与jpa(Java持久化API【java Persistence API】)整合之前,最好先去学习一下jpa的一些要求,这样可以在整合的时候,剩下更多时间。
在spring 中使用Jpa 的第一步是要在spring应用上下文中将实体管理器工厂安照bean的形式来进行配置。
1配置实体类管理工厂
jpa中要获取EntityManager 实例需要通过EntityManagerFactory来获取创建。而在JPA中有两种实体管理器①应用程序管理类型(Application-managed)②容器管理类型的(Container-managed),这里我们使用②,因为这种最适合Java EE容器。两种实体管理器工厂实现同一个接口:EntityManager。而主要区别在于两者对EntityManager的创建上,①是由EntityManagerFactory创建,②则是通过PersistenceProvider的CreateEntityManagerFactory()创建。①对应的 spring中的工厂是:LocalEntityManagerFactoryBean生产EntitymanagerFactory;②对应的LocalContainerEntityManagerFactoryBean。
2实例
(1)这里使用maven来管理项目pom.xml:
使用logback+slf4j来进行日志的管理,在百度百科中:SLF4J,即简单日志门面(Simple Logging Facade for Java),不是具体的日志解决方案,它只服务于各种各样的日志系统。按照官方的说法,SLF4J是一个用于日志系统的简单,允许最终用户在部署其应用时使用其所希望的日志System,在官网中:可用于各种日志框架(例如java.util.logging,logback,log4j),允许最终用户在部署 时插入所需的日志记录框架。
<dependency>
<groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.12</version> </dependency><dependency>
<groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.1.2</version> </dependency> <!-- 对slf4j的整合 --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.2</version> </dependency>
spring配置
<dependency>
<groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.9.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>4.3.9.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.3.9.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.9.RELEASE</version> </dependency>
jpa:这里使用hibernate作为jpa的实现
<dependency>
<groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>4.3.9.RELEASE</version></dependency><!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core --><dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.3.11.Final</version></dependency><dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>4.3.11.Final</version> </dependency>
数据库
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-dbcp2</artifactId> <version>2.1.1</version> </dependency>
如果是web项目也可以加入springweb
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.3.9.RELEASE</version></dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --><dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.9.RELEASE</version></dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency>
2配置
logback简单配置,jdbc.properties再次省略
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- encoder 默认配置为PatternLayoutEncoder --> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="STDOUT" /> </root> </configuration>
spring-dao.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:tx="http://www.springframework.org/schema/tx" 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/tx http://www.springframework.org/schema/tx/spring-tx.xsd> <context:property-placeholder location="classpath:jdbc.properties"/> <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"> <property name="driverClassName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean>
//代替了jpa的xml配置 <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="packagesToScan" value="com.spring.entity"/> <property name="dataSource" ref="dataSource"/> <property name="persistenceProvider"> <bean class="org.hibernate.jpa.HibernatePersistenceProvider"></bean> </property> <property name="jpaProperties"> <props> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> </props> </property> </bean> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </bean>
//事物,在jpa中必须在方法上加上事物处理 <tx:annotation-driven transaction-manager="transactionManager"/> <context:annotation-config/> <context:component-scan base-package="springJdbc.controller,com.spring.controller,com.spring.jpa"/></beans>
dao
@Repository
@Transactionalpublic class JpaDao { Logger log = LoggerFactory.getLogger(this.getClass());//摘自spring实战,这里方便大家有更深的了解
//有的地方可能是@PersistenceUnit,
//private EntityManagerFactory entityManagerFactory;
//调用的时候还要 entityManagerFactory.createEntityManager().persist(user);
//需要注意的是EntityManagerFactory属性, 它//使用了@PersistenceUnit注解, 因此, Spring会//将EntityManagerFactory注入到Repository之中。 有了//EntityManagerFactory之后, JpaDao 的方法//就能使用它来创建EntityManager了, 然后EntityManager可以//针对数据库执行操作。 每次我们都要create一次,还要重新创建一个EntityManager。//这里的问题在于EntityManager并不是线程安全的, 一般来讲并不//适合注入到像Repository这样共享的单例bean中。 但是, 这并不意味//着我们没有办法要求注入EntityManager。 如下的程序清单展现了//如何借助@PersistentContext注解为JpaDao //设置EntityManager。 //这里的真相是@PersistenceContext并不会真正注//入EntityManager——至少, 精确来讲不是这样的。 它没有将真正//的EntityManager设置给Repository, 而是给了它一//个EntityManager的代理。 真正的EntityManager是与当前事务 //相关联的那一个, 如果不存在这样的EntityManager的话, 就会创//建一个新的。 这样的话, 我们就能始终以线程安全的方式使用实体管//理器 //另外, 还需要了解@PersistenceUnit和@PersistenceContext//并不是Spring的注解, 它们是由JPA规范提供的
@PersistenceContext private EntityManager entityManagerFactory; public void add(User user){ log.info("user name:{}",user.getName()); entityManagerFactory.persist(user); entityManagerFactory.close(); }public void select (){
String sql = "select * from user"; Query query = entityManagerFactory.createNativeQuery(sql); List list=query.getResultList(); for(int i=0;i<list.size();i++){ Object[] obj = (Object[])list.get(i); System.out.println(obj[0]+":"+obj[1]+obj[2]); } entityManagerFactory.close(); }}
实体
@Entity
public class User {@Id
@GeneratedValue private Integer id; private String name; private String password;略getset方法
简单的controller测试
@Controller
@RequestMapping("/jpa")public class JpaController{
@Autowired
private JpaDao jpaDao; @Autowired private UserReporstory userRes; @RequestMapping(value="/add" ,method=RequestMethod.GET) public String add(){ jpaDao.select(); return "index.jsp"; } @RequestMapping(value="/add3" ,method=RequestMethod.GET) public String add3(){ User user = new User(); user.setName("mdl"); user.setPassword("mdl"); jpaDao.add(user); return "index.jsp"; }
3在编写spring与jpa的时候,要写好多的充分代码要是用spring data jpa就方便多了
在maven中加入
<dependency>
<groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>1.10.5.RELEASE</version></dependency>
在spring配置文件中
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd<jpa:repositories base-package="springdata.dao" repository-impl-postfix="Hill" />
写一个接口继承JpaRepository,User是映射的对象,Integer是主键的类型
public interface UserRepository extends JpaRepository<User, Integer>{
//它还会继承18个执行持久化操作的通用方法 ,此时, 你可能会想下一步就该编写一个类实现 ,如果真是这样就没有必要用spring data了//如果基本方法不能满足你的要求,你可以自定义
User findByName(String name);
//Spring Data允许在方法名中使用四种动词: get、 read、 find和count ,又想了解的,可以查阅相关知识
这里还是推荐jpa结合spring data jpa,使用jpa实现比较复杂的逻辑
}
public class UserRepositoryHill implements UserTop{
//jpa的实现。可以参考上面的jpa实现的方法
}
注意, UserRepositoryHill 并没有实现 UserRepository接口。 Spring Data JPA负责实现这个接口。 UserRepositoryHill (将它与Spring Data的Repository关联起来的是它的名字) 实现了UserTop, 它如下所示:
public interface UserTop(){
void top();
}我们还需要确保top()方法会被声明在UserRepository接口中。 要实现这一点, 避免代码重复的简单方式就是修改UserRepository, 让它扩展UserTop:
public interface UserRepository extends JpaRepository<User, Integer>,UserTop{}
注意UserRepositoryHill 中的Hill,是在spring data jpa中配置的<jpa:repositories base-package="springdata.dao" repository-impl-postfix="Hill" />这里你可以随便制定
测试
@Autowired
private UserReporstory userRes;@RequestMapping(value="/add1" ,method=RequestMethod.GET)
public String add1(){ User user = new User(); user.setName("hary"); user.setPassword("hary"); userRes.save(user); return "index.jsp"; }
最好希望大家也多点建议: