springboot整合spring data jpa

目录

1、jpa是什么?

2、spring data jpa

3、添加依赖

4、修改配置文件

5、手动建表

6、实体类

7、创建数据访问接口(数据访问层)

自定义的简单查询

分页查询

8、server层

9、controller层


1、jpa是什么?

JPA是一个规范,不是框架。

JPA (Java Persistence API) 是 Sun 官方提出的 Java 持久化规范。

JPA统一了java应用程序访问ORM框架的规范,结束现在 Hibernate,TopLink,JDO 等 ORM 框架各自为营的局面。

注意:JPA 是在充分吸收了现有 Hibernate,TopLink,JDO 等ORM框架的基础上发展而来的,具有易于使用,伸缩性强等优点。

 

总的来说,JPA包括以下3方面的技术:

• ORM映射元数据

JPA支持XML和JDK5.0注释(也可译作注解)两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中。

• Java持久化API

用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者可以从繁琐的JDBC和SQL代码中解脱出来。

• 查询语言(JPQL)

这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。

2、spring data jpa

Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套 JPA 应用框架,底层使用了 Hibernate 的 JPA 技术实现,可使开发者用极简的代码即可实现对数据的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展。

优点:丰富的API,简单操作无需编写额外的代码;丰富的SQL日志输出

缺点:学习成本较大,需要学习HQL;配置复杂,虽然SpringBoot简化的大量的配置,关系映射多表查询配置依旧不容易;

性能较差,对比JdbcTemplateMybatis等ORM框架,它的性能是最差的;

 

3、添加依赖

接下来步入正题

        <!-- Spring JDBC 的依赖包-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<!-- MYSQL包 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>

4、修改配置文件

spring.datasource.url=jdbc:mysql://localhost:3306/springboot_study?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
        
## JPA配置
#spring.jpa.hibernate.ddl-auto=update
# 打印sql语句日志
spring.jpa.show-sql=true

,下面简单介绍下spring.jpa.properties.hibernate.hbm2ddl.auto有几种配置:

  • create:每次加载Hibernate时都会删除上一次生成的表(包括数据),然后重新生成新表,即使两次没有任何修改也会这样执行。适用于每次执行单测前清空数据库的场景。
  • create-drop:每次加载Hibernate时都会生成表,但当SessionFactory关闭时,所生成的表将自动删除。
  • update:最常用的属性值!!!,第一次加载Hibernate时创建数据表(前提是需要先有数据库),以后加载Hibernate时不会删除上一次生成的表,会根据实体更新,只新增字段,不会删除字段(即使实体中已经删除)。
  • validate:每次加载Hibernate时都会验证数据表结构,只会和已经存在的数据表进行比较,根据model修改表结构,但不会创建新表。
  • springboot_study是数据库的名称,请自己建 

如果不配置此项,表示禁用自动建表功能;笔者建议禁用该功能,实体映射成表可能会出现异常,推荐大家自己手动建表

5、手动建表

user.sql


SET FOREIGN_KEY_CHECKS=0;


DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL,
  `username` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO `user` (`id`, `username`, `age`) VALUES (1, 'aaa', 18);
INSERT INTO `user` (`id`, `username`, `age`) VALUES (2, 'bbb', 18);
INSERT INTO `user` (`id`, `username`, `age`) VALUES (3, 'ccc', 20);
INSERT INTO `user` (`id`, `username`, `age`) VALUES (4, 'ddd', 24);

6、实体类

 

新建User类:

package com.zj.springbootstudy.domain;

import javax.persistence.Entity;
import javax.persistence.Id;

/**
 * @Auther: zj
 * @Date: 2019/1/19 17:58
 * @Description:
 */
@Entity
//@Table
//@Version
public class User {

    @Id
    //@GeneratedValue(strategy = GenerationType.IDENTITY) // 自增长策略
    private Integer id;

    //@Column
    private String username;

    //@Column
    //@Transient
    private Integer age;

    //注意:无参构造函数不能省!!!
    protected User() { JPA 的规范要求无参构造函数;设为 protected 防止直接使用

    }

    public User(Integer id, String username, Integer age) {
        this.id = id;
        this.username = username;
        this.age = age;
    }

//下面是getter,setter方法
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() { //重写toString() 方法,便于打印消息
        return String.format("User[id=%d, username='%s', age=%d]",
                id, username, age);
    }
}
@Entity 表示 对实体注释。任何Hibernate映射对象都要有这个注释,很重要
@Id 声明此属性为主键。该属性值可以通过应该自身创建,也可以通过Hibernate自动生成但推荐手动建表

拓展:

1、@Table   声明此对象映射到数据库的数据表,通过它可以为实体指定表(talbe),目录(Catalog)和schema的名字。该注释不是必须的,如果没有则系统使用默认值(实体的短类名) 

源码如下:

2、@Version  该注释可用于在实体Bean中添加乐观锁支持

 

3、@GeneratedValue  指定主键的生成策略

