zoukankan      html  css  js  c++  java
  • Springboot+Jpa的使用

    首先了解JPA是什么?

    JPA(Java Persistence API)是Sun官方提出的Java持久化规范。它为Java开发人员提供了一种

    对象/关联映射工具来管理Java应用中的关系数据。他的出现主要是为了简化现有的持久化开发工作和

    整合ORM技术,结束现在Hibernate,TopLink,JDO等ORM框架各自为营的局面。值得注意的是,

    JPA是在充分吸收了现有Hibernate,TopLink,JDO等ORM框架的基础上发展而来的,具有易于使用,

    伸缩性强等优点。从目前的开发社区的反应上看,JPA受到了极大的支持和赞扬,其中就包括了Spring

    与EJB3.0的开发团队。

    注意:JPA是一套规范,不是一套产品,那么像Hibernate,TopLink,JDO他们是一套产品,如果

    说这些产品实现了这个JPA规范,那么我们就可以叫他们为JPA的实现产品。

    spring data jpa

    Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套JPA应用框架,可使

    开发者用极简的代码即可实现对数据的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩

    展!学习并使用 Spring Data JPA  可以极大提高开发效率!

    spring data jpa让我们解脱了DAO层的操作,基本上所有CRUD都可以依赖于它来实现

    基本查询

    基本查询也分为两种,一种是spring data默认已经实现,一种是根据查询的方法来自动解析成SQL。

    预先生成方法

    spring data jpa 默认预先生成了一些基本的CURD的方法,例如:增、删、改等等

    1 继承JpaRepository

    public interface UserRepository extends JpaRepository<User, Long> {
    }
    2 使用默认方法
    @Test
    public void testBaseQuery() throws Exception {
        User user=new User();
        userRepository.findAll();
        userRepository.findOne(1l);
        userRepository.save(user);
        userRepository.delete(user);
        userRepository.count();
        userRepository.exists(1l); 
        // ...
    }

    自定义简单查询

    自定义的简单查询就是根据方法名来自动生成SQL,主要的语法是
    findXXBy,readAXXBy,queryXXBy,countXXBy, getXXBy后面跟属性名称:
    User findByUserName(String userName);
    也使用一些加一些关键字And、 Or
    User findByUserNameOrEmail(String username, String email);
    修改、删除、统计也是类似语法
    Long deleteById(Long id);
    Long countByUserName(String userName)
    基本上SQL体系中的关键词都可以使用,例如:LIKE、 IgnoreCase、 OrderBy。
    List<User> findByEmailLike(String email);
    User findByUserNameIgnoreCase(String userName);
    List<User> findByUserNameOrderByEmailDesc(String email);

    分页查询

    分页查询在实际使用中非常普遍了,spring data jpa已经帮我们实现了分页的功能,在查询的
    方法中,需要传入参数Pageable
    ,当查询中有多个参数的时候Pageable建议做为最后一个参数传入
    Page<User> findALL(Pageable pageable);
    Page<User> findByUserName(String userName,Pageable pageable);

    Pageable 是spring封装的分页实现类,使用的时候需要传入页数、每页条数和排序规则

    @Test
    public void testPageQuery() throws Exception {    
        int page=1,size=10;
        Sort sort = new Sort(Direction.DESC, "id");
        Pageable pageable = new PageRequest(page, size, sort);
        userRepository.findALL(pageable);
        userRepository.findByUserName("testName", pageable);
    }

    限制查询

    有时候我们只需要查询前N个元素,或者支取前一个实体。

    ser findFirstByOrderByLastnameAsc();
    User findTopByOrderByAgeDesc();
    Page<User> queryFirst10ByLastname(String lastname, Pageable pageable);
    List<User> findFirst10ByLastname(String lastname, Sort sort);
    List<User> findTop10ByLastname(String lastname, Pageable pageable);

    自定义SQL查询

    其实Spring data 觉大部分的SQL都可以根据方法名定义的方式来实现,但是由于某些原因我们想使用

    自定义的SQL来查询,spring data也是完美支持的;在SQL的查询方法上面使用@Query注解,如涉及到

    删除和修改在需要加上@Modifying.也可以根据需要添加 @Transactional 对事物的支持,查询超时的设

    置等

    @Modifying
    @Query("update User u set u.userName = ?1 where c.id = ?2")
    int modifyByIdAndUserId(String  userName, Long id);
    
    @Transactional
    @Modifying
    @Query("delete from User where id = ?1")
    void deleteByUserId(Long id);
    
    @Transactional(timeout = 10)
    @Query("select u from User u where u.emailAddress = ?1")    
    User findByEmailAddress(String emailAddress);

    多表查询

    多表查询在spring data jpa中有两种实现方式,第一种是利用hibernate的级联查询来实现,第二种是

    创建一个结果集的接口来接收连表查询后的结果,这里主要第二种方式。

    首先需要定义一个结果集的接口类。

    public interface HotelSummary {
        City getCity();
        String getName();    
        Double getAverageRating();    
        default Integer getAverageRatingRounded() {
                return getAverageRating() == null ? null : (int) Math.round(getAverageRating());
        }
    }

    查询的方法返回类型设置为新创建的接口

    @Query("select h.city as city, h.name as name, avg(r.rating) as averageRating "
            - "from Hotel h left outer join h.reviews r where h.city = ?1 group by h")
    Page<HotelSummary> findByCity(City city, Pageable pageable);
    
    @Query("select h.name as name, avg(r.rating) as averageRating "
            - "from Hotel h left outer join h.reviews r  group by h")
    Page<HotelSummary> findByCity(Pageable pageable);

    使用

    Page<HotelSummary> hotels = this.hotelRepository.findByCity(new PageRequest(0, 10, Direction.ASC, "name"));
    for(HotelSummary summay:hotels){
            System.out.println("Name" +summay.getName());
        }

    在运行中Spring会给接口(HotelSummary)自动生产一个代理类来接收返回的结果,代码汇总使用getXX的形式来获取

    多数据源的支持

    同源数据库的多源支持

    日常项目中因为使用的分布式开发模式,不同的服务有不同的数据源,常常需要在一个项目中使用多个数据源,

    因此需要配置sping data jpa对多数据源的使用,一般分一下为三步:

    • 1 配置多数据源

    • 2 不同源的实体类放入不同包路径

    • 3 声明不同的包路径下使用不同的数据源、事务支持

    这里有一篇文章写的很清楚:Spring Boot多数据源配置与使用

    异构数据库多源支持

    比如我们的项目中,即需要对mysql的支持,也需要对mongodb的查询等。

    实体类声明@Entity 关系型数据库支持类型、声明@Document 为mongodb支持类型,不同的数据源使用不同的实体就可以了

    interface PersonRepository extends Repository<Person, Long> {
     …
    }
    
    @Entity
    public class Person {
      …
    }
    
    interface UserRepository extends Repository<User, Long> {
     …
    }
    
    @Document
    public class User {
      …
    }

    但是,如果User用户既使用mysql也使用mongodb呢,也可以做混合使用

    interface JpaPersonRepository extends Repository<Person, Long> {
     …
    }
    
    interface MongoDBPersonRepository extends Repository<Person, Long> {
     …
    }
    
    @Entity
    @Document
    public class Person {
      …
    }

    也可以通过对不同的包路径进行声明,比如A包路径下使用mysql,B包路径下使用mongoDB

    @EnableJpaRepositories(basePackages = "com.neo.repositories.jpa")
    @EnableMongoRepositories(basePackages = "com.neo.repositories.mongo")
    interface Configuration { }

    其它

    使用枚举

    使用枚举的时候,我们希望数据库中存储的是枚举对应的String类型,而不是枚举的索引值,需要在属性上面

    添加@Enumerated(EnumType.STRING) 注解

    @Enumerated(EnumType.STRING) 
    @Column(nullable = true)
    private UserType type;

    不需要和数据库映射的属性

    正常情况下我们在实体类上加入注解@Entity,就会让实体类和表相关连如果其中某个属性我们不需要和数据库

    来关联只是在展示的时候做计算,只需要加上@Transient属性既可。

    @Transient
    private String  userName;

    这里有一个开源项目几乎使用了这里介绍的所有标签和布局,大家可以参考:https://github.com/cloudfavorites/favorites-web

    代码示例
    --------------------------------------------------------------------------------------------------------

    1.配置pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>SpringBootJpa</groupId> <artifactId>springBoot-Jpa</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>springBoot-Jpa Maven Webapp</name> <url>http://maven.apache.org</url> <!-- 继承父包 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.1.3.RELEASE</version> <relativePath></relativePath> </parent> <dependencies> <!-- https://mvnrepository.com/artifact/junit/junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> </dependencies> <build> <finalName>springBoot-Jpa</finalName> <!-- 配置java版本 不配置的话默认父类配置的是1.6--> <pluginManagement> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin> </plugins> </pluginManagement> </build> </project> 2.创建两个实体类 User.java package com.boot.entity; import java.io.Serializable; 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.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; @Entity @Table(name = "user") public class User implements Serializable{ /** * */ private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Integer userId; @Column(name = "id") private Integer id; @Column(name = "user_name") private String userName; @Column(name = "password") private String password; @Column(name = "nick_name") private String nickName; @Column(name="email") private String email; @Column(name="did",insertable=false,updatable=false) private Integer dId; @ManyToOne(cascade={CascadeType.MERGE,CascadeType.REFRESH}, fetch=FetchType.EAGER,optional=false) @JoinColumn(name="did",referencedColumnName = "id") private Dept dept; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getNickName() { return nickName; } public void setNickName(String nickName) { this.nickName = nickName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public User(Integer userId,Integer id, String userName, String password, String nickName, String email, Integer dId) { super(); this.userId = userId; this.id=id; this.userName = userName; this.password = password; this.nickName = nickName; this.email = email; this.dId = dId; } public User() { super(); // TODO Auto-generated constructor stub } public Integer getdId() { return dId; } public void setdId(Integer dId) { this.dId = dId; } public Dept getDept() { return dept; } public void setDept(Dept dept) { this.dept = dept; } public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } } Dept.java package com.boot.entity; import java.io.Serializable; import java.util.Set; 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; @Entity @Table(name = "dept") public class Dept implements Serializable{ /** * */ private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id", nullable = false) private Integer id; @Column(name="dept_id") private Integer deptId; @Column(name="dept_name") private String dept_name; @OneToMany (cascade={CascadeType.REFRESH, CascadeType.MERGE, CascadeType.REMOVE, CascadeType.PERSIST}, fetch=FetchType.LAZY,mappedBy="userId") private Set<User> user; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getDeptId() { return deptId; } public void setDeptId(Integer deptId) { this.deptId = deptId; } public String getDept_name() { return dept_name; } public void setDept_name(String dept_name) { this.dept_name = dept_name; } public Set<User> getUser() { return user; } public void setUser(Set<User> user) { this.user = user; } 3.编写application.properties spring.datasource.platform=mysql spring.datasource.url=jdbc:mysql://localhost/workdatabase?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&autoReconnect=true&failOverReadOnly=false spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driverClassName=com.mysql.jdbc.Driver # Advanced configuration... spring.datasource.max-active=50 spring.datasource.max-idle=6 spring.datasource.min-idle=2 spring.datasource.initial-size=6 #create table spring.jpa.hibernate.ddl-auto=validate spring.jpa.database: MYSQL spring.profiles.active=dev server.port=8080 server.session-timeout=30 server.tomcat.uri-encoding=UTF-8 #redirect spring.mvc.view.prefix=/Page/ spring.mvc.view.suffix=.jsp application.message: Hello Phil 5.编写接口IUserService.java package com.boot.serve; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.transaction.annotation.Transactional; import com.boot.entity.User; public interface IUserServe extends JpaRepository<User, Integer> { /*User findById(Integer id); User findByUserName(String userName); User findByUserNameAndPassword(String userName, String password); List<User> findByUserNameLike(String username); List<User> findByUserNameNotLike(String username); List<User> findByUserNameNot(String username);*/ //使用jpa注解来实现对数据库的操作 // @Query("Select new com.boot.entity.User(u.id,u.userName,u.password,u.nickName,u.email,u.deptId) FROM User u,Dept d WHERE u.deptId = d.deptId and u.deptId = ?1 AND u.password IS NOT NULL") @Query("from User u inner join fetch u.dept as d where d.id=?1") List<User> findByDeptId(Integer deptId); @Query("UPDATE User u SET u.password=?2 WHERE u.userName=?1") @Modifying @Transactional void updatePwd(String userName, String pwd); @Query("DELETE FROM User u WHERE u.userName=?1") @Modifying @Transactional void deleteByUserName(String userName); @Query("UPDATE User u SET u.email= :email WHERE u.userName = :user") @Modifying @Transactional void updateEmail(@Param("user") String userName, @Param("email") String email); } 7.编写测试类 package com.boot.test; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import com.boot.Application; import com.boot.entity.User; import com.boot.serve.IUserServe; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration public class UserTest { @Autowired private IUserServe userService; @Test public void test1(){ System.out.println("welcome"); } @Test public void testQuery() { List<User> list = userService.findByDeptId(3); /* for(int i =0;i<list.size();i++){ System.out.println(list.get(i).getUserName()+" "+list.get(i).getPassword()+" "+list.get(i).getDeptId()); }*/ for(User u : list){ System.out.println(u.getUserName()+" "+u.getPassword()+" "+u.getNickName()+" "+u.getEmail()+" "); switch(u.getUserId()){ case 1: System.out.println("开发部"); break; case 2: System.out.println("财务部"); break; case 3: System.out.println("测试部"); break; default: System.out.println("商务部"); break; } /*if(u.getdId()==1){ System.out.println("开发部"); }else if(u.getdId()==2){ System.out.println("财务部"); }else if(u.getdId()==3){ System.out.println("测试部"); }else{ System.out.println("商务部"); }*/ } } }
  • 相关阅读:
    uoj 36 玛里苟斯
    readlink
    Endless Spin
    rm
    rmdir
    [学习笔记]min-max容斥
    cp
    [HAOI2015]按位或
    java实现第四届蓝桥杯公式求值
    java实现第四届蓝桥杯危险系数
  • 原文地址:https://www.cnblogs.com/xiaolei2017/p/8079003.html
Copyright © 2011-2022 走看看