项目中有用到spring data jpa,简单看了一下,在基础的数据库操作上,要比mybatis好用,简化了持久层的操作,使coder可以专注于业务逻辑的实现。网上参考了一些文章,实际coding的时候还是出好多错误。这里通过CRUD,记录摸索填坑的过程。详细的概念可以参考文末的文章。
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>spring-jpa-webdisplay-name>
<servlet>
<servlet-name>appServletservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:spring.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>appServletservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
web-app>
特别说明,spring-data-jpa要用版本1.9.0.RELEASE。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>org.wxs.springgroupId>
<artifactId>spring-jpa-webartifactId>
<packaging>warpackaging>
<version>0.1.0version>
<properties>
<spring_version>4.3.0.RELEASEspring_version>
<spring_jpa_version>1.9.0.RELEASEspring_jpa_version>
<spring_data_commons_version>1.12.6.RELEASEspring_data_commons_version>
<hibernate.version>4.2.5.Finalhibernate.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.datagroupId>
<artifactId>spring-data-jpaartifactId>
<version>${spring_jpa_version}version>
dependency>
<dependency>
<groupId>org.hibernategroupId>
<artifactId>hibernate-coreartifactId>
<version>${hibernate.version}version>
dependency>
<dependency>
<groupId>org.hibernategroupId>
<artifactId>hibernate-entitymanagerartifactId>
<version>${hibernate.version}version>
dependency>
<dependency>
<groupId>org.hibernategroupId>
<artifactId>hibernate-ehcacheartifactId>
<version>${hibernate.version}version>
dependency>
<dependency>
<groupId>org.apache.tomcatgroupId>
<artifactId>tomcat-jdbcartifactId>
<version>7.0.54version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.35version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-coreartifactId>
<version>${spring_version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-beansartifactId>
<version>${spring_version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webartifactId>
<version>${spring_version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>${spring_version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>${spring_version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-ormartifactId>
<version>${spring_version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>${spring_version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>${spring_version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-context-supportartifactId>
<version>${spring_version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>${spring_version}version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
<dependency>
<groupId>org.apache.tomcatgroupId>
<artifactId>tomcat-servlet-apiartifactId>
<version>8.0.3version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.apache.tomcatgroupId>
<artifactId>jsp-apiartifactId>
<version>6.0.39version>
<scope>providedscope>
dependency>
<dependency>
<groupId>jstlgroupId>
<artifactId>jstlartifactId>
<version>1.2version>
dependency>
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>jsp-apiartifactId>
<version>2.1version>
<scope>providedscope>
dependency>
dependencies>
project>
<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:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd"
default-lazy-init="true">
<description>Spring公共配置description>
<context:component-scan base-package="com.wx.jpa"/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter"/>
<property name="packagesToScan" value="com.wx.jpa.entities"/>
<property name="jpaProperties">
<props>
<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategyprop>
props>
property>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
property>
bean>
<bean id="hibernateJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="true"/>
<property name="database" value="MYSQL"/>
<property name="databasePlatform" value="org.hibernate.dialect.MySQLInnoDBDialect"/>
bean>
<jpa:repositories base-package="com.wx.jpa.repository" transaction-manager-ref="transactionManager"
entity-manager-factory-ref="entityManagerFactory"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
bean>
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
bean>
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxActive" value="${jdbc.pool.maxActive}"/>
<property name="maxIdle" value="${jdbc.pool.maxIdle}"/>
<property name="minIdle" value="0"/>
<property name="defaultAutoCommit" value="true"/>
bean>
<context:property-placeholder location="classpath:jdbc.properties"/>
beans>
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/seckill?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=admin
jdbc.pool.maxIdle=5
jdbc.pool.maxActive=10
新建表 user
新建实体类User
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "name")
private String name;
@Column(name = "password")
private String password;
@Column(name = "birthday")
private Date birthday;
/**
* The default constructor only exists for the sake of JPA. You won’t use it directly, so it is designated as protected.
*/
protected User() {
}
public User(String name, String password, Date birthday) {
this.name = name;
this.password = password;
this.birthday = birthday;
}
getter、setter省略
创建接口UserRepository
public interface UserRepository extends JpaRepository<User,Integer> {
}
@Test
public void test1(){
User user=new User("SL1","123",new Date());
userRepository.save(user);
System.out.println("save success");
}
@Test
public void test2(){
for (User user:userRepository.findAll()) {
System.out.println(user);
}
System.out.println("search all success");
}
查询结果
User{id=9, name='SL1', password='123', birthday=2017-01-12 00:00:00.0}
User{id=10, name='SL1', password='123', birthday=2017-01-12 00:00:00.0}
User{id=11, name='SL1', password='123', birthday=2017-01-13 00:00:00.0}
search all success
@Test
public void test3(){
System.out.println(userRepository.findOne(9));
System.out.println("search one success");
}
查询结果
User{id=9, name='SL1', password='123', birthday=2017-01-12 00:00:00.0}
search one success
如果有Id,jpa会认为是更新,没有则是新增。
@Test
public void test4(){
User user=new User("SL99","123",new Date());
user.setId(9);
userRepository.save(user);
test3();
System.out.println("update success");
}
更新成功
User{id=9, name='SL99', password='123', birthday=2017-01-13 00:00:00.0}
search one success
update success
@Test
public void test5(){
userRepository.delete(9);
test3();
System.out.println("delete success");
}
删除成功
null
search one success
delete success
java.lang.AbstractMethodError: org.springframework.data.repository.core.support.RepositoryFactorySupport.getTargetRepository(Lorg/springframework/data/repository/core/RepositoryInformation;)Ljava/lang/Object;
Deleting the spring-data-commons and changing the spring-data-jpa version to 1.9.0.RELEASE like @peeskillet said now works fine!
这也是为什么pom文件中spring-data-jpa要配置1.9.0.RELEASE的版本。
java.lang.IllegalArgumentException: Not an managed type: class java.lang.Object
Dao层的接口继承JpaRepository的时候加上泛型。添加域对象类型和主键类型。
public interface UserRepository extends JpaRepository
org.hibernate.InstantiationException: No default constructor for entity: com.wx.jpa.entities.User
新增、根据ID查询这2个方法不会报这个异常。
Hibernate在创建Bean的时候需要User的默认构造方法。Accessing Data with JPA中也有讲到。
You also have two constructors. The default constructor only exists
for the sake of JPA. You won’t use it directly, so it is designated
as protected. The other constructor is the one you’ll use to create
instances of Customer to be saved to the database.
欢迎感兴趣的同学指正。。。
参考:
【原创】纯干货,Spring-data-jpa详解,全方位介绍。
了解 Spring Data JPA