有如下四个值:

 TABLE:使用表保存id值,容器指定用底层的数据表确保唯一;

 IDENTITY:identitycolumn 使用数据库德SEQUENCE列莱保证唯一(Oracle数据库通过序列来生成唯一ID);

 SEQUENCR :sequence 使用数据库的IDENTITY列莱保证唯一

 AUTO:根据数据库的不同自动使用上面三个

 4、@Column 声明该属性与数据库字段的映射关系。

我们点进去看她的源码:

可以看出,该注解有许多属性

1)name:映射的列名。如:映射tbl_user表的name列,可以在name属性的上面或getName方法上面加入;

2)unique:是否唯一;

3)nullable:是否允许为空;

4)length:对于字符型列,length属性指定列的最大字符长度;

5)insertable:是否允许插入;

6)updatetable:是否允许更新;

7)columnDefinition:定义建表时创建此列的DDL;

 5、@Transient  如果不想让一些成员属性映射成数据库字段,可以使用@Transient注释进行标注。

6、@OneToMany,@ManyToMany,@OneToOne,@ManyToOne 声明关联关系,外键关联
一般和@JoinTable配合使用

 @ManyToMany(cascade = {CascadeType.REFRESH},fetch = FetchType.EAGER) //这里一定要立即加载,不然会报错:org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role。。。。
    // 因为在获取一方的时候一方是获取到了,但是再获取多方的时候session已经关闭了,这时候会获取不到多方信息,因此报错。
    @JoinTable(
            name = "sys_user_role",
            joinColumns = @JoinColumn(
                    name = "user_id",referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(
                    name = "role_id",referencedColumnName = "id"
            )
    )
    private List<SysRole> roles;

如非必要,不建议使用外键关联,比较危险

7、创建数据访问接口(数据访问层)

public interface UserRepository extends JpaRepository<User,Integer>{

}

我们的UserRepository继承JpaRepository<User,Integer>这个接口,

发现后面的泛型是什么东东?

查看JpaRepository源码:

由此我们发现,User是我们现前创的类,Integer是主键的类型 

还发现JpaRepository默认预先生成了一些基本的CURD的方法,例如:创建(save)、更新(save)、删除(delete)、查询(findAll、findOne)等等

自定义的简单查询

根据官方文档所说,还可以自定义的简单查询就是根据方法名来自动生成SQL

修改UserRepository:

public interface UserRepository extends JpaRepository<User,Integer>{
    User findByUsername(String username);
    
    User findByAge(Integer age);
}

单元测试:我们一般写完一个方法,就需编写对应的单元测试来验证编写的内容是否正确

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserRepositoryTest {

    @Autowired
    UserRepository userRepository;
    @Test
    public void findByUsername() throws Exception {

        System.out.println(  userRepository.findByUsername( "aaa" ));

    }

}

结果:

表明测试无误,接下来的例子就不贴了

 

 

也可以使用一些加一些关键字And、 Or

User findByUsernameOrAge(String username, Integer age );

修改、删除、统计也是类似语法

void deleteById(Long id);

Long countByUsername(String username)

基本上SQL体系中的关键词都可以使用,例如:LIKE、 IgnoreCase、 OrderBy等等

List<User> findByUsernameLike(String username);

User findByUsernameIgnoreCase(String username);
    
List<User> findByUserNameOrderByAgeDesc(String age);

jpa一般规则:

这就是Spring-data-jpa的一大特性:通过解析方法名创建查询

除了通过解析方法名来创建查询外,它也提供通过使用@Query 注解来创建查询,您可以手写sql语句

---

@Query("select u from User u where u.username = username")
    User findByUsername2(String username);

--

分页查询

修改UserRepository,添加下方的代码:

 Page<User> findAll(Pageable pageable);

Pageable 是spring封装的分页实现类,查看其源码发现

使用的时候可以传入页数、每页条数和排序规则等

单元测试:

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserRepositoryTest {

    @Autowired
    UserRepository userRepository;

    @Test
    public void findAll() throws Exception {

        Sort sort = new Sort( Sort.Direction.DESC, "id");
//        Pageable pageable = new PageRequest(0, 3,sort); 已经废弃!!!
        Pageable pageable = PageRequest.of( 0,3,sort);
        System.out.println( userRepository.findAll( pageable ).getContent() );
    }
}

结果:

注意:

 PageRequest 已经废弃,现在是PageRequest,我们查看其源码:

page传入页数、size每页条数和sort排序规则

8、server层

新建文件目录

这里只举一个例子,其他类推

UserService:

public interface UserService {

    List<User> listAllUserWithPage(Pageable pageable);

}

UserServiceImpl:

@Service
public class UserServiceImpl implements UserService{
    @Autowired
    UserRepository userRepository;
    
    @Override
    public List<User> listAllUserWithPage(Pageable pageable) {
        
        return userRepository.findAll( pageable ).getContent();
    }
}

9、controller层

@RestController
public class UserController {

    @Autowired
    UserService userService;

    @GetMapping("/test")
    public Object test11111() {

        Sort sort = new Sort( Sort.Direction.DESC, "id");
        Pageable pageable = PageRequest.of( 0,3,sort);
        
        return userService.listAllUserWithPage( pageable);
    }

}

 测试:

参考:

https://www.cnblogs.com/lich/archive/2011/11/27/2265253.html

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小牛呼噜噜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值