springboot集成spring data jpa


引入依賴

這里使用mysql數據庫,所以要引用mysql數據庫連接包

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>    

 添加配置

在application.yml文件添加數據庫連接配置及jpa配置

spring: 
 datasource: 
  driver-class-name: com.mysql.jdbc.Driver
  url: jdbc:mysql://localhost:3306/springboot_1?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
  username: root
  password: 123456
 jpa:
  properties: 
   hibernate: 
    hbm2ddl: 
     auto: update
     dialect: org.hibernate.dialect.MySQL5InnoDBDialect
     format_sql: true
  show-sql: true

實體類

a)組織

@Entity
@Table(name="t_organization")
public class Organization {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(nullable=false)
    private String name;
    @Column(nullable=false)
    private String code;
    @OneToMany(mappedBy="organization",cascade=CascadeType.REMOVE,fetch=FetchType.EAGER)
    private List<User> userList;
    
    public Organization(){};
    
    public Organization(String name,String code,List<User> userList){
        this.name = name;
        this.code = code;
        this.userList = userList;
    }

b)用戶

@Entity
@Table(name="t_user")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(nullable = false)
    private String name;
    @Column(nullable = false)
    private String sex;
    @ManyToOne(cascade={CascadeType.MERGE,CascadeType.PERSIST})
    @JoinColumn(name="orgId")
    @JsonIgnore
    private Organization organization;
    
    @ManyToMany(cascade={CascadeType.MERGE,CascadeType.PERSIST})
    @JoinTable(name="t_user_role",joinColumns={@JoinColumn(name="userId")},
    inverseJoinColumns={@JoinColumn(name="roleId")} )
    private List<Role> roleList;
    
    public User(){};
    
    public User(String name,String sex,Organization organization){
        this.name = name;
        this.sex = sex;
        this.organization = organization;
    }

c)角色

@Entity
public class Role {
    @Id
    @GeneratedValue
    private Long id;
    @Column
    private String name;
    @ManyToMany(cascade={CascadeType.MERGE,CascadeType.PERSIST})
    @JoinTable(name="t_user_role",joinColumns={@JoinColumn(name="roleId")},
    inverseJoinColumns={@JoinColumn(name="userId")} )
    @JsonIgnore
    private List<User> userList;
    @ManyToMany(cascade={CascadeType.MERGE,CascadeType.PERSIST})
    @JoinTable(name="t_role_privilege",joinColumns={@JoinColumn(name="roleId")},
    inverseJoinColumns={@JoinColumn(name="privilegeId")})
    private List<Privilege> privilegeList;
    
    public Role(){};
    
    public Role(String name,List<User> userList, List<Privilege> privilegeList){
        this.name = name;
        this.userList = userList;
        this.privilegeList = privilegeList;
    }

d)權限

@Entity
public class Privilege {
    @Id
    @GeneratedValue
    private Long id;
    @Column
    private String name;
    @ManyToMany(cascade={CascadeType.MERGE,CascadeType.PERSIST})
    @JoinTable(name="t_role_privilege",joinColumns={@JoinColumn(name="privilegeId")},
    inverseJoinColumns={@JoinColumn(name="roleId")})
    @JsonIgnore
    private List<Role> roleList;
    
    public Privilege(){};
    
    public Privilege(String name,List<Role> roleList){
        this.name = name;
        this.roleList = roleList;
    }

級聯

a)cascade:級聯操作權限

PERSIST 級聯保存

REMOVE 級聯刪除

MERGE  級聯更新

DETACH 級聯游離,要想刪除某一條學生信息,但學生的id在成績表中作為外鍵,無法直接刪除

REFRESH 級聯刷新 與MERGE  好像沒什么區別

ALL 上面所有的結合,慎用

b)fetch:設置關聯對象的加載方式

EAGER 立即加載

LAZY 延遲加載,需要用到的時候再加載

關聯對象

a)OneToMany

一對多,一對多一般不維護關系表字段,所以在這端添加 mappedBy=“mappedBy值” , mappedBy值是多端對象指向一端的屬性值,mappedBy與JoinColumn、JoinTable互斥。因為JoinColumn、JoinTable表示這一端維護這外鍵或中間表

b)ManyToOne

多對一,一般在這端添加外鍵,外鍵對應的字段 JoinColumn(name="外鍵") ,外鍵由這端進行維護

c)ManyToMany

多對多,一般添加一個中間表, @JoinTable(name="t_user_role",joinColumns={@JoinColumn(name="自己的ID字段")},inverseJoinColumns={@JoinColumn(name="另一端的ID字段")} )

接口編寫

編寫一個用戶接口

public interface UserRepository extends JpaRepository<User, Long>{
    
    List<User> findByName(String name);
    
    List<User> findByNameLike(String name);

在要使用用戶接口的地主直接引用即可

