JPA学习 —— 第三课、spring整合JPA (完全版)
1.配置依赖
<!--版本控制 -->
<properties>
<mysql.version>5.1.34</mysql.version>
<spring.version>4.3.0.RELEASE</spring.version>
<hibernate.version>4.1.0.Final</hibernate.version>
<querydsl.version>4.1.4</querydsl.version>
<jackson.version>2.5.4</jackson.version>
</properties>
<dependencies>
<!-- javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<!-- Spring Framework -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring Framework end -->
<!-- c3p0 start -->
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- c3[0 end -->
<!--hibernate start -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<!--hibernate end -->
<!-- cglib start -->
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
<!-- cglib end -->
<!--mysql start -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--mysql end -->
<!--test start -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--test end -->
<!--common start -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
<!--common end -->
</dependencies>
这里比之前不完全版就是多了事务配置相关依赖
2.配置 applicationContext.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" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 配置自动扫描的包 -->
<context:component-scan base-package="com.ssj"></context:component-scan>
<!-- 配置数据源 -->
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<!-- 配置其他属性(省略) -->
</bean>
<!-- 配置 JPA 的 EntityManagerFactory -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"></bean>
</property>
<property name="packagesToScan" value="com.ssj.domain"></property>
<property name="jpaProperties">
<props>
<!-- 实体类命名规则 hibernate5以下有效-->
<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
<!-- 指定自动生成数据表的策略 -->
<prop key="hibernate.hbm2ddl.auto">update</prop>
<!-- 执行操作时是否在控制台打印SQL -->
<prop key="hibernate.show_sql">true</prop>
<!-- 是否对SQL进行格式化 -->
<prop key="hibernate.format_sql">true</prop>
<!-- 方言 -->
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
<!-- 其他配置 -->
</props>
</property>
</bean>
<!-- 配置事务 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"></property>
</bean>
<!-- 使用annotation定义事务 -->
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="true" />
<!-- #2通知:增强事务 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="get*" propagation="SUPPORTS" read-only="true" />
<tx:method name="find*" propagation="SUPPORTS" read-only="true" />
<tx:method name="select*" propagation="SUPPORTS" read-only="true" />
<tx:method name="load*" propagation="SUPPORTS" read-only="true" />
<!-- 其他采用默认事务方式 -->
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<!-- #3 切面:将切入点与通知点关联 -->
<aop:config proxy-target-class="true">
<aop:pointcut expression=" execution(* com.ssj.service..*(..))"
id="serviceMethod" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod" />
</aop:config>
</beans>
这里配置了事务控制,主要是监控service中的方法,通过方法前缀进行匹配。这样开发者就不用再管事务相关的内容了,全交给spring容器进行管理了。
3.实体类
package com.ssj.domain;
import java.util.Date;
import javax.persistence.*;
@Entity
@Table(name="employee")
public class Employee {
@Column(name="ID")
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Id
private Integer Id;
@Column(name="EMP_NAME")
private String empName;
@Column(name="EMP_BIRTH")
@Temporal(TemporalType.DATE)
private Date empBirth;
public Integer getId() {
return Id;
}
public void setId(Integer id) {
Id = id;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public Date getEmpBirth() {
return empBirth;
}
public void setEmpBirth(Date empBirth) {
this.empBirth = empBirth;
}
@Override
public String toString() {
return "Employee [Id=" + Id + ", empName=" + empName + ", empBirth="
+ empBirth + "]";
}
}
4.dao层
package com.ssj.dao;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
import com.ssj.domain.Employee;
@Repository
public class EmployeeDao {
@PersistenceContext
private EntityManager em;
public void save(Employee emp){
em.persist(emp);
}
}
5.service层
package com.ssj.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ssj.dao.EmployeeDao;
import com.ssj.domain.Employee;
@Service
public class EmployeeService {
@Autowired
private EmployeeDao employeeDao;
public void save(Employee emp){
employeeDao.save(emp);
}
}
6.测试类
package com.ssj.test;
import java.util.Date;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.ssj.domain.Employee;
import com.ssj.service.EmployeeService;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= "classpath:applicationContext.xml")
public class Test01 {
@Autowired
private EmployeeService employeeService;
@Test
public void test1(){
Employee emp = new Employee();
emp.setEmpName("李四");
emp.setEmpBirth(new Date());
employeeService.save(emp);
}
}
7.测试结果
数据库
总结:这里比之前不完全版就多了个事务的配置,将事务控制交给spring容器管理,开发者就不用关注事务相关内容。
开发时直接注入使用EntityManage,而不用再通过工厂方法获取。
@PersistenceContext
private EntityManager em;
注:之前用的hibernate5,但是有个配置是只在5以下才有效,所以改成了hibernate4
<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
命名规范的设置在hibernate5中改了,这里就不详细说了,有兴趣的朋友可以自己去研究下。
注:之前配置hibernate方言使用的是org.hibernate.dialect.MySQLMyISAMDialect就是告诉MySQL数据库使用MyISAM引擎。但是使用这个引擎创建的数据表总是生成不了外键,查了一些资料才知道:
MyISAM类型不支持事务处理和外键等高级处理,而InnoDB类型支持。MyISAM类型的表强调的是性能,其执行数度比InnoDB类型更快,但是不提供事务支持,而InnoDB提供事务支持以及外键等高级数据库功能。
所以后来就改为了使用InnoDB
<!-- 方言 -->
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
但是使用这个又出现个问题,新建表失败。
原来是我的MySql数据库美誉开启InnoDB的缘故。
开启方法:
修改MySQL安装目录下的my.ini,在skip-innodb前增加#,重启MySQL即可。
重启:
Windows
1.点击“开始”->“运行”(快捷键Win+R),cmd。
2.停止:输入 net stop mysql
3.启动:输入 net start mysql