jpa是面向对象的,而非面向数据库,所以这里我们不需要去写sql语句操作数据库,只需要通过操作对象就能达到修改和查询数据库的操作。在这里我就先使用jpa创建一个数据库t_user表。
- 创建一个springboot项目,添加mysql和jpa
取好项目名,next
然后修改pom文件中mysql依赖,加上版本号,不然等会在yml文件中会无法解析driver-class-name
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>
- 修改resources目录下的properties文件变成yml文件
2.1 配置yml文件
spring:
# 配置数据源
datasource:
username: root
password: root
url: jdbc:mysql://127.0.0.1:3306/jpaDemo
driver-class-name: com.mysql.jdbc.Driver
# 配置jpa的相关信息
jpa:
generate-ddl: true # 生成创建表的sql语句
hibernate:
ddl-auto: update # 每次启动项目时,检查数据库表结构和实体属性是否进行映射
show-sql: true
#配置数据方言
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
- 创建实体类
import javax.persistence.*;
//给数据库表取名
@Entity(name="t_user")
public class User {
@Id //设置主键
@GeneratedValue(strategy = GenerationType.IDENTITY) //设置主键自增
private Integer uid;
@Column //设置列
private String uname;
@Column //设置列
private String address;
@Override
public String toString() {
return "User{" +
"uid=" + uid +
", uname='" + uname + '\'' +
", address='" + address + '\'' +
'}';
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
3.1 接下来去测试类中运行方法即可在数据库中创建一个和实体类属性相对应的表了。
3.2 查看数据库就能发现表已经创建完成。
4. 接下来我们将使用jpa对数据库进行增删查改操作。
4.1 创建一个dao包,里面包含userDao接口,并继承JpaRepository类
public interface UserDao extends JpaRepository<User,Integer> {
}
4.2在测试类注入UserDao
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringdataJpaDemoApplicationTests {
@Autowired
private UserDao userDao;
@Test
public void contextLoads() {
System.out.println("--------创建数据库表--------");
}
//新增操作
@Test
public void saveUser(){
User user=new User();
user.setUname("一一");
user.setAddress("北京");
userDao.save(user);
}
4.3 更新操作
//更新操作 , 和插入的区别是这个有id,先执行查询,然后再更新数据
@Test
public void updateUser(){
User user=new User();
user.setUid(1);
user.setUname("liming");
user.setAddress("上海");
userDao.save(user);
}
4.4 删除操作
//删除操作
@Test
public void deleteUser(){
userDao.deleteById(1);
}
4.5 查询单个用户
//查询某个用户
@Test
public void findOne(){
Optional<User> optional=userDao.findById(1);
User user=optional.get();
System.out.println(user.getUid()+","+user.getUname()+","+user.getAddress());
}
4.6 查询全部用户
//查询所有用户信息
@Test
public void findAll(){
List<User> list = userDao.findAll();
for (User i : list){
System.out.println(i.getUid()+"--"+i.getUname()+"--"+i.getAddress());
}
}
4.7 具体条件查询多个用户
//具体条件查询多个用户
@Test
public void findMoreByXX(){
User user=new User();
user.setUname("王五");
user.setAddress("上海");
//存储User对象指定where查询
Example<User> example=Example.of(user);
List<User> list = userDao.findAll(example);
for (User u : list) {
System.out.println(u.getUid()+"--"+u.getUname()+"--"+u.getAddress());
}
}
4.8 模糊查询多个用户
//模糊查询多个用户
@Test
public void findMoreByVague(){
User user=new User();
//user.setUname("王");
user.setAddress("上");
//在对象中存了“上”这个值,才能实现 where address like 上% 这个sql语句
ExampleMatcher matcher=ExampleMatcher.matching().withMatcher("address",ExampleMatcher.GenericPropertyMatchers.startsWith());
Example<User> example=Example.of(user,matcher);
List<User> list = userDao.findAll(example);
for (User u : list) {
System.out.println(u.getUid()+"--"+u.getUname()+"--"+u.getAddress());
}
}
4.9 分页查询
//分页查询
@Test
public void findPage(){
//创建分页查询对象
Pageable pageable= PageRequest.of(0,2);
Page<User> page = userDao.findAll(pageable);
for (User u : page) {
System.out.println(u.getUid()+"--"+u.getUname()+"--"+u.getAddress());
}
//获得本次查询的总记录数和总页数
System.out.println(page.getTotalElements()+"---"+page.getTotalPages());
}
4.10 分页查询结果排序
//查询结果排序
@Test
public void findSort(){
Sort sort=new Sort(Sort.Direction.DESC,"uid");
PageRequest pageRequest = PageRequest.of(1, 3, sort);
Page<User> page = userDao.findAll(pageRequest);
page.forEach(new Consumer<User>() {
@Override
public void accept(User user) {
System.out.println(user.getUid()+"--"+user.getUname()+"--"+user.getAddress());
}
});
}
- 建立用户表和订单表之间的关系
如果我们按照之前的方法再建立一张订单表,那么订单表和用户表好像是独立的,两者没有外键关联的。那这样就不能根据用户id查询用户订单了,所以我们有必要给他们建立一个关联。
5.1创建订单类
package com.zym.springdata_jpa_demo.pojo;
import javax.persistence.*;
import java.util.Date;
@Entity(name = "t_orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column
private Double total;
@Column
private Date date;
// 用户和订单是多对一的关系,所以这里使用 @ManyToOne
@ManyToOne
@JoinColumn(name="uid") //设置uid为外键
private User user;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Double getTotal() {
return total;
}
public void setTotal(Double total) {
this.total = total;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
5.2 修改用户类
//给数据库表取名
@Entity(name="t_user")
public class User {
@Id //设置主键
@GeneratedValue(strategy = GenerationType.IDENTITY) //设置主键自增
private Integer uid;
@Column //设置列
private String uname;
@Column //设置列
private String address;
//用户和订单是多对一的关系,所以在用户类中使用 @OneToMany
@OneToMany(mappedBy = "user")
private List<Order> oList;
5.3 启动测试类,查看数据库的表
5.4 多表关联查询
//查询某个用户所有订单信息
@Test
public void findOneAllOrders(){
Optional<User> userOptional = userDao.findById(2);
User user = userOptional.get();
List<Order> orderList = user.getoList();
for (Order order : orderList) {
System.out.println(order.getId()+"--"+order.getDate()+"--"+order.getTotal()+"--"+order.getUser().getUid());
}
}
这里会报错,org.hibernate.LazyInitializationException: failed to lazily initialize a col,因为jpa默认是懒加载的,当执行user.getoList()方法时,数据库连接已经关闭了,查不到了,所以这里有两种解决办法,一是将用户类的@OneToMany设置成立即加载,二是设置session延迟关闭。在这里我们先介绍第一种方案,
@OneToMany(mappedBy = "user",fetch = FetchType.EAGER)
private List<Order> oList;
设置成立即加载后再次运行即可成功。
6. 定义jpql查询数据库
这是一个类似于sql的查询语句。和sql不同的是,sql语句中是用表名查询,jpql用的是类的全限定路径。
6.1 在userDao中自定义扩展方法
package com.zym.springdata_jpa_demo.dao;
import com.zym.springdata_jpa_demo.pojo.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
public interface UserDao extends JpaRepository<User,Integer> {
//自己扩展方法
@Query(value = "from com.zym.springdata_jpa_demo.pojo.User u ")
public List<User> loadUserList();
}
6.2 在测试类写查询方法
//jpql查询数据库
@Test
public void loadUserList(){
List<User> userList = userDao.loadUserList();
for (User user : userList) {
System.out.println(user.getUid()+"--"+user.getUname()+"--"+user.getAddress());
}
}
6.3 jpql多表关联查询
@Query(value = "from com.zym.springdata_jpa_demo.pojo.User u join " +
"com.zym.springdata_jpa_demo.pojo.Order o on u.uid=o.user.uid")
//集合中既要存储用户还要存储订单,所以使用Object数组
public List<Object[]> loadUserAndOrderList();
//jpql多表关联查询
@Test
public void loadUserAndOrderList(){
List<Object[]> list=userDao.loadUserAndOrderList();
for (Object[] obj : list) {
User user = (User) obj[0];
Order order = (Order) obj[1];
System.out.println(user.getUid()+"--"+user.getUname()+"--订单信息:"+order.getTotal()+"--"+order.getDate());
}
}