【JPA】
JPA是【Java Persistence API】的简称,中文名【Java持久层API】,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
Sun引入新的JPA ORM规范出于两个原因:
【1】简化现有Java EE和Java SE应用开发工作;
【2】Sun希望整合ORM技术,实现天下归一。目前比较成熟的 JPA 框架主要包括
【1】Oracle的Oracle AS TopLink(TopLink,是位居第一的Java对象关系可持续性体系结构,原署WebGain公司的产品,后被Oracle收购)
【2】Oracle 捐献给 Eclipse 社区的 EclipseLink
【3】Jboss 的 Hibernate EntityManager
【4】Apache 的 OpenJPA 等。
Spring 框架对 JPA 提供的支持主要体现在如下几个方面:
【1】它使得 JPA 配置变得更加灵活。
JPA 规范要求,配置文件必须命名为 persistence.xml,并存在于类路径下的META-INF 目录中。该文件通常包含了初始化 JPA 引擎所需的全部信息。Spring 提供的
LocalContainerEntityManagerFactoryBean 提供了非常灵活的配置,persistence.xml
中的信息都可以在此以属性注入的方式提供。【2】Spring 实现了部分在 EJB 容器环境下才具有的功能,
比如对 @PersistenceContext、@PersistenceUnit 的容器注入支持。【3】Spring 将 EntityManager
的创建与销毁、事务管理等代码抽取出来,并由其统一管理,开发者不需要关心这些,业务方法中只剩下操作领域对象的代码,事务管理和
EntityManager 创建、销毁的代码都不再需要开发者关心了。**
Spring Data JPA 框架,主要针对的就是 Spring 唯一没有简化到的业务逻辑代码。
使用Spring-data-JPA开发者连仅剩的实现持久层业务逻辑的工作都省了,唯一要做的,就只是声明持久层的接口,其他都交给 Spring Data JPA 来帮你完成!
【1】导入jar(spring-data-jpa的jar,mysql数据库连接的jar)
连版本都不用写了,父pom中已经定义了,此处只需要加入引用即可。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-jpaartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
【2】添加配置文件,数据库操作,四大配置肯定少不了
#配置数据库,使用SpringJPA
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: *********
driver-class-name: com.mysql.jdbc.Driver
【3】编写实体类,spring-data-jpa会自动创建一个数据库的表与之对应,,参考配置如下
package xatu.zsl.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import java.io.Serializable;
/**
* Created by zsl on 2017/9/4.
*/
@Entity(name = "user_test")//此标签即我要创建表,user_test
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id//主键
@GeneratedValue//自增
private long id;
//此属性与表中的【user_name】列对应,不可以为空
@Column(nullable = false, name = "user_name")
private String name;
//此属性与表中的【password】列对应,不可以为空
@Column(nullable = false)
private String password;
public User() {
}
public User(String name, String password) {
this.name = name;
this.password = password;
}
public static long getSerialVersionUID() {
return serialVersionUID;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
【4】写一个dao层的接口例如【UserRepositoryDao】
//JpaRepository,,第一个是
public interface UserRepositoryDao extends JpaRepository<User, Long> {
}
就这样可以玩?? 【回答】是的,就这样简单粗暴,,原因见下面细节分析【3】
到此,,SpringBoot对jpa的配置算是完成了。,下面用一下,体验非一般的感觉
测试代码片段如下:有点问题的代码
@GetMapping("/showuser")
public List showUsers() {
User user = new User("小鼠标一号", "password" + 5);
user.setId(4);
//增
System.out.println("============= 增 ===========");
userRepositoryDao.save(user);
//改
System.out.println("============= 改 ===========");
User user2 = new User("小鼠标二号", "password" + 5);
user.setId(4);
userRepositoryDao.save(user);
//查
System.out.println("============= 查 ===========");
// userRepositoryDao.delete(user);
List users = userRepositoryDao.findAll();
//删
System.out.println("============= 删 ===========");
User user1 = new User("小鼠标","mima");
userRepositoryDao.save(user1);
userRepositoryDao.delete(user1);
return users;
}
控制台打印出的sql如下
【1】增和删除,,事先需要通过ID,,select是为了防止重复插入,造成主键重复错误
【2】删除前的插入,是代码中专门放的为了测试使用。
package xatu.zsl.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import xatu.zsl.dao.UserRepositoryDao;
import xatu.zsl.domain.XatuZSLinfo;
import xatu.zsl.entity.Student;
import xatu.zsl.entity.User;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Created by zsl on 2017/9/2.
*/
@RestController
public class HelloController {
@RequestMapping("/springboot")
public String hello() {
return "Hello SpringBoot!";
}
@GetMapping("/student_json")
public List getStudentJson() {
List students = new ArrayList<>();
students.add(new Student("刘备", "1406001", 25));
students.add(new Student("张飞", "1406001", 20));
students.add(new Student("关羽", "1406001", 23));
students.add(new Student("曹操", "1405001", 24));
return students;
}
@Autowired
FilterRegistrationBean registration;
@GetMapping("/getname")
public Map getName() {
Map initParameters = registration.getInitParameters();
return initParameters;
}
@Autowired
private XatuZSLinfo properties;
@GetMapping("/getzsl")
public XatuZSLinfo getXatuZSLinfo() {
return properties;
}
@Autowired
private UserRepositoryDao userRepositoryDao;
@GetMapping("/showuser")
public List showUsers() {
User user = new User("小鼠标一号", "password" + 5);
//增
System.out.println("============= 增 ===========");
userRepositoryDao.save(user);
//改
System.out.println("============= 改 ===========");
user.setName("小鼠标更改");
userRepositoryDao.save(user);
//查
System.out.println("============= 查 ===========");
// userRepositoryDao.delete(user);
List users = userRepositoryDao.findAll();
//删
System.out.println("============= 删 ===========");
User user1 = new User("小鼠标","mima");
userRepositoryDao.save(user1);
userRepositoryDao.delete(user1);
return users;
}
}
这个增删改查看起来更规范一点。。
【1】@Entity注解,,起始主要就是一个属性,,表名。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package javax.persistence;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Entity {
String name() default "";
}
【2】 @Column注解内容稍微多一点。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package javax.persistence;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String name() default "";
//是唯一
boolean unique() default false;
//可以为空
boolean nullable() default true;
//可插入的
boolean insertable() default true;
//可更新的
boolean updatable() default true;
//列定义
String columnDefinition() default "";
String table() default "";
int length() default 255;
//精度
int precision() default 0;
//规模
int scale() default 0;
}
【3】springBoot为什么这么方便的使用JPA的方法,只需要继承JpaRepository接口,
下面是JpaRepository接口的内容,只需要设置相应的泛型,就可以很方便的使用(Spring容器中肯定有这个接口的实现。)
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.data.jpa.repository;
import java.io.Serializable;
import java.util.List;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.QueryByExampleExecutor;
@NoRepositoryBean
public interface JpaRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
List findAll();
List findAll(Sort var1);
List findAll(Iterable var1);
List save(Iterable var1);
void flush();
S saveAndFlush(S var1);
void deleteInBatch(Iterable var1);
void deleteAllInBatch();
T getOne(ID var1);
List findAll(Example var1);
List findAll(Example var1, Sort var2);
}