spring-data-jpa操作jpa(hibernate实现)

本文介绍了如何在Spring Boot项目中使用Spring Data JPA和Hibernate进行数据库操作。首先,需要在Maven的pom.xml中添加相关依赖,并在配置文件中设置数据库连接信息。接着,详细讲解了实体类的构建,包括`@Table`、`@Entity`等注解的使用,以及如何处理双向关联以避免JSON序列化时的递归错误。然后,阐述了Repository的构建,说明只需简单继承`JpaRepository`即可实现基本的CRUD操作。最后,讨论了JPA的多表操作,包括JPQL和固定前缀查询方法,以及使用Example对象进行查询的方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.在maven的pom文件中添加依赖

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>	<!-- druid start -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.1.9</version>
		</dependency>
		<!-- druid end -->
		<!-- mysql start -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.11</version><!--$NO-MVN-MAN-VER$ -->
		</dependency>
		<!-- mysql end -->


2.在springboot的配置文件yml文件中配置数据库链接信息

spring:
#数据库链接信息配置
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql://192.168.1.25:3306/test?useUnicode=true&characterEncoding=utf8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
#JPA配置
  jpa:
    hibernate:
      ddl-auto: create-drop
    show-sql: true
    database-platform: org.hibernate.dialect.MySQL55Dialect
#请求编码配置  
  http:
    encoding:
      charset: UTF-8
      force: true
      enabled: true
#日志配置
logging:
  file: /logs/springBootTest.log
  pattern:
    level: debug

3.具体编码

3.1第一步:构建实体类Customer

package com.example.myapplication.customer;


import java.io.Serializable;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import com.example.myapplication.order.Order;

@Table
@Entity
public class Customer implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 4340240628311870193L;
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(columnDefinition="int unsigned")
	private Long id;
	@Column(nullable=false)
	private String name;
	@Column(name="borthday",nullable=false)
	private Date borthDay;
	@Column(nullable=false)
	private String address;
	@OneToMany(fetch=FetchType.LAZY,cascade=CascadeType.ALL)
	private List<Order> orders;
	
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Date getBorthDay() {
		return borthDay;
	}
	public void setBorthDay(Date borthDay) {
		this.borthDay = borthDay;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	
	public List<Order> getOrders() {
		return orders;
	}
	public void setOrders(List<Order> orders) {
		this.orders = orders;
	}
	@Override
	public String toString() {
		return "Customer [id=" + id + ", name=" + name + ", borthDay=" + borthDay + ", address=" + address + "]";
	}
	
}

构建实体类Order,order是mysql数据库的关键字(order by),必须用``包括住,否则无法报错,无法创建表

package com.example.myapplication.order;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

import com.example.myapplication.customer.Customer;
import com.fasterxml.jackson.annotation.JsonBackReference;

@Entity
@Table(name="`order`")
public class Order implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = -5202655458725277540L;
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(columnDefinition="int unsigned")
	private Long id;
	@Column(nullable=false,length=50)
	private String name;
	@Column(nullable=false)
	private String sn;
	@Column(nullable=false)
	private Long price;
	@Column(nullable=false,columnDefinition="tinyint default 0 COMMENT '状态:0 未支付;1 已支付;'")
	private Integer state;
	@JsonBackReference
	@ManyToOne(optional=true,fetch=FetchType.EAGER)
	private Customer customer;
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSn() {
		return sn;
	}
	public void setSn(String sn) {
		this.sn = sn;
	}
	public Long getPrice() {
		return price;
	}
	public void setPrice(Long price) {
		this.price = price;
	}
	public Integer getState() {
		return state;
	}
	public void setState(Integer state) {
		this.state = state;
	}
	public Customer getCustomer() {
		return customer;
	}
	public void setCustomer(Customer customer) {
		this.customer = customer;
	}
}

实体类构建是使用hibernate最关键的一步

@Tabe:标记这是一个表<->实体类的关系映射关系,如果表名和实体类一致不用填写name属性,表名和实体类名对应关系是

实体类类名首字母大写:表名首字母小写;实体类类名中间有驼峰形式的大写字母:表名在大写字母前加"_",对应字母小写;

例如:实体类OrderItem==>表名:order_item,字段名的命名规范也是一至的

@Entity:标记这个类是实体类,

实体类之间一般通过一对多,多对一来管理映射关系

@JsonBackReference



这个标签可以在json序列化的时候忽略这个字段,避免由于双向关联引起的无限递归报错,该字段仍然有值;

