这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战
前言
方向不对努力白费
平常你也付出了很多的时间,但就是没有得到多少收益。就像有时候很多小伙伴问我,我是该怎么学一个我没接触过的内容。我的个人经验非常建议,先不要学太多理论性的内容,而是尝试实际操作下,把要学的内容做一些Demo案例出来。这有点像你买了个自行车是先拆了学学怎么个原理,还是先骑几圈呢?哪怕摔了跟头,但那都是必须经历后留下的经验。
前面讲了SpringDataJpa持久层操作,请查看博主的SpringDataJpa系列文章。欢迎关注!
创建实体
在com.cyj.springboot.entity下创建Student类,如下:
package com.cyj.springboot.entity;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.springframework.format.annotation.DateTimeFormat;
/*** 由于数据库没有数据表@Entity创建实体
* @table(name="studenttb")在springbootjpahelloworlddb里面自动创建表名为studenttb的数据表 */
@Entity
@Table(name="studenttb")
public class Student {
@Id
//实体类的主键
@GeneratedValue
//自动增长列
private Integer studentId;
//学生编号
private String studentName;
//学生姓名
private Integer studentAge;
//学生年龄
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private Date studentBirthday;
//学生出生年月
public Integer getStudentId() {
return studentId;
}
public void setStudentId(Integer studentId) {
this.studentId = studentId;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public Integer getStudentAge() {
return studentAge;
}
public void setStudentAge(Integer studentAge) {
this.studentAge = studentAge;
}
public Date getStudentBirthday() {
return studentBirthday;
}
public void setStudentBirthday(Date studentBirthday) {
this.studentBirthday = studentBirthday;
}
@Override
public String toString() {
return "Student [studentId=" + studentId + ", studentName=" + studentName + ", studentAge=" + studentAge + ", studentBirthday=" + studentBirthday + "]";
}
}
下面总结一下JPA中常用的注解标签
- @Entity:@Entity标记在类名上面,作为实体类的标识。
- @Table:当实体类与其映射的数据库表名不同名时需要使用 @Table 标注说明,该标注与 @Entity 标注并列 使用,置于实体类声明语句之前,可写于单独语句行,也可与声明语句同行。 @Table 标注的常用选项是 name,用于指明数据库的表名。 @Table标注还有一个两个选项 catalog 和 schema 用于设置表所属的数据 库目录或模式,通常为数据库名。uniqueConstraints选项用于设置约束条件,通常不须设置。
- @Id:@Id设置对象表示符,标识的实体类的属性映射对应表中的主键。
- @GeneratedValue:设置标识符的生成策略,常与@Id一起使用。参数:strategy指定具体的生成策略
- 方式一:@GeneratedValue(strategy=GenerationType.AUTO) 也是默认策略, 即写成@GeneratedValue也可;类似于hibernate的native策略,生成方式取决于底层的数据库。
- 方式二:@GeneratedValue(strategy = GenerationType.IDENTITY)指定“自动增长”策略,适用于MySQL;
- 方式三:@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = “seq_tbl_person”)指 定“序列”策略,常用于Oracle,其中generator表示生成器的名字。而且还要指定@SequenceGenerator(name = “seq_tbl_person”, sequenceName = “seq_tbl_person”, allocationSize = 1)注解配合使用。其中name指定生成器的名字(与generator的值一样),sequenceName指定数据 库中定义序列的名字,allocationSize指定序列每次增长1。
- @Column:描述数据库表中该字段的定义,具有一下属性。
- name:表示数据库表中该字段的名称,默认情形属性名称一致。
- nullable:表示该字段是否允许为null,默认为true。
- unique:表示该字段是否是唯一标识,默认为false。
- length:表示该字段的大小,仅对String类型的字段有效。
- insertable:表示在ORM框架执行插入操作时,该字段是否应出现- INSETRT语句中,默认为true。
- updateable:表示在ORM框架执行更新操作时,该字段是否应该出现在UPDATE语句中,默认为true。 对于一经创建就不可以更改的字段,该属性非常有用,如对于birthday字段。
- columnDefinition:表示该字段在数据库中的实际类型。通常ORM框架可以根据属性类型自动判断数据 库中字段的类型,但是对于Date类型仍无法确定数据库中字段类型究竟是DATE,TIME还是 TIMESTAMP。此外,String的默认映射类型为VARCHAR,如果要将String类型映射到特定数据库的 BLOB或TEXT字段类型,该属性非常有用。
- @OrderBy:在加载数据的时候可以为其指定顺序。
- @Transient:表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性。 如果一个属性并非数据库表的字段映射。就务必将其标示为@Transient。否则。ORM框架默认其注解为@Basic
自定义查询语句(JPQL)
这种查询可以声明在Repository方法中,摆脱像命名查询那样的约束,将查询直接在相应的接口方法中声明,结构更清晰,这是SpringDataJpa的特有实现
使用@Query自定义查询
- 前面介绍的获取数据的方式都没有使用到任何的HQL(Hibernate Query Language)语句,那些方法已经可以满足 很多需求,也有时候会觉得方法名太长不太方便,下面介绍一下使用Hql方式获取数据。
例如根据具体名字查询学生信息,在StudentRepository类中添加如下方法:
@Query("select s from Student s where s.studentName = ?1")
Student findByStudentName(String studentName);
在Controller调用,如下
/***
* http://localhost:8090/findStudentsByName?name=刘三
* @param name
* @return */
@RequestMapping("/findStudentsByName")
public Object findStudentBystudentName(String name) {
Student student = repository.findByStudentName(name);
return student;
}
@Query与 @Modifying的联合使用
这两个annotation一起声明,可定义个性化更新操作,例如只涉及某些字段更新时最为常用,示例如下:
- a.如果要修改学生姓名,首先在StudentRepository下添加如下代码:
@Transactional
@Modifying
@Query("update Student s set s.studentName=?1 where s.studentId=?2")
int setFixedStudentNameFor(String studentName,int studentId);
- b.在StudentController里面进行调用,代码如下:
/***
* http://localhost:8090/setStudent?name=lucy&id=2
* @param name
* @return */
@RequestMapping("/setStudent")
public Object setStudentByName(String name,int id) {
int i = repository.setFixedStudentNameFor(name,id);
Map<String,Object> map=new HashMap<String,Object>();
if(i>0) {
map.put("success", true);
}else {
map.put("success", false); }return map;
}
}
索引参数与命名参数
- 索引参数如下例代码所示,索引值从1开始,查询中 ”?X” 个数需要与方法定义的参数个数相一致,并且顺序也 要一致
@Transactional
@Modifying
@Query("update Student s set s.studentName=?1 where s.studentId=?2")
int setFixedStudentNameFor(String studentName,int studentId);
- 命名参数(推荐使用这种方式) 可以定义好参数名,赋值时采用@Param("参数名"),而不用管顺序。如下所
示:
- a.在StudentRepository里添加如下代码:
@Query("select s from Student s where s.studentName like %:studentName% ")
List<Student> queryByname(@Param(value = "studentName") String studentName);
- b.在StudentController里面进行调用,代码如下:
/***
* http://localhost:8090/queryByname?name=刘
* @param name
* @return */
@RequestMapping("/queryByname")
public Object queryByname(String name) {
List<Student> student = repository.queryByname(name);
return student;
}
好了到这里也该结束了,下一篇讲解--SpringDataJpa的原生Sql查询,各位要自己多动手才能学到真正的东西。加油各位
最后
-
更多参考精彩博文请看这里:《陈永佳的博客》
-
喜欢博主的小伙伴可以加个关注、点个赞哦,持续更新嘿嘿!