溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring JPA使用案例分析

發(fā)布時間:2022-02-25 10:29:34 來源:億速云 閱讀:286 作者:iii 欄目:開發(fā)技術

今天小編給大家分享一下Spring JPA使用案例分析的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

1.什么是JPA

JPA (Java Persistence API) 是 Sun 官方提出的 Java 持久化規(guī)范。它為 Java 開發(fā)人員提供了一種對象/關聯(lián)映射工具來管理 Java 應用中的關系數(shù)據(jù)。他的出現(xiàn)主要是為了簡化現(xiàn)有的持久化開發(fā)工作和整合 ORM 技術,結束現(xiàn)在 Hibernate,TopLink,JDO 等 ORM 框架各自為營的凌亂局面。JPA 在充分吸收了現(xiàn)有Hibernate,TopLinkJDOORM框架的基礎上發(fā)展而來的,具有易于使用,伸縮性強等優(yōu)點。從上面的解釋中我們可以了解到JPA 是一套規(guī)范,而類似 Hibernate,TopLink,JDO這些產品是實現(xiàn)了 JPA 規(guī)范。

了解了什么是 JPA,我們來看看本文的主角——spring data jpa

2.spring data jpa

pring Data JPASpring 基于 ORM 框架、JPA規(guī)范的基礎上封裝的一套 JPA 應用框架,底層使用了 HibernateJPA 技術實現(xiàn),可使開發(fā)者用極簡的代碼即可實現(xiàn)對數(shù)據(jù)的訪問和操作。它提供了包括增刪改查等在內的常用功能,且易于擴展!學習并使用 Spring Data JPA 可以極大提高開發(fā)效率。

什么意思呢?如果用過Hibernate 或者MyBatis 的話,就會知道對象關系映射(ORM)框架有多么方便。但是Spring Data JPA框架功能更進一步,為我們做了 一個數(shù)據(jù)持久層框架幾乎能做的任何事情。以Springboot整合MyBatis為例,比如我們要向數(shù)據(jù)庫中插入一些用戶的數(shù)據(jù),那么我們需要先定義用戶的實體類,然后我們要定義一個UserDao

@Repository
public class UserDao {
    @Autowired
    JdbcTemplate jdbcTemplate;


    public int addUser(User user){
    return jdbcTemplate.update("INSERT INTO t_user(username,jobs,phone) VALUE (?,?,?)",
    user.getName,user.getJobs,user.getPhone);
    }
    public int updateUser(User user){
    return jdbcTemplate.update("UPDATE t_user SET username=?,jobs=?,phone=? WHERE id=?",
    user.getName,user.getJobs,user.getPhone,user.getId);
    }
    public int deleteUser(Integer id){
    return jdbcTemplate.update("DELETE FROM t_user WHERE id=?",id);
    }
    public User getUserById(Integer id){
    return jdbcTemplate.queryForObject("SELECT * FROM t_user WHERE id =?",new BeanPropertyRowMapper<>(User.class),id);
    }
    public List<User> getAllUser{
    return jdbcTemplate.query("SELECT * FROM t_user",new BeanPropertyRowMapper<>(User.class));
    }
}

以及UserService

@Service
public class UserService {


    @Autowired
    UserDao userDao;
    public int addUser(User user){
    return userDao.addUser(user);
    }
    public int updateUser(User user){
    return userDao.updateUser(user);
    }
    public int deleteUser(Integer id){
    return userDao.deleteUser(id);
    }
    public User getUserById(Integer id){
    return userDao.getUserById(id);
    }
    public List<User> getAllUser{
    return userDao.getAllUser;
    }
}

最后,我們在去調用對應的service 中的方法。這是傳統(tǒng)的方式,如果使用mapper,會稍微簡單一些,比如我們要添加mapper

@Mapper
public interface UserMapper {
    int addUser(User user);
    int deleteUser(int id);
    int updateUser(User user);
    User getUserById(Integer id);
    List<User> getAllUsers;


}

然后定義一個UserMapper.xml ,添加對應的CURD SQL語句,做好映射,然后改造service,例如

@Service
public class UserService {


