springboot-jpa

jpa简介

JPA (Java Persistence API) Java持久化API。是一套Java官方制定的ORM 方案。Java持久性API(JPA)是Java的一个规范。 它用于在Java对象和关系数据库之间保存数据。 JPA充当面向对象的领域模型和关系数据库系统之间的桥梁。由于JPA只是一个规范,它本身不执行任何操作。 它需要一个实现。 因此,像Hibernate,TopLink和iBatis这样的ORM工具实现了JPA数据持久性规范。实现JPA规范的框架一般最常用的就是Hibernate,它是一个重量级框架,学习难度相比Mybatis也更高一些,而SpringDataJPA也是采用Hibernate框架作为底层实现,并对其加以封装。

ORM框架(以下是在ORM机制上运行的一些框架)

  • Hibernate (参考:http://www.yiibai.com/hibernate )
  • TopLink
  • ORMLite
  • iBATIS
  • JPOX

使用JPA

导入依赖

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

yaml配置

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mybatis
    username: root
    password:
    driver-class-name: com.mysql.jdbc.Driver
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: update

ddl-auto`属性用于设置自动表定义,可以实现自动在数据库中为我们创建一个表,表的结构会根据我们定义的实体类决定,它有4种

  • create 启动时删数据库中的表,然后创建,退出时不删除数据表
  • create-drop 启动时删数据库中的表,然后创建,退出时删除数据表 如果表不存在报错
  • update 如果启动时表格式不一致则更新表,原有数据保留
  • validate 项目启动表结构进行校验 如果不一致则报错

JPA常用注解

@Entity
@Table
@Basic
@Column
@GeneratedValue
@Id
@Transient
@Temporal
@OneToMany
@ManyToOne
@ManyToMany
@Query (Spring Data JPA 用法)
@Modifying

创建entity

@Entity
@Data
@Table(name= "user")
public class User {
    @Id
    @Column(name="id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "name")
    private String name;

    @Column(name = "pwd")
    private String pwd;
}

创建Repository接口

public interface UserRepository extends JpaRepository<User,Integer> {
}

方法名拼接自定义sql

如果我们需要进行条件查询等操作或是一些判断,就需要自定义一些方法来实现,同样的,我们不需要编写SQL语句,而是通过方法名称的拼接来实现条件判断,这里列出了所有支持的条件判断名称:

关键字方法拼接数据库语句
DistinctfindDistinctByLastnameAndFirstnameselect distinct … where x.lastname = ?1 and x.firstname = ?2
AndfindByLastnameAndFirstname… where x.lastname = ?1 and x.firstname = ?2
OrfindByLastnameOrFirstname… where x.lastname = ?1 or x.firstname = ?2
IsEqualsfindByFirstname,findByFirstnameIs,findByFirstnameEquals… where x.firstname = ?1
BetweenfindByStartDateBetween… where x.startDate between ?1 and ?2
LessThanfindByAgeLessThan… where x.age < ?1
LessThanEqualfindByAgeLessThanEqual… where x.age <= ?1
GreaterThanfindByAgeGreaterThan… where x.age > ?1
GreaterThanEqualfindByAgeGreaterThanEqual… where x.age >= ?1
AfterfindByStartDateAfter… where x.startDate > ?1
BeforefindByStartDateBefore… where x.startDate < ?1
IsNullNullfindByAge(Is)Null… where x.age is null
IsNotNullNotNullfindByAge(Is)NotNull… where x.age not null
LikefindByFirstnameLike… where x.firstname like ?1
NotLikefindByFirstnameNotLike… where x.firstname not like ?1
StartingWithfindByFirstnameStartingWith… where x.firstname like ?1(参数与附加%绑定)
EndingWithfindByFirstnameEndingWith… where x.firstname like ?1(参数与前缀%绑定)
ContainingfindByFirstnameContaining… where x.firstname like ?1(参数绑定以%包装)
OrderByfindByAgeOrderByLastnameDesc… where x.age = ?1 order by x.lastname desc
NotfindByLastnameNot… where x.lastname <> ?1
InfindByAgeIn(Collection<Age> ages)… where x.age in ?1
NotInfindByAgeNotIn(Collection<Age> ages)… where x.age not in ?1
TruefindByActiveTrue()… where x.active = true
FalsefindByActiveFalse()… where x.active = false
IgnoreCasefindByFirstnameIgnoreCase… where UPPER(x.firstname) = UPPER(?1)

例子:

public interface UserRepository extends JpaRepository<User,Integer> {
    //通过名字查找用户
    List<User> findByName(String name);

    //通过模糊查询查找用户
    List<User> findByNameLike(String name);

    //通过名字或id查找用户
    List<User> findByNameOrId(String name,Integer id);
    
    //用户是否存在
    boolean existsUserByIdAndName(Integer id,String name);
}

关联查询

使用外键

  • @OneToOne
    参数相关:

      fetch = FetchType.LAZY  设置懒加载,这样只有在需要时才会向数据库获取
      cascade = CascadeType.ALL
      	ALL:所有操作都进行关联操作
      	PERSIST:插入操作时才进行关联操作
      	REMOVE:删除操作时才进行关联操作
      	MERGE:修改操作时才进行关联操作
    
  • @OneToMany

  • @ManyToOne

  • @ManyToMany

  • @JoinColumn

注意的点有:

  • 自动建立外键
    如果用这种方法查询就避免不了建外键,而外键主要是保证数据库数据的完整性和一致性,对于使用外键有好处也有坏处,主要坏处是操作数据方面有了很多的限制,增加了维护成本,需要看你怎么取舍,但很多项目都是业务进行控制数据库的完整性和一致性,不需要建立外键。
  • 不能分页查询
    如果是一对多,多对多,那么只能一次查询全部对应的集合,不能使用分页。

使用@Query注解

@Query比较简单,可以帮你实现分页逻辑,但不能动态条件参数查询,不适合查询条件参数不确定的情况,如果查询条件确定,那么是推荐使用这种。@Query默认使用hsql语言进行查询

HQLSQL
hql查数据库查类和属性sql是通过表和表的列进行查询
区分大小写,关键字不区分大小写不区分大小写
都可以取别名都可以取别名
?占位符(hibernate5之后不支持),一般都是用命名参数,下标从0开始计算?占位符,从顺序1开始计算
:命名参数没有命名参数 不支持
面向对象的查询语言面向结构查询语言
public @interface Query {

	/** 定义被执行的sql或者hql */
	String value() default "";

	/** 分页时用于查询中数量的sql或者hql */
	String countQuery() default "";

	/** 用原生的分页 */
	String countProjection() default "";

	/** 使用原生sql,为false时使用hql */
	boolean nativeQuery() default false;

	/** 定义该查询的名字 */
	String name() default "";

	/** 数量查询返回的别名 */
	String countName() default "";
}

@query返回自定义对象
使用的时hql语法,不支持sql原生

@Data
public class UserDept implements Serializable {

    @JsonProperty("user_id")
    private Integer userId;

    @JsonProperty("user_name")
    private String userName;

    @JsonProperty("dept_id")
    private Integer deptId;

    @JsonProperty("dept_name")
    private String deptName;

    public UserDept(Integer userId, String userName, Integer deptId, String deptName) {
        this.userId = userId;
        this.userName = userName;
        this.deptId = deptId;
        this.deptName = deptName;
    }
}

from 后面都是用的对象(hql)

@Repository
public interface UserRepository extends JpaRepository<User, Integer> {

    @Query("select new com.ljw.test.pojo.domain.UserDept(" +
            "u.id, u.name, d.id, d.name ) " +
            "from User u, Dept d " +
            "where u.deptId=d.id")
    List<UserDept> findAllForUserDept();

    @Query("select new map(" +
            "u.id as user_id, u.name as user_name, d.id as dept_id, d.name as dept_name) " +
            "from User u, Dept d " +
            "where u.deptId=d.id")
    List<Map<String, Object>> findAllForMap();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值