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上的事务注解不生效

猜你喜欢

转载自www.cnblogs.com/tanouou/p/12193401.html