文章目录
jpa详解
- spirng data jpa是spring提供的一套简化JPA开发的框架。
- 按照约定好的【方法命名规则】写dao层接口,就可以在不写接口实现的情况下,实现对数据库的访问和操作。
- Spring Data JPA 可以理解为 JPA 规范的再次封装抽象,底层还是使用了 Hibernate 的 JPA 技术实现。
(一)jpa注解使用
注解 | 解释 |
---|---|
@Entity | 声明类为实体或表。 |
@Table | 声明表名。 |
@Basic | 指定非约束明确的各个字段。 |
@Embedded | 指定类或它的值是一个可嵌入的类的实例的实体的属性。 |
@Id | 指定的类的属性,用于识别(主键)。 |
@GeneratedValue | 指定如何标识属性可以被初始化,自动、手动、或从序列表中获得的值。 |
@Transient | 指定的属性,不会存储在数据库中。 |
@Column | 指定持久属性栏属性。 |
@SequenceGenerator | 指定在@GeneratedValue注解中的属性的指定值,创建序列。 |
@TableGenerator | 指定在@GeneratedValue批注指定属性的值发生器。 |
@AccessType | 访问类型。如果设置@AccessType(FIELD),则可以直接访问变量并且不需要getter和setter,但必须为public。如果设置@AccessType(PROPERTY),通过getter和setter方法访问Entity的变量。 |
@JoinColumn | 指定一个实体组织或实体的集合。这是用在多对一和一对多关联。 |
@UniqueConstraint | 指定的字段和用于主要或辅助表的唯一约束。 |
@ColumnResult | 参考使用select子句的SQL查询中的列名。 |
@ManyToMany | 定义了连接表之间的多对多,一对多的关系。 |
@ManyToOne | 定义了连接表之间的多对一的关系。 |
@OneToMany | 定义了连接表之间存在一个一对多的关系。 |
@OneToOne | 定义了连接表之间有一个一对一的关系。 |
@NamedQuery | 指定使用静态名称的查询。 |
(二)快速使用
1、导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
2、配置文件
# 格式化显示sql语句
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
3、项目结构
controller
:控制层entity
:实体类repository
:持久层( PS:又称dao层,在jpa中叫做repository,在mybatis中叫做mapper )
service
:业务逻辑层impl
:业务逻辑层的实现类
(三)创建项目结构
1、创建entity实体类
@Data注解需事先导入Lombok依赖使用
@Data
@Entity
@Table(name = "userinfo")
public class Userinfo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Integer id;
private String userName;
private String userPass;
private String userNick;
private Boolean enable;
2、创建repository持久层
只需继承JpaRepository接口,泛型选择实体类和id的类型
public interface UserinfoRepository extends JpaRepository<Userinfo, Integer> {
}
3、创建service业务层
public interface UserinfoService {
}
4、创建Impl实现类
实现service接口,添加@Service注解
@Service
public class UserinfoServiceImpl implements UserinfoService {
}
5、创建controller控制层
添加访问映射地址,使用@Autowired注入service
@RestController
@RequestMapping(value = "/userinfo")
public class UserinfoController {
@Autowired
private UserinfoService userinfoService;
}
(四)第一种:单表crud操作
1、Service
public interface UserinfoService {
// 增---添加新用户
void add(Userinfo userinfo);
// 删---根据id删除用户
void delById(Integer id);
// 改---根据id修改用户信息
void updataUserById(Userinfo userinfo);
// 查---返回全部用户
List<Userinfo> findAllUser();
}
2、Impl
实现接口后重写每个方法,使用@Autowired注入业务逻辑层UserinfoRepository并调用封装好的crud操作
@Service
public class UserinfoServiceImpl implements UserinfoService {
@Autowired
private UserinfoRepository userinfoRepository;
@Override
public void add(Userinfo userinfo) {
userinfoRepository.save(userinfo);
}
@Override
public void delById(Integer id) {
userinfoRepository.deleteById(id);
}
@Override
public void updataUserById(Userinfo userinfo) {
userinfoRepository.saveAndFlush(userinfo);
}
@Override
public List<Userinfo> findAllUser() {
List<Userinfo> userinfoList = userinfoRepository.findAll();
return userinfoList;
}
}
3、Controller
进入controller控制层书写地址映射调用方法,并使用前端测试工具检测
@RestController
@RequestMapping(value = "/userinfo")
public class UserinfoController {
@Autowired
private UserinfoService userinfoService;
// 增---Post增加新用户
@PostMapping("addUser")
public void addUser(Userinfo userinfo) {
userinfoService.add(userinfo);
}
// 删---Del根据Id删除一个用户
@DeleteMapping("/delUser/{id:\\d+}")
public void delUserById(@PathVariable Integer id) {
userinfoService.delById(id);
}
// 改---Put修改用户信息
@PutMapping("/updateUser")
public void updateByUserId(Userinfo userinfo) {
userinfoService.updataUserById(userinfo);
}
// 查---Get查询所有
@GetMapping("/findAllUser")
public List<Userinfo> findAllUser() {
return userinfoService.findAllUser();
}
}
(五)第二种:sql自定义脚本操作
1、持久层repository
- 自定义方法,加上@Query注解和自定义的sql语句
- @Modifying涉及了数据库修改操作,和@Query一并使用
sql语句中使用 " :" 接收参数,传参需要使用@Param(“ 参数值 ”)。
sql语句中使用 " ?" 接收参数,传参需要注意下顺序不可乱。
// 自定义sql更新昵称,:接受参数
@Modifying
@Query(value = "update userinfo set user_nick = :userNick where id = :id", nativeQuery = true)
void updateUserNickByUserId(@Param("id") Integer id, @Param("userNick") String uesrNick);
// 自定义sql更新昵称,?接受参数
@Query(value = "update userinfo set user_nick = ?where id = ?", nativeQuery = true)
void updateUserNickByUserId( String uesrNick , Integer id );
2、控制层controller
// 改---Put根据用户ID修改昵称
@PutMapping("/updateUser")
public void updateByUserId(@RequestParam Integer id, @RequestParam String userNick) {
userinfoRepository.updateUserNickByUserId(id, userNick);
}
(六)自动关系映射
1、一对一,@OneToOne
首先需要两个表的实体类,主表不包含次表外键属性,次表有一列为主表的外键属性
添加question表的实体类Entity
添加@OneToOne注解表示一对一关系映射
使用@JoinColumn为次表中关联主表的外键字段
@Entity
@Data
@Table(name = "question")
public class Question {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Integer id;
private String title;
@OneToOne
@JoinColumn( name = "userinfo_id" )
private Userinfo userinfo;
}
2、一对多,多对一,@OneToMany、@ManyToOne
一端(Userinfo)使用@OneToMany。
一端(Userinfo)使用@OneToMany注释的mappedBy="userinfo"属性表明userinfo是关系被维护端。
@Setter
@Getter
@Entity
public class Userinfo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Integer id;
private String userName;
private String userPass;
private String userNick;
private Boolean enable;
@OneToMany(mappedBy = "userinfo")
private List<Question> questionList;
}
多端(Question)使用@ManyToOne。
@ManyToOne表明Question是多端,@JoinColumn设置在Question表中的关联字段(外键)。
@Entity
@Setter
@Getter
public class Question {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Integer id;
private String title;
@ManyToOne
@JsonIgnore
@JoinColumn(name = "userinfo_id")
private Userinfo userinfo;
}
(七)第三种:jpa关键字自定义方法
jpa封装好的方法肯定是不能满足我们的业务需求,有需求是按照特定的单词对方法名进行定义,那么Spring就会对我们写的方法名进行解析,生成对应的实例进行数据处理。
关键字 | 使用示例 | 文字说明 |
---|---|---|
And | findByNameAndPwd | 根据用户名和密码查询 |
Or | findByNameOrSex | 根据用户名和性别查询 |
Is,Equals | findById,findByIdEquals | 根据ID查询 |
Between | findByIdBetween | 根据ID范围区间查询 |
LessThan | findByIdLessThan | 查询大于此ID的 |
LessThanEquals | findByIdLessThanEquals | 查询大于等于此ID的 |
GreaterThan | findByIdGreaterThan | 查询小于此ID的 |
GreaterThanEquals | findByIdGreaterThanEquals | 查询小于等于此ID的 |
IsNull | findByNameIsNull | 查询ID是否为null |
isNotNull,NotNull | findByNameNotNull | 查询ID是否不为null |
Like | findByNameLike | 根据用户名模糊查询 |
NotLike | findByNameNotLike | 不包括该用户名模糊查询 |
StartingWith | findByNameStartingWith | 确定首字用户名模糊查询 |
EndingWith | findByNameEndingWith | 确定尾字用户名模糊查询 |
Containing | findByNameContaining | 包含此字用户名模糊查询 |
OrderBy | findByIdOrderByXDesc | 根据ID查询X列倒序排序 |
Not | findByNameNot | 查找非此用户名的 |
In | findByIdIn(Collection<?> c) | 根据ID查询集合内的 |
NotIn | findByIdNotIn(Collection<?> c) | 根据ID查询不在集合内的 |
True | findByEnableTrue | 查询Enable列是否为真 |
False | findByEnableFalse | 查询Enable列是否为假 |
1、例子说明
// 根据ID倒序返回启动状态
List<Userinfo> findByEnableIsTrueOrderByIdDesc();
// 根据用户名模糊查询
List<Userinfo> findByUserNameLike(String name);
- 省略业务实现层,DDDD…
控制层调用,模糊查询带上“ % ”,意为包含用户的全部查出。
@GetMapping("/findLike")
public List<Userinfo> findLike(String name){
List<Userinfo> userinfoList=userinfoService.findLike("%"+name+"%");
return userinfoList;
}
总而言之,jpa对于数据的查询,主要有三点:
- 通过repository继承JpaRepository接口实现的crud操作。
- 通过jpa关键字的组合来自定义方法。
- 通过自定义sql语句脚本自定义方法。