前言
之前一直使用Mybatis、mplus,最新工作需求,简单学习下Jpa。作为一个ORM框架,JPA给我的感觉是sql粉碎机,你不再需要像mybatis那样频繁的写sql语句了。话不多说,开始整活。
一:依赖配置
本人这里使用的是Springboot项目,管理工具使用的是maven。在pom文件中导入相关依赖。
<!--jpa-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!--数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
<version>8.0.23</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
导入依赖后,还需要添加相关配置。
数据库或jpa其他配置这里先不加,足够练习使用即可。
#配置端口
server:
port: 8080
#配置数据库
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/jpa?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&serverTimezone=GMT
username: root
password: root
jpa:
generate-ddl: true #开发阶段可以设置为true,是否开启逆向工程
hibernate:
#create:每次都新建表 create-drop:每次新建,使用完删除
#none:无效果 update:没有表就新建,有就使用。如果实体类有变化会更新表 validate:实体类和数据库表对比,不一致抛出异常
ddl-auto: update #常用
show-sql: true #生成sql
database-platform: org.hibernate.dialect.MySQL8Dialect #指定数据库类型
二:代码编写
注意:先不要创建数据库表。这里引入知识点:正向工程和逆向工程。
逆向工程:平时我们先创建数据库表,再创建相应实体类,这种方式可以称为逆向。
正向工程:从代码出发,也就是先创建实体类,再生成数据库。
1:创建实体类
这里使用的是注解方式,比较重要的是@Entity注解,表示对应的表名。@Column表示对应列名。
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity(name = "PET")
public class PetEntity {
/**
* @Id 声明主键
* @GeneratedValue 自增策略
* @Column 对应列
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private Integer id;
/**
* 宠物名
*/
@Column(name = "P_NAME")
private String name;
/**
* 颜色
*/
@Column(name = "P_COLOR")
private String color;
}
将项目启动,(可在springboot启动类或测试类,反正启动就好),数据库即可生成表,列就是实体类定义的属性。
注意:这里从实体类生成数据表是有策略的。ddl-auto:上文的配置文件中有讲到。
2:编写方法及测试
2.1:JAP封装方法。
OK,实体类我们已经创建完毕,表也生成了。接下来我们创建一个mapper。
如同Mybatis-plus一样,JPA也给我们封装好了一些增删改查方法,只需要实现接口即可使用。
接口和接口之间是继承😀。图上有描述,这里不再赘述。
测试代码:包含增删改查、分页查等一些常用方法。
@Test
void jpaInsertTest() {
PetEntity pet = new PetEntity();
//如果有id则为修改
//pet.setId(2);
pet.setName("小黄");
pet.setColor("黄色");
petDao.save(pet);
}
@Test
void jpaSelectByIdTest() {
//查询单个 得到Optional对象,使用get方法取出
Optional<PetEntity> optional = petDao.findById(1);
PetEntity PetEntity = optional.get();
System.out.println(PetEntity);
}
@Test
void jpaSelectAllTest() {
//List<PetEntity> petList = petDao.findAll();
//findAll还可指定参数 Sort:排序
//注意:desc()里的参数是 实体类 属性,不是列
List<PetEntity> petList = petDao.findAll(Sort.by(Sort.Order.desc("id")));
for (PetEntity PetEntity : petList) {
System.out.println(PetEntity);
}
}
@Test
void jpaSelectAndPage() {
//PageRequest.of():填写页码,条目数实现分页
Pageable pageable = PageRequest.of(0, 1, Sort.Direction.DESC, "id");
//将pageable放入findAll中,返回分页后的集合数据
Page<PetEntity> petDaoAll = petDao.findAll(pageable);
for (PetEntity PetEntity : petDaoAll) {
System.out.println(PetEntity);
}
//petDaoAll.getTotalElements(): 获取总条目数
System.out.println(petDaoAll.getTotalElements());
//petDaoAll.getTotalPages(): 获取总页码数
System.out.println(petDaoAll.getTotalPages());
}
@Test
void jpaDeleteTest() {
PetEntity PetEntity = new PetEntity();
PetEntity.setId(1);
petDao.delete(PetEntity);
}
2.2:自定义查询(方法)
当JPA封装的方法不足以我们使用时,(如业务字段查询),这时JPA(Mybatis-plus也有)给我们提供的有自定义方法查询。按照固定的格式创建方法名,也可实现不写sql的查询。
/**
* 根据名称查询
*
* @param pName 宠物名
* @return 宠物集合
*/
List<PetEntity> findByName(String pName);
/**
* 根据颜色查询
*
* @param color 颜色
* @return 宠物集合
*/
List<PetEntity> findByColor(String color);
/**
* 根据名称颜色查询
* 注意:方法名不能乱写,根据sql语句写
*
* @param name 宠物名
* @param color 颜色
* @return
*/
List<PetEntity> findByNameAndColor(String name, String color);
注意:类似findBy这种就是固定格式,后面跟实体类属性名即可完成对应字段查询。其他增删改大家可以自己探索。
测试代码:这里只展示代码,不展示运行结果了。
@Test
void jpaCustomTest() {
List<PetEntity> byName = petDao.findByName("小黄");
System.out.println(byName);
List<PetEntity> byColor = petDao.findByColor("黄色");
System.out.println(byColor);
}
@Test
void jpaSelectAllByNameAndColorTest() {
List<PetEntity> byName = petDao.findByName("小黄");
System.out.println(byName);
List<PetEntity> byColor = petDao.findByColor("黄色");
System.out.println(byColor);
List<PetEntity> byPnameAndColor = petDao.findByNameAndColor("小黄", "黄色");
System.out.println(byPnameAndColor);
}
2.3:自定义查询(JPQL)
不想使用固定名字创建方法,那第二种自定义查询就是使用JPQL语句,它和sql的区别是:
sql针对的是数据库表和列
jpql针对的是实体类和属性
使用也很简单,方法上添加@Query注解,里面写JPQL语句即可。
①无参的:
Tips:from实体类的全路径,id,name等都是实体类属性
/**
* * jpql查询所有
* * sql: select * from t_pet
* * jpql:
* from com.jpatest.entity.PetEntity
* select pet from com.jpatest.entity.PetEntity pet
*
* @return
*/
@Query(value = "select pet from com.jpatest.entity.PetEntity pet")
List<PetEntity> selectPetAll();
/**
* 注意:查列返回封装Object[]数组,用实体接收会转换异常
* select id,name,color from com.changhui.eo.PetEntity
*
* @return
*/
@Query(value = "select id,name,color from com.jpatest.entity.PetEntity")
List<Object[]> selectAllColumnList();
/**
* 查询列且返回实体类接收
* new 对象,使用实体类的参数构造器
*
* @return
*/
@Query(value = "select new com.jpatest.entity.PetEntity(id,name,color) from com.jpatest.entity.PetEntity ")
List<PetEntity> selectAllPetListForColumn();
②带参数的话,会有两种参数使用方式:顺序参数和具名参数。
顺序参数:?参数位置
/** * 使用jpql顺序查询,根据名称查询 * * @param name 名称 * @return */ @Query(value = "from com.jpatest.entity.PetEntity where name =?1") List<PetEntity> selectPetByName(String name);
具名参数: :Param指定的名字
/** * 使用jpql具名查询,根据颜色查询 * * @param color 颜色 * @return */ @Query(value = "from com.jpatest.entity.PetEntity where color = :color") List<PetEntity> selectPetByColor(@Param("color") String color);
注意:JPQL不支持新增,但可以使用HIbernate实现伪新增,有兴趣的可以了解一下。使用JPQL语句增删改,需要添加@Modifying:告诉JPA此方法是增删改方法。切记。
③如果不想使用JPQL,还可以使用原生Sql语句,在注解后面添加一个属性。
/**
* 使用原生sql查询
* 添加 nativeQuery = true,即代表使用原生sql,不再使用类,使用数据库
*
* @param color 颜色
* @return
*/
@Query(value = "SELECT * FROM pet WHERE p_color = :color", nativeQuery = true)
List<PetEntity> selectPetByColorForTable(@Param("color") String color);
测试就不要贴了,就是普通的dao层方法调用。
好了,其实jpql还可以使用createQuery等实现,练习到这里了,有兴趣的可以自行检索。项目已同步至gitee,大家可以去拉取代码,希望留下你的小星星。
tu.gitee/jpa-exercisehttps://gitee.com/aaaaaafdf/jpa-exercise