@JsonManagedReference则是在json反序列化的时候忽略字段,该字段仍然有值;

@JsonIgnore则是json序列化时候完全忽略该字段,并且该字段不会被赋值

3.2 第二步:构建Repository,也就是我们传统上的dao,持久层的操作方法都在这里

例如:

import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;

public interface OrderRepository extends JpaRepository<Order, Long>{

	@Override
	default <S extends Order> Optional<S> findOne(Example<S> example) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	default <S extends Order> Page<S> findAll(Example<S> example, Pageable pageable) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	default <S extends Order> long count(Example<S> example) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	default <S extends Order> boolean exists(Example<S> example) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	default Page<Order> findAll(Pageable pageable) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	default <S extends Order> S save(S entity) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	default Optional<Order> findById(Long id) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	default boolean existsById(Long id) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	default long count() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	default void deleteById(Long id) {
		// TODO Auto-generated method stub
		
	}

	@Override
	default void delete(Order entity) {
		// TODO Auto-generated method stub
		
	}

	@Override
	default void deleteAll(Iterable<? extends Order> entities) {
		// TODO Auto-generated method stub
		
	}

	@Override
	default void deleteAll() {
		// TODO Auto-generated method stub
		
	}

	@Override
	default List<Order> findAll() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	default List<Order> findAll(Sort sort) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	default List<Order> findAllById(Iterable<Long> ids) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	default <S extends Order> List<S> saveAll(Iterable<S> entities) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	default void flush() {
		// TODO Auto-generated method stub
		
	}

	@Override
	default <S extends Order> S saveAndFlush(S entity) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	default void deleteInBatch(Iterable<Order> entities) {
		// TODO Auto-generated method stub
		
	}

	@Override
	default void deleteAllInBatch() {
		// TODO Auto-generated method stub
		
	}

	@Override
	default Order getOne(Long id) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	default <S extends Order> List<S> findAll(Example<S> example) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	default <S extends Order> List<S> findAll(Example<S> example, Sort sort) {
		// TODO Auto-generated method stub
		return null;
	}
	
}

只要像下面这样简单的继承JpaRepository<实体类类型,id类型>就可以得到上面的所有方法实现,无需程序员自己去编写代码,

jpa的多表操作通常都是通过第一步的构建实体类,配置关系映射和级联关系这几个步骤来实现的

package com.example.myapplication.order;

import org.springframework.data.jpa.repository.JpaRepository;

public interface OrderRepository extends JpaRepository<Order, Long>{
	
}

当然,如果你喜欢更加灵活一些的方法也可以的,这是通过jpql(一种和hql高度相似的面向对象的查询语言)来实现的查询,第一种方法是直接使用Jpql来查询,第二种则是通过固定的前缀,例如findBy,再加上驼峰命名的字段条件作为方法名(个人感觉虽然不用写jpql,但是还是如果条件多的话文件名就会过长了,也不好维护)

@Repository("customerRepository")
public interface ICustomerRepository extends JpaRepository<Customer, Long>{

	@Query(value="SELECT customer FROM Customer customer where id = ?1")
	Customer getCustomer(Long id);
	//@Query(value="SELECT customer FROM Customer customer where name = ?1 and address = ?2")
	Customer findByNameAndAddress(String name,String address);
}


jpql的参数传递也可以这样,更加方便容易维护:
	@Query(value="SELECT customer FROM Customer customer where id = :id and name = :name")
	Customer getCustomer(@Param("id")Long id,@Param("name")String name);

如果对jpql不熟悉的,也可以使用自然sql,不过映射的对象依然必须是该实体类类型或者是Object类型,不能是自定义的一个javaBean,这个也是hibernate/jpa这种完全ORM框架的不灵活的地方,相对复杂的查询,结果集映射没有mybatis那样可以自由灵活地返回自定义的map<k,v>集合,list<Map<k,v>>集合

@Query(value="select * from `order` where id=:id and name=:name",nativeQuery=true)
	Order getOder(@Param("id")Long id,@Param("name")String name);
	@Query(value="select * from `order` where id=? and name=?",nativeQuery=true)
	Order getOder2(Long id,String name);

还有一种通过Example对象操作来进行查询的方法:

ExampleMatcher matcher = ExampleMatcher.matching()
				  .withMatcher("id", match -> match.endsWith())
				  .withMatcher("name", match -> match.startsWith());
		Order probe = new Order();
		probe.setId(1l);
		Example<Order> ex = Example.of(probe , matcher);
		List<Order> lis = orderRepository.findAll(ex);



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值