Spring Data学习(一):初识

前言

Spring Data是为了简化数据库的访问,支持关系数据库、非关系数据库、map-reduce框架和基于云的数据服务

添加Spring Data

将SpringData添加进Spring Boot项目中。

配置pom.xml

<!--会下载所有Spring Data Jpa所需的依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

配置数据库相关信息(application.properties)

配置数据库信息

# Mysql属性配置,Spring-boot系统配置
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=123
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

配置自动根据实体类在数据库创建表

# create----每次运行该程序,没有表格会新建表格,表内有数据会清空
# create-drop----每次程序结束的时候会清空表
# update----每次运行程序,没有表格会新建表格,表内有数据不会清空,只会更新
# validate----运行程序会校验数据与数据库的字段类型是否相同,不同会报错
spring.jpa.hibernate.ddl-auto=update
# 运行时数据SQL语句
spring.jpa.show-sql = true

创建User.java

说明:若是不填写各字段在数据库里的列名,Spring Data会自动根据字段名称创建。

package com.jc.springdata.dao;


import javax.persistence.*;

/**
 * Created by Administrator on 2018/7/31.
 */
@Entity  //表示是一个JPA实体类
@Table(name = "SBD_USER") //映射的表名称
public class User {

    @Id // 表示为ID
    @GeneratedValue(strategy = GenerationType.AUTO) //自动生成
    private Long id;

    @Column(length = 25)
    private String name;

    @Column(length = 20) //为设置数据库里的字段名称,Spring Data会自动根据实体类字段名称设置,默认为:birthy_day
    private String birthyDay;

    public User() {
    }

    public User(String name, String birthyDay) {
        this.name = name;
        this.birthyDay = birthyDay;
    }

    public Long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getBirthyDay() {
        return birthyDay;
    }

    public void setBirthyDay(String birthyDay) {
        this.birthyDay = birthyDay;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", birthyDay='" + birthyDay + '\'' +
                '}';
    }
}

ps:添加java实体类时,可以考虑使用lombok(https://www.cnblogs.com/wsygdb/p/9467690.html)

创建查询

下面就是见证Spring Data神奇的时候了,即:您不必编写存储库接口的实现。Spring Data JPA在运行应用程序时动态创建一个实现。
创建一个关于对User表的查询接口IUserRepository.java

import com.jc.springdata.dao.User;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * Created by Administrator on 2018/8/2.<br/>
 * 特别说明:这正是Spring Data JPA如此强大的原因:您不必编写存储库接口的实现。Spring Data JPA在运行应用程序时动态创建一个实现。
 */
@Repository("userRepository")  //表明该类是用来执行与数据库相关的操作(即dao对象),并支持自动处理数据库操作产生的异常
public interface IUserRepository extends CrudRepository<User,Long> { // 参数1:表示数据表对应的实体类,参数2:主键的类型

    /**
     * 根据名称查找用户</>
     * @param name
     * @return
     */
    List<User> findByName(String name);

    /**
     * 根据生日查询对应的用户
     * @param birthyDay
     * @return
     */
    List<User> findByBirthyDay(String birthyDay);

}

测试

1) 创建UserCommandLineRunner.java,实现CommandLineRunner.java接口,用户在SpringBoot启动时运行

package com.jc.springdata.runner;

import com.jc.springdata.dao.User;
import com.jc.springdata.mgr.IUserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * Created by Administrator on 2018/8/3.
 */
@Order(value = 1) //系统启动的优先级
@Component
public class UserCommandLineRunner implements CommandLineRunner{

    private static final Logger LOG = LoggerFactory.getLogger(UserCommandLineRunner.class);

    @Autowired
    private IUserRepository userRepository;

    @Override
    public void run(String... args) throws Exception {
        LOG.info("---- start save ----");
        userRepository.save(new User("Tom","20150101"));
        userRepository.save(new User("Jack","20050101"));
        userRepository.save(new User("SuSan","20000101"));

        LOG.info("---- find all ----");
        Iterable<User> users = userRepository.findAll();
        for (User user: users) {
            LOG.info("user:{}",user);
        }
    }

}

2) 启动Spring Boot

再次启动SpringBoot,查看启动日志,发现系统有创建表的sql、查询等被执行的SQL:

这是系统查询

查看数据库,确实是自动创建了表,可以看到,由于我们未给各个字段设置数据库里的字段名,Spring Data自动根据实体类字段名设置了数据库里的字段名。

遇见问题处理

Failed to read Class-Path attribute from manifest of jar file:/../repository/org/jboss/jandex/2.0.3.Final/jandex-2.0.3.Final.jar

报错是在启动SpringBoot时出现的,直接导致系统不能启动。
具体报错信息

Exception in thread "main" java.lang.IllegalStateException: Failed to read Class-Path attribute from manifest of jar file:/xx/maven/repository/org/jboss/jandex/2.0.3.Final/jandex-2.0.3.Final.jar
	at org.springframework.boot.devtools.restart.ChangeableUrls.getUrlsFromClassPathOfJarManifestIfPossible(ChangeableUrls.java:132)
	at org.springframework.boot.devtools.restart.ChangeableUrls.fromClassLoader(ChangeableUrls.java:98)
	at org.springframework.boot.devtools.restart.DefaultRestartInitializer.getUrls(DefaultRestartInitializer.java:91)
	at org.springframework.boot.devtools.restart.DefaultRestartInitializer.getInitialUrls(DefaultRestartInitializer.java:55)
	at org.springframework.boot.devtools.restart.Restarter.<init>(Restarter.java:142)
	at org.springframework.boot.devtools.restart.Restarter.initialize(Restarter.java:556)
	at org.springframework.boot.devtools.restart.RestartApplicationListener.onApplicationStartingEvent(RestartApplicationListener.java:67)
	at org.springframework.boot.devtools.restart.RestartApplicationListener.onApplicationEvent(RestartApplicationListener.java:45)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127)
	at org.springframework.boot.context.event.EventPublishingRunListener.starting(EventPublishingRunListener.java:68)
	at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:48)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:313)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1255)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1243)
	at com.jc.SpringbootdemoApplication.main(SpringbootdemoApplication.java:11)
Caused by: java.util.zip.ZipException: invalid LOC header (bad signature)
	at java.util.zip.ZipFile.read(Native Method)
	at java.util.zip.ZipFile.access$1400(ZipFile.java:60)
	at java.util.zip.ZipFile$ZipFileInputStream.read(ZipFile.java:717)
	at java.util.zip.ZipFile$ZipFileInflaterInputStream.fill(ZipFile.java:419)
	at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:158)
	at sun.misc.IOUtils.readFully(IOUtils.java:65)
	at java.util.jar.JarFile.getBytes(JarFile.java:425)
	at java.util.jar.JarFile.getManifestFromReference(JarFile.java:193)
	at java.util.jar.JarFile.getManifest(JarFile.java:180)
	at org.springframework.boot.devtools.restart.ChangeableUrls.getUrlsFromManifestClassPathAttribute(ChangeableUrls.java:153)
	at org.springframework.boot.devtools.restart.ChangeableUrls.getUrlsFromClassPathOfJarManifestIfPossible(ChangeableUrls.java:129)
	... 17 more

原因分析

maven本地库中指定的jar文件有问题。

处理方法

stap 1:删除指定目录内的jar文件(/xx/maven/repository/org/jboss/jandex/2.0.3.Final/jandex-2.0.3.Final.jar);
step 2:然后让Maven重新获取一次就行;

参考

官网说明:http://projects.spring.io/spring-data-jpa/
官网入门示例:https://spring.io/guides/gs/accessing-data-jpa/

posted @ 2018-08-17 13:45  我是一个豆笔  阅读(824)  评论(0编辑  收藏  举报