spring 集成jpa 以及spring data与jpa

在与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允许在方法名中使用四种动词: getreadfindcount ,又想了解的,可以查阅相关知识

这里还是推荐jpa结合spring data jpa,使用jpa实现比较复杂的逻辑

}

public class UserRepositoryHill implements UserTop{

//jpa的实现。可以参考上面的jpa实现的方法

}

注意, UserRepositoryHill 并没有实现
 UserRepository接口。 Spring Data JPA负责实现这个接
口。 UserRepositoryHill (将它与Spring DataRepository
联起来的是它的名字) 实现了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";
}

  最好希望大家也多点建议:

posted @ 2017-09-15 22:45  引路人®  阅读(300)  评论(0编辑  收藏  举报