Spring中使用JPA
1.配置persistence.xml,在类路径下META-INF/persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistencehttp://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
<persistence-unit name="jpaPU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<!--
<property name="hibernate.dialect" value=" org.hibernate.dialect.Oracle9iDialect"/>
<property name="hibernate.connection.driver_class" value="oracle.jdbc.driver.OracleDriver"/>
<property name="hibernate.connection.username" value="scott"/>
<property name="hibernate.connection.password" value="123456"/>
<property name="hibernate.connection.url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
<property name="hibernate.max_fetch_depth" value="3"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name = "hibernate.show_sql" value = "true"/>
<property name = "hibernate.format_sql" value = "true"/>
-->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
<property name="hibernate.connection.driver_class" value="org.gjt.mm.mysql.Driver"/>
<property name="hibernate.connection.username" value="root"/>
<property name="hibernate.connection.password" value="123456"/>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/hib?useUnicode=true&characterEncoding=UTF-8"/>
<property name="hibernate.max_fetch_depth" value="3"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name = "hibernate.show_sql" value = "true"/>
<property name = "hibernate.format_sql" value = "true"/>
</properties>
</persistence-unit>
</persistence>
2.beans.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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!--使用注解时需要用到它,如@Resource,@PersistenceContext 等注解-->
<context:annotation-config/>
<!-- 配置实体管理器工厂,引入持久化单元-->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="jpaPU"/>
</bean>
<--使用Spring提供的适配器:JPA事务管理器-->
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<!--使用Spring声明式事务管理-->
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="ps" class="com.service.impl.PersonServiceBean"/>
</beans>
3.编写实体Bean和业务Bean
package com.domin;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import org.hibernate.annotations.GenericGenerator;
@Entity
public class Person implements java.io.Serializable{
@Id
@GeneratedValue
private Integer id;
@Column(length=10,nullable=false)
private String name;
public Person(String name) {
// TODO Auto-generated constructor stub
this.name=name;
}
public Person() {
// TODO Auto-generated constructor stub
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public void setId(Integer id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
}
业务方法接口
package com.service;
import java.util.List;
import com.domin.Person;
public interface IPersonService {
public void save(Person person);
public void update(Person person);
public void delete(Integer id);
public Person getPerson(Integer id);
public List<Person> getPersons();
}
业务方法实现:
package com.service.impl;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.domin.Person;
import com.service.IPersonService;
@Transactional
public class PersonServiceBean implements IPersonService {
@PersistenceContext EntityManager em;//注入实体管理器
public void save(Person person){
em.persist(person);
}
public void update(Person person){
em.merge(person);
}
public void delete(Integer personid){
em.remove(em.getReference(Person.class, personid));
}
@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
public Person getPerson(Integer personid){
return em.find(Person.class, personid);
}
@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
@SuppressWarnings("unchecked")
public List<Person> getPersons(){
return em.createQuery("select o from Person o").getResultList();
}
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
IPersonService personService =(IPersonService) context.getBean("personService");
personService.save(new Person("小叶2"));
}
}
其实,使用@PersistenceContext EntityManager em;是为了和@Transactional配合使用。因为声明式事务管理应用AOP技术,要在业务方法执行前后对它进行拦截以进行事务处理,包括事务的打开,关闭,提交,回滚等操作。所以就要求业务方法中操作数据库的对象不是自己新建Connection连接对象,而是也能使用当前线程中的连接对象(如果已经有的话)。其实,Spring自己提供的JdbcTemplate,JpaTemplate,HibernateTemplate类获取连接对象时都要先从当前线程中查找,所以可以配合声明式事务处理使用。
Spring实现AOP的方式不外乎使用JDK自带的动态代理技术和cglib代理。
使用动态代理时,必须使用被代理对象的接口来调用方法。
使用cglib,则可以直接使用代理对象来调用方法。
也就是说,由于上面的业务Bean实现了某一个接口,那么Spring会使用动态代理的方式,则只能使用它的接口。
IPersonService personService =(IPersonService) context.getBean("personService");
这句若改为
PersonServiceBean ps=(PersonServiceBean)apc.getBean("ps");
就会报错。
java.lang.ClassCastException: $Proxy12 cannot be cast to com.service.impl.PersonServiceBean
但是,如果业务Bean不实现某个接口,则Spring会使用cglib创建它的子类,使用
PersonServiceBean ps=(PersonServiceBean)apc.getBean("ps");是正确的。