转载自 天问雪狼
文档参考:
JPA之@Generated注解 jpa 表生成器@ TableGenerato
oracle 自增序列实现 可作为主键 Orcle 主键自增(序列sequence、触发器trigger、主键primary)
Spring data 简介 spring data jpa使用详解
Hibernate 实体类 表关系 注解 大全 Spring注解之实体类常用注解
SpringDataJpa——JpaRepository增删改查
1.id的两种增长方式
自增主键: mysql的auto_increment SQLServer的identity
序列: oracle的sequence
自增主键是数据插入的时候自动生成主键数值
按照序列自增,需要创建序列,将序列设为主键后,才能向表内插入数据
2.框架实现自增主键
使用 JDBC需要拼SQL语句
PerparedStatement不能直接存一个对象,只能把对象里面的每个字段拿出来拼到SQL里面
引入框架hibernate,可以直接操作对象,而不是拼SQL语句了(拼SQL语句这件事hibernate已经帮你做掉了)
java操作的是对象,数据库里面存的是实体和实体之间的关系,hibernate把这两者的关系做了一个映射,即对象(object)-关系(relationship)映射(mapping),所以hibernate或者其他类似的框架(mybatis)也叫ORM框架
以hibernate的API为蓝本推出的一套接口标准叫JPA(默认的实现就是hibernate)
但是写这个JPA也不是很方便,于是spring也加入进来了,spring的作用,有人叫胶水,把各种东西整合起来让别人能更方便地使用(比如spring mvc),于是数据库操作这个部分就叫做spring data(pom.xml)
org.springframework.boot
spring-boot-starter-data-jpa
3.Spring data 实现自增主键步骤
实体类的配置:
第一步:建一个实体类(比如User),给属性加上get set方法
第二步:给类加上@Entity和@Table注解
前者表示这是一个被jpa管理的实体类,后者表示这个实体类对应一张数据库表
第三步:给主键对应的属性加上@Id注解
@Id注解放在属性和get方法上面都可以,但是大部分框架找字段找的不是属性,而是get方法
第四步:给主键列加上@GeneratedValue 和某些限制(比如非空@NotNull,这类注解都是javax.persistence包下面)
第五步:如果有实体之间的关系,给相关的列上加关系相关的注解
@OneToOne @ManyToOne @ManyToMany
public class UserBean {
private Long id;
private String username;
private String password;
private LocalDateTime registerTime;
private UserInfoBean info;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) //提供了主键的生成策略
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
public LocalDateTime getRegisterTime() {
return registerTime;
}
public void setRegisterTime(LocalDateTime registerTime) {
this.registerTime = registerTime;
}
@OneToOne
public UserInfoBean getInfo() {
return info;
}
public void setInfo(UserInfoBean info) {
this.info = info;
}
}
数据库操作的配置:
操作数据库的类称为Data Access Object(DAO)(现在依然可以这么叫,只不过实现方式变了)
第一步:建接口XXXDAO,继承JPA提供的一些接口(比如 JpaRepository CrudRepository
第二步:继承JpaRepository接口,它继承了其它所有接口,功能是最全的,包括增删改查,分页等等
JpaRepository接口带泛型,有两个参数(第一个,由它负责操作的实体类,第二个,这个实体类的主键的类型)
第三步:加上@Repository注解,springboot会自动扫描所有这种注解,然后把它加到容器里面,就可以在其他地方用这个DAO了
@Repository
public interface UserDAO extends JpaRepository { //实体类为UserBean,主键属性为Long
}
XXXDAO使用:JPA提供的基本操作
比如在Controller或者Service里面用@Autowired注入
insert和update操作用的都是save方法,XXXDAO.save(XXX),执行完save之后,自动生成的主键会被填入到该对象中(如果此时主键是null,并且是自增主键,会执行insert)
就是说
user.getId() //null
userDAO.save(user);
user.getId(); //自动生成的主键
课后练习:主键是不是null,是不是自动生成的主键,什么情况是update 什么情况是insert 什么情况会报错?
delete操作方法名就是delete
select操作方法名是find开头,特殊的比如select count(*)方法名就是count
进阶操作:根据指定的字段查找 更新 删除
功能1:查找username是xxx的用户
在XXXDAO接口里面加一个方法
public UserBean findByUsername(String username);
//然后在外面直接userDAO.findByUsername("xxx")就可以了
框架会自动解析你的方法名,发现是find,就知道要做select操作;(find可以换成get)
有By关键字,就知道要加where;
条件字段是Username,就知道是where username = xxx
功能2:符合条件查询
public UserBean findByUsernameAndPassword(String username, String password);
生成出来的SQL语句:select xxx from xxx where username = xxx and password = xxx
只要你的方法名符合框架指定的命名规则,它就能直接转换成SQL语句,具体规则很多
功能3:自己写SQL语句
如果你觉得命名规则也不能满足你的需求,那么你可以自己写SQL语句
比如: @Query注解(方法名无所谓)
@Query(value = "select * from tb_user t1 left join tb_user_info t2 on t1.info_id = t2.id where t2.nickname like ?1 or t2.name like ?1", nativeQuery = true)
nativeQuery表示原生SQL,不加的话要写JPQL,或者叫面向对象的查询语言吧
JPQL大概是select * from UserBean u where u.id = xxx(操作的不是表而是Java对象,或者说JPA管理的Entity)
4.@GeneratedValue注解
@GeneratedValue注解有两个属性:strategy和generator
@GeneratedValue(strategy=GenerationType.TABLE , generator="TableGeneratorname")
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "roleSeq")
@TableGenerator(name = "roleSeq", allocationSize = 1, table = "seq_table", pkColumnName = "seq_id", valueColumnName = "seq_count")
public Long getId() {
return id;
}
@GeneratedValue(strategy=GenerationType.SEQUENCE , generator="SequenceGeneratorname")
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "menuSeq")
@SequenceGenerator(name = "menuSeq", initialValue = 1, allocationSize = 1, sequenceName = "MENU_SEQUENCE")
public Long getId() {
return id;
}
以上这两个都便于移植到各种环境
@GeneratedValue(strategy = GenerationType.IDENTITY) 只适用于有自增主键功能的数据库(MySQL)
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
@GeneratedValue(strategy = GenerationType.AUTO) 可以写为@GeneratedValue
以上这两个方法移植性较差
@GeneratedValue(strategy = GenerationType.AUTO) //或者 @GeneratedValue
public Long getId() {
return id;
}