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);
}
@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);