    @Resource
    private UserRepository userRepository;

命名查詢

下表描述了JPA支持的關鍵字以及包含該關鍵字的JPA命名查詢方法:

關鍵字

示例

SQL

And

findByLastnameAndFirstname

… where x.lastname = ?1 and x.firstname = ?2

Or

findByLastnameOrFirstname

… where x.lastname = ?1 or x.firstname = ?2

Is,Equals

findByFirstname,findByFirstnameIs,findByFirstnameEquals

… where x.firstname = ?1

Between

findByStartDateBetween

… where x.startDate between ?1 and ?2

LessThan

findByAgeLessThan

… where x.age < ?1

LessThanEqual

findByAgeLessThanEqual

… where x.age <= ?1

GreaterThan

findByAgeGreaterThan

… where x.age > ?1

GreaterThanEqual

findByAgeGreaterThanEqual

… where x.age >= ?1

After

findByStartDateAfter

… where x.startDate > ?1

Before

findByStartDateBefore

… where x.startDate < ?1

IsNull

findByAgeIsNull

… where x.age is null

IsNotNull,NotNull

findByAge(Is)NotNull

… where x.age not null

Like

findByFirstnameLike

… where x.firstname like ?1

NotLike

findByFirstnameNotLike

… where x.firstname not like ?1

StartingWith

findByFirstnameStartingWith

… where x.firstname like ?1(parameter bound with appended %)

EndingWith

findByFirstnameEndingWith

… where x.firstname like ?1(parameter bound with prepended %)

Containing

findByFirstnameContaining

… where x.firstname like ?1(parameter bound wrapped in %)

OrderBy

findByAgeOrderByLastnameDesc

… where x.age = ?1 order by x.lastname desc

Not

findByLastnameNot

… where x.lastname <> ?1

In

findByAgeIn(Collection<Age> ages)

… where x.age in ?1

NotIn

findByAgeNotIn(Collection<Age> ages)

… where x.age not in ?1

True

findByActiveTrue()

… where x.active = true

False

findByActiveFalse()

… where x.active = false

IgnoreCase

findByFirstnameIgnoreCase

… where UPPER(x.firstame) = UPPER(?

Query查詢

a)原生sql查詢,nativeQuery = true

@Query(value="select * from t_user u where u.name =?1",nativeQuery = true)
List<User> queryBySql(String name);

b)hql查詢

@Query(value="select u from User u where u.name =?1",nativeQuery = false)
List<User> queryByHql(String name);

c)使用命名參數傳參

    @Query("select u from User u where u.firstname = :firstname or u.lastname = :lastname")
    User findByLastnameOrFirstname(@Param("lastname")String lastname,@Param("firstname")String firstname);

d)返回的不是實體對象

如果返回的不是實體對象,則可以先建一個dto返回類對象UserVo,把查詢的結果映射到實體類上

@Query(value="select new com.ouou.vo.UserVo(u.id,u.name,u.sex) from User u where u.name =?1",nativeQuery = false)
List<UserVo> queryByHqlUserVo(String name);

或返回一個數組對象,然后在代碼里進行組裝提取

@Query(value="select u.id,u.name,u.sex from User u where u.name =?1",nativeQuery = false)
List<Object[]> queryByHqlObject(String name);

分頁查詢

編寫分頁接口

Page<User> findByNameLike(String name,Pageable pageable);

@Query(value="select new com.ouou.vo.UserVo(u.id,u.name,u.sex) from User u where u.name like ?1",nativeQuery = false)
Page<UserVo> queryByHqlUserVoPage(String name,Pageable pageable);

a)通過參數生成Pageable對象

Pageable定義了很多方法,但其核心的信息只有兩個:一是分頁的信息(page、size),二是排序的信息。Spring Data Jpa提供了PageRequest的具體實現,Spring MVC提供了對Spring Data JPA非常好的支持,我們只提供分頁以及排序信息即可:

@RequestMapping(value = "/params", method=RequestMethod.GET)
public Page<User> getEntryByParams(Integer page,Integer size) {
    Sort sort = new Sort(Direction.DESC, "id");
    Pageable pageable = new PageRequest(page, size, sort);
    return userRepository.findByNameLike("姓名",pageable);
}

在這里,我們通過參數獲得分頁的信息,並通過Sort以及Direction告訴pageable需要通過id逆序排列

b)直接獲取Pageable對象

@RequestMapping(value = "/params", method=RequestMethod.GET)
public Page<User> getEntryByPageable(@PageableDefault(value = 15, sort = { "id" }, direction = Sort.Direction.DESC) 
    Pageable pageable) {
    returnuserRepository.findByNameLike("姓名",pageable);
}

我們可以看到,我們只需要在方法的參數中直接定義一個pageable類型的參數,當Spring發現這個參數時,Spring會自動的根據request的參數來組裝該pageable對象,Spring支持的request參數如下:

  • page,第幾頁,從0開始,默認為第0頁
  • size,每一頁的大小,默認為20
  • sort,排序相關的信息,以property,property(,ASC|DESC)的方式組織,例如sort=firstname&sort=lastname,desc表示在按firstname正序排列基礎上按lastname倒序排列

這樣,我們就可以通過url的參數來進行多樣化、個性化的查詢,而不需要為每一種情況來寫不同的方法了。

通過url來定制pageable很方便,但唯一的缺點是不太美觀,因此我們需要為pageable設置一個默認配置,這樣很多情況下我們都能夠通過一個簡潔的url來獲取信息了。

Spring提供了@PageableDefault幫助我們個性化的設置pageable的默認配置。例如@PageableDefault(value = 15, sort = { "id" }, direction = Sort.Direction.DESC)表示默認情況下我們按照id倒序排列,每一頁的大小為15

事務

在service 或 controller類上或方法上添加注解 @Transactional即可。注意:如果service類和controller類上都有@Transactional,則controller類上的事務注解生效,service上的事務注解不生效


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM