spring-data-jdbc的基礎使用(一)


前言

很多人知道Mybatis,知道Jpa,但是對spring-data-jdbc可能了解的少之又少。注意我們這里說的是data-jdbc,而不是普通的jdbc。它擁有了類似jpa的一些特性,比如能夠根據方法名推導出sql,基本的CRUD等,也擁有了寫原生sql的能力。最為關鍵的是,它非常的清爽,不需要依賴hibernte或者jpa。

一、使用https://start.spring.io/ ,建立一個demo

file

二、使用 Java 配置的 Spring Data JDBC


// @EnableJdbcRepositories  為接口Repository 創建實現
//AbstractJdbcConfiguration 提供 Spring Data JDBC 所需的各種默認 bean
@Configuration
@EnableJdbcRepositories(basePackages = "com.example.springdatajdbctest")
public class ApplicationConfiguration extends AbstractJdbcConfiguration {



    /**
     * 創建DataSource,使用springboot的默認的連接池,當然你也可以使用druid
     * ConfigurationProperties注解,去配置項中找spring.datasource開頭的配置項,來創建DataSource
     */

    @Bean
    @ConfigurationProperties(prefix="spring.datasource" )
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }
    /**
     * 官方使用內置的數據庫類型
     @Bean
     public DataSource dataSource() {
     EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
     return builder.setType(EmbeddedDatabaseType.H2).build();
     }
     */

    /**
     * NamedParameterJdbcOperations是Spring Data JDBC 用來訪問數據庫的
     * @param dataSource
     * @return
     */
    @Bean
    NamedParameterJdbcOperations namedParameterJdbcOperations(DataSource dataSource) {
        return new NamedParameterJdbcTemplate(dataSource);
    }

    /**
     * 提供的事務管理
     * @param dataSource
     * @return
     */
    @Bean
    TransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

對應的application.properties內容如下:

spring.datasource.jdbc-url = jdbc:mysql://127.0.0.1/sss?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useAffectedRows=true
spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver
spring.datasource.username = root
spring.datasource.password = ****

三、數據庫建表、建實體類

create table user_info
(
    id          int auto_increment  primary key,
    name        varchar(32)       not null,
    age         int               not null,
    sex         tinyint default 1 not null,
    create_time datetime          not null,
    update_time datetime          not null
)
    comment '用戶表';

@Data
public class UserInfo extends BaseEntity{
    /**
     * ID注解需要加上,標記為主鍵,否則無法識別主鍵
     * 其他字段不需要加對應的列明,表名也可以不加注解,前提是類名、字段名符合標准的駝峰命名規范,否則無法對應上
     */
    @Id
    private Integer id ;
    private String name;
    private Integer age;
    private Integer sex;
}

@Data
public class BaseEntity {
    private LocalDateTime createTime;
    private LocalDateTime updateTime;
}

四、建立倉儲接口UserInfoRepository

/**
 * 這里CrudRepository接口已經提供了常見的一些接口,因此這里繼承CrudRepository
 */
public interface UserInfoRepository extends CrudRepository<UserInfo, Integer> {

}

/**
* 也可以繼承PagingAndSortingRepository,它繼承了CrudRepository,多了排序和分頁默認方法
*/
public interface UserInfoRepository extends PagingAndSortingRepository<UserInfo, Integer> {

}

五、運行一下:

@SpringBootTest
@RunWith(SpringRunner.class)
class SpringDataJdbcTestApplicationTests {

	@Autowired
	private UserInfoRepository userInfoRepository;

	@Test
	public void testGet() {
		Optional<UserInfo> userInfo = userInfoRepository.findById(1);
		System.out.println(userInfo.get());
	}

	@Test
	public void testCount() {
		long count = userInfoRepository.count();
		System.out.println(count);
	}

}

file

六、關鍵字查詢方法

如果默認方法中沒有我們需要的方法,我們還可以按規則來編寫關鍵字查詢方法。可以通過帶有關鍵字的方法名來解析出SQL,比如

public interface UserInfoRepository extends PagingAndSortingRepository<UserInfo, Integer> {
    List<UserInfo> findByName(String ame);
}

這樣無需寫SQL語句,就能查詢出我們想要的結果。這里使用的是關鍵字findBy后面的既是需要的查詢條件,當然還支持復合查詢。比如

List<UserInfo> findByNameAndAge(String name,Integer age);

當然還支持其他的關鍵字查詢。見下表
file
關鍵字方式,僅限於可以在WHERE不使用連接的情況下在子句中使用的屬性

再如果你不喜歡這種關鍵字方式,可以自定義方法名字,你還可以使用@Query方式進行定義查詢方法

	@Query("select name, age from user_info u where u.name = :name")
	List<UserInfo> getUserInfoByName(String name);

如果你要修改或者刪除,只需要增加注解@Modifying,語句如下:

@Modifying
@Query("update user_info set age=:age where name = :name")
Boolean updateAgeById(String name,Integer age);

@Modifying
@Query("delete from user_info where id = :id")
Boolean deleteRecord(Integer id);

是不是感覺很方便,不再用去寫SQL了

七、生命周期的事件機制

Spring Data JDBC 的操作可以作為事件和ApplicationListener的事件相結合
比如,監聽所有插入前的操作,這里我們只演示打印日志:

@Configuration
@Slf4j
public class CommonEventConfiguration {
    @Bean
    public ApplicationListener<BeforeSaveEvent<Object>> loggingSaves() {

        return event -> {
            Object entity = event.getEntity();
            log.info("{} is getting saved.", entity);
        };
    }
}

當然你不想對所有的操作都監聽處理,你可以指定具體某一個表的操作,如下:

@Slf4j
@Repository
public class UserSavedListener extends AbstractRelationalEventListener<UserInfo> {

    @Override
    protected void onAfterSave(AfterSaveEvent<UserInfo> userInfoAfterSaveEvent) {
        log.info("用戶:{},保存成功",userInfoAfterSaveEvent.getEntity());
    }
}

執行測試代碼:

@Test
public void testInsert() {
	UserInfo userInfo =new UserInfo();
	userInfo.setName("王五");
	userInfo.setAge(20);
	userInfo.setSex(1);
	UserInfo result = userInfoRepository.save(userInfo);
	System.out.println(result);
}

執行結果:
file

可用事件有:
file

八、實體回調

Spring Data 基礎設施提供了在調用某些方法之前和之后修改實體的鈎子。也許你已經注意到了,user_info表的創建時間和更新時間我們沒有賦值,數據庫里的兩個時間都是有值的,這就是用實體回調來實現的。

建立一個實體回調類

@Component
public class DefaultingEntityCallback implements BeforeSaveCallback<BaseEntity> {

    @Override
    public BaseEntity onBeforeSave(BaseEntity baseEntity, MutableAggregateChange<BaseEntity> mutableAggregateChange) {
        baseEntity.setCreateTime(LocalDateTime.now());
        baseEntity.setUpdateTime(LocalDateTime.now());
        return baseEntity;
    }
}

另外一種場景,在查詢結果出來后需要將用戶的敏感信息脫敏,則可以使用AfterLoadCallback實體回調

完結


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM