我们要做什么
这篇文章是我借助Spring框架搭建的一个spring-data-jpa的后端demo,可以带条件并分页查询数据库记录,支持事务,希望对你有帮助。 Eclipse的朋友可以使用STS来快速构建你的spring项目,在Eclipse上方工具栏,点击Help-> Eclipse Marketplace, 搜索STS,那个Spring Tool Suite就是。Install之后,重启Eclipse, 你就可以像在IDEA里面一样快速生成一个spring项目啦!
你需要有这些准备
代码及相关配置文件
pom文件
<?xml version="1.0" encoding="UTF-8"?>
< 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 https://maven.apache.org/xsd/maven-4.0.0.xsd" >
< modelVersion> 4.0.0</ modelVersion>
< groupId> org.lzy.example</ groupId>
< artifactId> backend-practice</ artifactId>
< version> 0.0.1-SNAPSHOT</ version>
< name> backend-practice</ name>
< description> Demo project for Spring Boot</ description>
< properties>
< project.build.sourceEncoding> UTF-8</ project.build.sourceEncoding>
< project.reporting.outputEncoding> UTF-8</ project.reporting.outputEncoding>
< java.version> 1.8</ java.version>
</ properties>
< dependencies>
< dependency>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot</ artifactId>
< version> 2.2.12.RELEASE</ version>
</ dependency>
< dependency>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-starter-data-jpa</ artifactId>
< version> 2.2.12.RELEASE</ version>
</ dependency>
< dependency>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-starter-web</ artifactId>
< version> 2.2.12.RELEASE</ version>
</ dependency>
< dependency>
< groupId> com.alibaba</ groupId>
< artifactId> druid</ artifactId>
< version> 1.0.29</ version>
</ dependency>
< dependency>
< groupId> mysql</ groupId>
< artifactId> mysql-connector-java</ artifactId>
< version> 8.0.22</ version>
</ dependency>
< dependency>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-starter-test</ artifactId>
< version> 2.2.12.RELEASE</ version>
< exclusions>
< exclusion>
< groupId> org.junit.vintage</ groupId>
< artifactId> junit-vintage-engine</ artifactId>
</ exclusion>
</ exclusions>
</ dependency>
</ dependencies>
< build>
< plugins>
< plugin>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-maven-plugin</ artifactId>
</ plugin>
</ plugins>
</ build>
</ project>
application.properties文件
Spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
Spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
Spring.datasource.url=jdbc:mysql://[YOUR_DATABASE_URL_HERE]:3306/[YOUR_DATABASE_NAME_HERE]?characterEncoding=utf8
Spring.datasource.username=[YOUR_USERNAME_HRER]
Spring.datasource.password=[YOUR_PASSWORD_HRER]
Spring.jpa.properties.hibernate.show_sql=true
Spring.jpa.properties.hibernate.format_sql=true
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
mysql数据库建表
Customer表
Field Type PrimaryKey auto_increment id int 主键 自增 firstName varchar lastName varchar
TrainInfo表
Field Type PrimaryKey auto_increment id int 主键 自增 trainNumber varchar trainLeaveTime date trainStartStation varchar
TicketRecord表
Field Type PrimaryKey auto_increment id int 主键 自增 passengerName varchar trainNumber varchar
整体项目结构
各个代码文件
Customer.java
package org. lzy. example. entity;
import java. io. Serializable;
import javax. persistence. *;
@Entity
public class Customer implements Serializable {
@Id
@GeneratedValue ( strategy= GenerationType. IDENTITY)
private Long id;
private String firstName;
private String lastName;
protected Customer ( ) { }
public Customer ( String firstName, String lastName) {
this . firstName = firstName;
this . lastName = lastName;
}
public Long getId ( ) {
return id;
}
public void setId ( Long id) {
this . id = id;
}
public String getFirstName ( ) {
return firstName;
}
public void setFirstName ( String firstName) {
this . firstName = firstName;
}
public String getLastName ( ) {
return lastName;
}
public void setLastName ( String lastName) {
this . lastName = lastName;
}
@Override
public String toString ( ) {
return "Customer [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + "]" ;
}
}
TicketRecord.java
package org. lzy. example. entity;
import javax. persistence. Entity;
import javax. persistence. GeneratedValue;
import javax. persistence. GenerationType;
import javax. persistence. Id;
@Entity
public class TicketRecord {
@Id
@GeneratedValue ( strategy= GenerationType. IDENTITY)
private Integer id;
private String passengerName;
private String trainNumber;
public Integer getId ( ) {
return id;
}
public void setId ( Integer id) {
this . id = id;
}
public String getPassengerName ( ) {
return passengerName;
}
public void setPassengerName ( String passengerName) {
this . passengerName = passengerName;
}
public String getTrainNumber ( ) {
return trainNumber;
}
public void setTrainNumber ( String trainNumber) {
this . trainNumber = trainNumber;
}
public TicketRecord ( String passengerName, String trainNumber) {
super ( ) ;
this . passengerName = passengerName;
this . trainNumber = trainNumber;
}
}
TrainInfo.java
package org. lzy. example. entity;
import java. io. Serializable;
import java. util. Date;
import javax. persistence. Entity;
import javax. persistence. GeneratedValue;
import javax. persistence. GenerationType;
import javax. persistence. Id;
import javax. persistence. Temporal;
import javax. persistence. TemporalType;
@Entity
public class TrainInfo implements Serializable {
@Id
@GeneratedValue ( strategy= GenerationType. IDENTITY)
private Integer id;
@Temporal ( TemporalType. TIMESTAMP)
private Date trainLeaveTime;
private String trainStartStation;
private String trainNumber;
public Integer getId ( ) {
return id;
}
public void setId ( Integer id) {
this . id = id;
}
public Date getTrainLeaveTime ( ) {
return trainLeaveTime;
}
public void setTrainLeaveTime ( Date trainLeaveTime) {
this . trainLeaveTime = trainLeaveTime;
}
public String getTrainStartStation ( ) {
return trainStartStation;
}
public void setTrainStartStation ( String trainStartStation) {
this . trainStartStation = trainStartStation;
}
public String getTrainNumber ( ) {
return trainNumber;
}
public void setTrainNumber ( String trainNumber) {
this . trainNumber = trainNumber;
}
}
CustomerRepository.java
package org. lzy. example. repository;
import org. lzy. example. entity. Customer;
import org. springframework. data. repository. CrudRepository;
import java. util. List;
public interface CustomerRepository extends CrudRepository < Customer, Long> {
List< Customer> findByLastName ( String lastName) ;
Customer findById ( long id) ;
}
TicketRecordRepository.java
package org. lzy. example. repository;
import org. lzy. example. entity. TicketRecord;
import org. springframework. data. repository. CrudRepository;
public interface TicketRecordRepository extends CrudRepository < TicketRecord, Long> {
}
TrainInfoRepository.java
package org. lzy. example. repository;
import java. util. List;
import org. lzy. example. entity. TrainInfo;
import org. springframework. data. domain. Pageable;
import org. springframework. data. repository. PagingAndSortingRepository;
import org. springframework. data. repository. query. Param;
public interface TrainInfoRepository extends PagingAndSortingRepository < TrainInfo, Long> {
List< TrainInfo> findByTrainNumber ( String trainNumber) ;
List< TrainInfo> findByTrainStartStation ( String station, Pageable pageable) ;
}
NoThisTrainException.java
package org. lzy. example. exception;
public class NoThisTrainException extends RuntimeException {
public NoThisTrainException ( String message) {
super ( message) ;
}
}
CustomerServiceController.java
package org. lzy. example. controller;
import java. util. HashMap;
import java. util. List;
import java. util. Map;
import org. lzy. example. entity. Customer;
import org. lzy. example. repository. CustomerRepository;
import org. springframework. beans. factory. annotation. Autowired;
import org. springframework. web. bind. annotation. RequestBody;
import org. springframework. web. bind. annotation. RequestMapping;
import org. springframework. web. bind. annotation. RestController;
@RestController
public class CustomerServiceController {
@Autowired
private CustomerRepository customerRepository;
@RequestMapping ( "/customer/add" )
public Map< String, Object> add ( @RequestBody ( required= false ) Customer customer) {
Map< String, Object> resultMap = new HashMap < String, Object> ( ) ;
customerRepository. save ( customer) ;
resultMap. put ( "msg" , "ok" ) ;
return resultMap;
}
@RequestMapping ( "/customer/query_all" )
public Map< String, Object> query_all ( ) {
Map< String, Object> resultMap = new HashMap < String, Object> ( ) ;
List< Customer> allCustomers = ( List< Customer> ) customerRepository. findAll ( ) ;
resultMap. put ( "msg" , "ok" ) ;
resultMap. put ( "data" , allCustomers) ;
resultMap. put ( "total" , allCustomers. size ( ) ) ;
return resultMap;
}
}
TrainServiceController.java
package org. lzy. example. controller;
import java. util. ArrayList;
import java. util. HashMap;
import java. util. List;
import java. util. Map;
import org. lzy. example. entity. TicketRecord;
import org. lzy. example. entity. TrainInfo;
import org. lzy. example. exception. NoThisTrainException;
import org. lzy. example. repository. CustomerRepository;
import org. lzy. example. repository. TicketRecordRepository;
import org. lzy. example. repository. TrainInfoRepository;
import org. springframework. beans. factory. annotation. Autowired;
import org. springframework. data. domain. Page;
import org. springframework. data. domain. PageRequest;
import org. springframework. data. domain. Pageable;
import org. springframework. data. domain. Sort;
import org. springframework. data. domain. Sort. Direction;
import org. springframework. data. domain. Sort. Order;
import org. springframework. transaction. annotation. Transactional;
import org. springframework. web. bind. annotation. PathVariable;
import org. springframework. web. bind. annotation. RequestMapping;
import org. springframework. web. bind. annotation. RestController;
@RestController
public class TrainServiceController {
@Autowired
private CustomerRepository customerRepostitory;
@Autowired
private TrainInfoRepository trainInfoRepository;
@Autowired
private TicketRecordRepository ticketRecordRepository;
@RequestMapping ( "/trainService/query/station/{stationName}/{page}/{size}" )
public Map< String, Object> queryStation ( @PathVariable ( "stationName" ) String station,
@PathVariable ( "page" ) Integer page,
@PathVariable ( "size" ) Integer size) {
Map< String, Object> returnMap = new HashMap < String, Object> ( ) ;
PageRequest pageRequest = PageRequest. of ( page- 1 , size, Direction. DESC, "trainLeaveTime" , "trainNumber" ) ;
List< TrainInfo> t = trainInfoRepository. findByTrainStartStation ( station, pageRequest) ;
returnMap. put ( "data" , t) ;
returnMap. put ( "total" , t. size ( ) ) ;
returnMap. put ( "page" , page) ;
returnMap. put ( "size" , size) ;
return returnMap;
}
@Transactional
@RequestMapping ( "/trainService/order/submit/{train_no}/{p_name}" )
public Map< String, Object> submitTrainTicketOrder ( @PathVariable ( "train_no" ) String trainNumber,
@PathVariable ( "p_name" ) String passengerName) {
Map< String, Object> returnMap = new HashMap < String, Object> ( ) ;
TicketRecord tr = new TicketRecord ( passengerName, trainNumber) ;
ticketRecordRepository. save ( tr) ;
String resultStatus = "购票失败" ;
List< TrainInfo> ti = trainInfoRepository. findByTrainNumber ( trainNumber) ;
if ( ti. size ( ) != 0 )
resultStatus = "购票成功" ;
else
throw new NoThisTrainException ( "查询不到该趟列车!" ) ;
returnMap. put ( "result" , resultStatus) ;
return returnMap;
}
}
BackendPracticeApplication.java
package org. lzy. example;
import org. springframework. boot. SpringApplication;
import org. springframework. boot. autoconfigure. SpringBootApplication;
@SpringBootApplication
public class BackendPracticeApplication {
public static void main ( String[ ] args) {
SpringApplication. run ( BackendPracticeApplication. class , args) ;
}
}
记录我遇到的坑
entity的那些类一定不要忘记生成setter/gettter方法,否则在controller里的getContent()只会记录元素个数,不会显示出内容!! 数据库表最好把主键设置为自增,然后GenerationType用IDENTITY。 之前我自己而外在entity的类前加上@Table(name=“Customer”), 但是这样做它有时还是会显示Table ‘xxx.Customer’ does not exist, 所以我干脆不要这个注释了,但是application.properties里面别忘了
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
TrainServiceController.java这个类里的submitTrainTicketOrder方法,如果不加@Transactional注解,好像是不能支持事务的。大家可以自己测试一下。 下面这行代码产生的 ti 不能使用 == null 来判断是否查询到记录(即使查不到它也不为null), 应该用 ti.size() != 0来判断,血的教训。。。
List< TrainInfo> ti = trainInfoRepository. findByTrainNumber ( trainNumber) ;
【补充】如果你突然遇到 No default constructor for entity 这个报错,看看实体类里有没有空构造器,没有的话创建一个 protected Xxxx() {} 然后再运行试试?
谢谢大家的捧场,如果有任何问题可以留言,我会时不时回来看的。