    @Autowired
    UserMapper userMapper;
    public int addUser(User user){
    return userMapper.addUser(user);
    }
    public int updateUser(User user){
    return userMapper.updateUser(user);
    }
    public int deleteUser(Integer id){
    return userMapper.deleteUser(id);
    }
    public User getUserById(Integer id){
    return userMapper.getUserById(id);
    }
    public List<User> getAllUser{
    return userMapper.getAllUsers;
    }
}

發(fā)現(xiàn)什么問題了嗎?如果我們要去實現(xiàn)多個表的操作,我們需要定義不同的實體類,然后實現(xiàn)對應的mapper,然后寫同樣的增刪改查方法,最后調用。這也太麻煩了些,而Spring data jpa 則可以輕松的幫我們實現(xiàn)這些繁瑣重復且沒有技術含量的操作。我們一起看下吧!

3.案例演示

1.首先,我們需要配置pom.xml

<dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

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

2.然后是application.properties 的配置

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

這里重點簡單介紹下spring.jpa.properties.hibernate.hbm2ddl.auto有幾種配置:

  • create:表示每次加載Hibernate時都會刪除上一次生成的表(包括數(shù)據(jù)),然后重新生成新表,即使兩次沒有任何修改也會這樣執(zhí)行。適用于每次執(zhí)行單測前清空數(shù)據(jù)庫的場景。

  • create-drop:表示每次加載Hibernate時都會生成表,但當SessionFactory關閉時,所生成的表將自動刪除。

  • update:最常用的屬性值,第一次加載Hibernate時創(chuàng)建數(shù)據(jù)表(前提是需要先有數(shù)據(jù)庫),以后加載Hibernate時不會刪除上一次生成的表,會根據(jù)實體更新,只新增字段,不會刪除字段(即使實體中已經刪除)。

  • validate:每次加載Hibernate時都會驗證數(shù)據(jù)表結構,只會和已經存在的數(shù)據(jù)表進行比較,根據(jù)model修改表結構,但不會創(chuàng)建新表。

  • 不配置此項,表示禁用自動建表功能

spring.jpa.show-sql=true 該配置當在執(zhí)行數(shù)據(jù)庫操作的時候會在控制臺打印 sql 語句,方便我們檢查排錯等。

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect 這是數(shù)據(jù)庫的方言配置。

3.接下來我們建立用戶實體類

@Entity
public class User {

 
    @Id
    @GeneratedValue
    private long id;
    @Column(nullable = false, unique = true)
    private String userName;
    @Column(nullable = false)
    private String password;
    @Column(nullable = false)
    private int age;
}

這里的一些注解解釋如下:

  • @Entity 是一個類注解,用來注解該類是一個實體類用來進行和數(shù)據(jù)庫中的表建立關聯(lián)關系,首次啟動項目的時候,默認會在數(shù)據(jù)中生成一個同實體類相同名字的表(table),也可以通過注解中的 name 屬性來修改表(table)名稱, 如@Entity(name=“user”) , 這樣數(shù)據(jù)庫中表的名稱則是 user。該注解十分重要,如果沒有該注解首次啟動項目的時候你會發(fā)現(xiàn)數(shù)據(jù)庫沒有生成對應的表。

  • @Table 注解也是一個類注解,該注解可以用來修改表的名字,該注解完全可以忽略掉不用,@Entity 注解已具備該注解的功能。

  • @Id 類的屬性注解,該注解表明該屬性字段是一個主鍵,該屬性必須具備,不可缺少。

  • @GeneratedValue 該注解通常和 @Id 主鍵注解一起使用,用來定義主鍵的呈現(xiàn)形式,該注解通常有多種使用策略,先總結如下:

  • @GeneratedValue(strategy= GenerationType.IDENTITY) 該注解由數(shù)據(jù)庫自動生成,主鍵自增型,在 mysql 數(shù)據(jù)庫中使用最頻繁,oracle 不支持。

  • @GeneratedValue(strategy= GenerationType.AUTO)  主鍵由程序控制,默認的主鍵生成策略,oracle 默認是序列化的方式,mysql 默認是主鍵自增的方式。

  • @GeneratedValue(strategy= GenerationType.SEQUENCE) 根據(jù)底層數(shù)據(jù)庫的序列來生成主鍵,條件是數(shù)據(jù)庫支持序列,Oracle支持,Mysql不支持。

  • @GeneratedValue(strategy= GenerationType.TABLE) 使用一個特定的數(shù)據(jù)庫表格來保存主鍵,較少使用。

上面這些主鍵生成策略中,以 mysql 為例,  IDENTITY  AUTO 用的較多,二者當中IDENTIT 用的多些,以下文章當中演示的 demo 主鍵均使用 @GeneratedValue(strategy= GenerationType.IDENTITY) 的生成策略。

@Column 是一個類的屬性注解,該注解可以定義一個字段映射到數(shù)據(jù)庫屬性的具體特征,比如字段長度,映射到數(shù)據(jù)庫時屬性的具體名字等。

@Transient  是一個屬性注解,該注解標注的字段不會被映射到數(shù)據(jù)庫當中。

4. 聲明 UserRepository接口,繼承JpaRepository,如下所示

public interface UserRepository extends JpaRepository<User, Long> {

 
}

這里的 JpaRepository繼承了接口PagingAndSortingRepositoryQueryByExampleExecutor。而,PagingAndSortingRepository又繼承CrudRepository

因此,JpaRepository接口同時擁有了基本CRUD功能以及分頁功能。因此,這里我們可以繼承JpaRepository,從而獲得Spring為我們預先定義的多種基本數(shù)據(jù)操作方法。

5.然后我們定義一個測試類,  這里我們演示下添加操作, @Transactional 表示開啟事務防止出現(xiàn)臟數(shù)據(jù)。

        ……
        @Autowired
    private UserRepository userRepository;

 
    @Test
    @Transactional
    public void userAddTest() {
        User user = new User();
        user.setUserName("吳彥祖");
        user.setAge(30);
        user.setPassword("123456");
        userRepository.save(user);
        User item = userRepository.findByUserName("wyk");
        log.info(JsonUtils.toJson(item));
    }

6.接下來我們說下查詢,查詢可以分為基本查詢和自定義查詢,一種是 spring data 默認已經實現(xiàn),只需要要繼承JpaRepository,一種是根據(jù)查詢的方法來自動解析成 SQL。

@Test
public void testQuery() throws Exception {
    User user=new User();
    userRepository.findAll();
    userRepository.findOne(1l);
    userRepository.save(user);
    userRepository.delete(user);
    userRepository.count();
    userRepository.exists(1l);
    ……
}

7.自定義的簡單查詢就是根據(jù)方法名來自動生成SQL,主要的語法是findXXBy,readAXXBy,queryXXBy,countXXBy, getXXBy后面跟屬性名稱,舉幾個例子:

User findByUserName(String userName);

 
User findByUserNameOrEmail(String username, String email);

 
Long deleteById(Long id);

 
Long countByUserName(String userName);

 
List<User> findByEmailLike(String email);

 
User findByUserNameIgnoreCase(String userName);

 
List<User> findByUserNameOrderByEmailDesc(String email);

8.接下來,我們說下復雜的查詢,在實際的開發(fā)中我們需要用到分頁、刪選、連表等查詢的時候就需要特殊的方法或者自定義 SQL,以分頁查詢?yōu)槔?,分頁查詢在實際使用中非常普遍了,spring data jpa已經幫我們實現(xiàn)了分頁的功能,在查詢的方法中,需要傳入?yún)?shù)Pageable,當查詢中有多個參數(shù)的時候Pageable建議做為最后一個參數(shù)傳入。Pageablespring 封裝的分頁實現(xiàn)類,使用的時候需要傳入頁數(shù)、每頁條數(shù)和排序規(guī)則

Page<User> findALL(Pageable pageable);

 
Page<User> findByUserName(String userName,Pageable pageable);

9.我們看下下面的測試用例

@Test
public void testPageQuery() throws Exception {
    int page=1,size=5;
    Sort sort = new Sort(Direction.DESC, "id");
    Pageable pageable = new PageRequest(page, size, sort);
    userRepository.findALL(pageable);
    userRepository.findByUserName("testName", pageable);
}
  1. Spring data 大部分的SQL都可以根據(jù)方法名定義的方式來實現(xiàn),但是由于某些原因我們想使用自定義的 SQL 來查詢,spring data 也是完美支持的,如下所示:

@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 JPA使用案例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

AI