目标
访问MySQL数据库
要点
现在访问数据库的编程已经很容易了,但是这次踩的坑不少。原因还是对内在机制了解太少,先把坑记录下来,以后学习Spring Data好好补上。
编程要点:创建@Entity model(对应数据库里Table的定义)以及基于这个model的CRUD repository。
代码
0. 数据库
0.安装MySQL数据库可以参见本人的简书。然后创建DB和Table,本文例子里的DB是mydb1, 创建Table的语句为:
create table teacher (id int(3) auto_increment not null primary key, name char(10) not null, address varchar(50) default '深圳', year date);
1. 创建资源文件,定义数据库连接
资源文件为:src/main/resources/application.properties. 本例中在这个文件里定义数据库连接:
spring.jpa.hibernate.ddl-auto=none
spring.datasource.url=jdbc:mysql://localhost:3306/mydb1?serverTimezone=GMT&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
2. POM Dependency
2.1 增加两个dependency:data-jpa和mysql-connector-java
Group Id: org.springframework.boot
Artifact Id: spring-boot-starter-data-jpa
Version: 2.0.0.RELEASE
Group Id: mysql
Artifact Id: mysql-connector-java
Version: 8.0.12
2.2 Spring Boot Maven plugin
在POM.xml的最后一行</project>之前插入下面这段:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
3. Java Code
3.1 创建@Entity model
src/main/java/hello/teacher.java
package hello;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity // This tells Hibernate to make a table out of this class
public class teacher {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
private String name;
private String address;
private java.sql.Date year;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public java.sql.Date getYear() {
return year;
}
public void setYear(java.sql.Date year) {
this.year = year;
}
}
3.2 创建repository
src/main/java/hello/TeacherRepository.java
package hello;
import org.springframework.data.repository.CrudRepository;
import hello.teacher;
import hello.TeacherRepository;
// This will be AUTO IMPLEMENTED by Spring into a Bean called userRepository
// CRUD refers Create, Read, Update, Delete
//@Repository
public interface TeacherRepository extends CrudRepository<teacher, Integer> {
}
3.3 创建Controller和Application
src/main/java/hello/example.java
package hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import hello.teacher;
import hello.TeacherRepository;
@Controller // This means that this class is a Controller
@RequestMapping(path="/demo") // This means URL's start with /demo (after Application path)
@EnableAutoConfiguration
//@SpringBootApplication(scanBasePackages={"com.exmample.springdemo-125"})
public class example {
@Autowired // This means to get the bean called teacherRepository
// Which is auto-generated by Spring, we will use it to handle the data
private TeacherRepository teacherRepository;
@GetMapping(path="/add") // Map ONLY GET Requests
public @ResponseBody String addNewTeacher (@RequestParam String name
, @RequestParam String address, @RequestParam java.sql.Date year) {
// @ResponseBody means the returned String is the response, not a view name
// @RequestParam means it is a parameter from the GET or POST request
teacher n = new teacher();
n.setName(name);
n.setAddress(address);
n.setYear(year);
teacherRepository.save(n);
return "Saved";
}
@GetMapping(path="/all")
public @ResponseBody Iterable<teacher> getAllTeachers() {
// This returns a JSON or XML with the teachers
Iterable<teacher> t = teacherRepository.findAll();
return teacherRepository.findAll();
}
public static void main(String args[]) throws Exception{
SpringApplication.run(example.class, args);
}
}
4. 测试URL
http://localhost:8080/demo/all
说明
1. Table名和@Entity类名的大小写问题
在官网的例子里,Table名的首字母是大写的。但是Windows平台上的MySQL表名是不区分大小写的,存放在硬盘里的是小写。大小写是由配置选项lower_case_table_names决定的,安装后就不能再修改了。所以我用的Table名全都是小写:teacher.
注意:@Entity类名需要和Table名完全一致。
2. application.properties中的spring.jpa.hibernate.ddl-auto的值
spring.jpa.hibernate.ddl-auto可以是 none, update, create, create-drop
如果这个值是create,每次都会创建数据库。我调试过程中,一开始往Table里插入了一些记录,但是每次查询都是空,后来进MySQL看,Table是空的,应该就是把spring.jpa.hibernate.ddl-auto设成create引起的,后来改成none就好了。
我曾经也怀疑过是否和Table名大小写有关,但是因为日志里没有找不到Table的错误信息,所以应该和Table名无关。
3.application.properties中的spring.datasource.url
spring.datasource.url包含MySQL的IP地址、端口号、DB名和一些选项。因为有date类型的字段,所以如果不指定serverTimezone,好像会报错。
4. POM dependency中mysql-connector-java的版本号
猜了几个都不行,最后找到Maven Repository的网址Chapter 2 Connector/J Versions, and the MySQL and Java Versions They Support,一下子就查到了。以后还是别乱猜。
5. POM 中Spring Boot Maven plugin
其作用参见官网 | Accessing data with MySQL
6. date数据类型
在Access MySQL的Java code里,date数据类型应该 java.sql.Date
7. Bean找不到
这是我折腾最久的一个坑,网上找了好多文章都没有解决问题。最后一行一行读官网 | Accessing data with MySQL,发现我用的Eclipse下默认的default package,而官网的例子用的是hello。所以又建了一个hello package,把java文件都移到hello里就OK了。
参考
1.官网 | Accessing data with MySQL
2. Chapter 2 Connector/J Versions, and the MySQL and Java Versions They Support
3. mysql-connector-java与mysql版本的对应
5. 从零开始学JAVA(09)-使用SpringMVC4 + Mybatis + MySql 例子(注解方式开发)
6. 数据库的时间类型 与 spring mvc 中 entity 属性类型的对应关系
7. JDBC中The server time zone value '???ú±ê×??±??' is ............. 的错误
网友评论