在与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是一个用于日志系统的简单Facade,允许最终用户在部署其应用时使用其所希望的日志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
@Transactional
public 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";
}
最好希望大家也多点建议: