SpringBoot 集成 JPA

一、简介:
Java Persistence API:用于对象持久化的 API。Java EE 5.0 平台标准的 ORM 规范,使得应用程序以统一的方式访问持久层。JPA 是 hibernate 的一个抽象,将Java应用与数据库解耦,开发者不用关心Sql的编写,和底层数据库的种类。

二、示例:

  1. 引入相应依赖

    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    
  2. 数据源相关配置

    spring.datasource.url = jdbc:mysql://106.13.181.6:3306/FA?useUnicode=true&characterEncoding=UTF-8
    spring.datasource.username = root
    spring.datasource.password= Wanghaiyun@12345
    spring.datasource.driver-class-name = com.mysql.jdbc.Driver
    
    spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
    spring.jpa.show-sql = true
    
  3. Controller层编写

    package com.study.demo.controller;
    
    import com.google.gson.Gson;
    import com.study.demo.entity.UserInfo;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.util.CollectionUtils;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseBody;
    import com.study.demo.service.UserInfoService;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.List;
    import java.util.UUID;
    
    @Controller
    @RequestMapping("/demo")
    public class UserInfoController {
    
    	private static Logger LOGGER = LoggerFactory.getLogger(UserInfoController.class);
    
    	@Autowired
    	private UserInfoService userInfoService;
    
    	private static Gson gson = new Gson();
    
    	@ResponseBody
    	@RequestMapping("/queryUser_{userId}.htm")
    	public String queryUserInfoByUserId (@PathVariable String userId) {
    		return gson.toJson(userInfoService.selectByPrimaryKey(userId));
    	}
    
    	@ResponseBody
    	@RequestMapping(value = "/saveUser.htm", method = RequestMethod.POST)
    	public String saveUserInfo (UserInfo userInfo) {
    		UUID uuid = UUID.randomUUID();
    		userInfo.setId(uuid.toString());
    		try {
    			userInfoService.persistUserInfo(userInfo);
    		} catch (Exception e){
    			LOGGER.error("UserInfoController.saveUserInfo Error. userInfo:{}, e:{}", gson.toJson(userInfo), e);
    			return "Error";
    		}
    		return "OK";
    	}
    
    	@ResponseBody
    	@RequestMapping(value = "/queryAllByCreateTime.htm", method = RequestMethod.POST)
    	public String queryAllByCreateTime (String createTime) {
    		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    		try {
    			Date date = format.parse(createTime);
    			List<UserInfo> infoList = userInfoService.queryAllByCreateTimeAfter(date);
    			if (!CollectionUtils.isEmpty(infoList)) {
    				return gson.toJson(infoList);
    			}
    		} catch (Exception e) {
    			LOGGER.error("UserInfoController.queryAllByCreateTime Error. createTime:{}, e:{}", createTime, e);
    		}
    		return null;
    	}
    }
    
    
  4. Dao层编写

    package com.study.demo.dao;
    
    import com.study.demo.entity.UserInfo;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.stereotype.Repository;
    import java.util.Date;
    import java.util.List;
    
    @Repository
    public interface UserInfoDao extends JpaRepository<UserInfo, String>{
    
    	UserInfo queryUserInfoById(String id);
    
    	List<UserInfo> queryAllByCreateTimeAfter(Date createTime);
    
    }
    
    
  5. Entity层编写

    package com.study.demo.entity;
    
    import lombok.Data;
    import org.springframework.format.annotation.DateTimeFormat;
    import java.io.Serializable;
    import java.util.Date;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.Table;
    
    @Data
    @Entity
    @Table(name = "USER_INFO")
    public class UserInfo implements Serializable {
    
        private static final long serialVersionUID = 860529229491709995L;
    
        @Id
    	@Column(name = "ID")
    	private String id;
    
    	@Column(name = "NAME")
    	private String name;
    
    	@Column(name = "SEX")
    	private String sex;
    
    	@Column(name = "BIRTHDAY")
    	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    	private Date birthday;
    
    	@Column(name = "AGE")
    	private Integer age;
    
    	@Column(name = "ADDRESS")
    	private String address;
    
    	@Column(name = "CREATE_TIME")
    	private Date createTime = new Date();
    
    }
    
    

三、用法说明
简单的CURD在JpaRepository已经提供了,对于复杂的查询可以通过关键字拼接方法名的方式来实现。
例如上述例子中,查询所有在某时间之后创建的用户信息,通过After关键字,表示在xx日期之后,入参为Date格式,CreateTime为Entity对象的属性,通过驼峰方式拼接。
相关的关键字还有:(摘自:https://blog.csdn.net/lionel_zsj/article/details/98937678)

关键字 简单示例 JPQL片段示例
AND findByLastNameAndFirstName WHERE Entity.lastName = ?1 AND Entity.firstName = ?2
IsNull findByAddressIsNull WHERE Entity.address is NULL
IsNotNull readByAddressIsNotNull WHERE Entity.address NOT NULL
NotNull readByAddressNotNull WHERE Entity.address NOT NULL
OR readByLastNameOrFirstName WHERE Entity.lastName = ?1 OR Entity.firstName = ?2
Between getByStartDateBetween WHERE Entity.startDate BETWEEN ?1 AND ?2
LessThan findByAgeLessThan WHERE Entity.age < ?1
GreaterThan readByAgeGreaterThan WHERE Entity.age > ?1
After只作用在时间 findByStartDateAfter WHERE Entity.startDate > ?1
Before只作用在时间 findByStartDateBefore WHERE Entity.startDate < ?1
LessThanEqual findByAgeLessThenEqual WHERE Entity.age <= ?1
GreaterThanEqual readByAgeGreaterThenEqual WHERE Entity.age >= ?1
Is findByLastNameIs WHERE Entity.lastName = ?1
Equal getByFirstNameEqual WHERE Entity.firstName = ?1
Like findByNameLike WHERE Entity.name LIKE ? 不包括’%'符号
Not Like findByNameNotLike WHERE Entity.name not like ?1 不包括’%'符号
StartingWith readByNameStartingWith WHERE Entity.name like ‘?1%’条件以’%'符号结尾
EndingWith readByName EndingWith WHERE Entity.name like ‘%?1’条件以’%'符号开头
Containing getByNameContaining WHERE Entity.name like ‘%?1%’ 包含’%'符号
OrderBy findByAgeOrderByAddressDesc WHERE Entity.age = ? Order By Entity.address DESC
Not readByAgeNot WHERE Entity.age <> ?1 不等于
In findByNameIn(Collection name) WHERE Entity.name IN (?1 ,?2, ?3)
NotIn getByNameNotIn(Collection name) WHERE Entity.name NOT IN (?1 ,?2, ?3)
True readByFloagTrue() WHERE Entity.floag = true
False readByFloagFalse() WHERE Entity.floag = false
IgnoreCase findByNameIgnoreCase WHERE UPPER(Entity.Name) = UPPER(?1)

一些复杂查询可以使Dao层接口继承JpaSpecificationExecutor接口,使用Specification对象和Pageable对象分页查询。也可以使用ExampleMatcher对象。如:

package com.study.demo.dao;

import com.study.demo.entity.UserInfo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
import java.util.Date;
import java.util.List;

@Repository
public interface UserInfoDao extends JpaRepository<UserInfo, String>, JpaSpecificationExecutor<UserInfo> {

	UserInfo queryUserInfoById(String id);

	List<UserInfo> queryAllByCreateTimeAfter(Date createTime);

}

Service层实现方法:

package com.study.demo.service.Impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import com.study.demo.dao.UserInfoDao;
import com.study.demo.entity.UserInfo;
import com.study.demo.service.UserInfoService;
import javax.persistence.criteria.Predicate;
import java.util.Date;
import java.util.List;

@Service
public class UserInfoServiceImpl implements UserInfoService {
	
	@Autowired
	private UserInfoDao userInfoDao;

	@Override
	public UserInfo selectByPrimaryKey(String id) {
		return userInfoDao.queryUserInfoById(id);
	}

	@Override
	public void persistUserInfo(UserInfo userInfo) {
		userInfoDao.save(userInfo);
	}

    @Override
    public List<UserInfo> queryAllByCreateTimeAfter(Date createTime) {
        return userInfoDao.queryAllByCreateTimeAfter(createTime);
    }

    @Override
    public List<UserInfo> queryAllBySexAndCreateTime(String sex, Date createTime, int page, int size){
        Specification<UserInfo> specification = (Specification<UserInfo>) (root, query, builder) -> {
            Predicate first = builder.equal(root.get("sex"), sex);
            Predicate second = builder.greaterThan(root.get("createTime"), createTime);
            return builder.and(first, second);
        };
        Pageable pageable = PageRequest.of(page-1, size);
        return userInfoDao.findAll(specification, pageable).getContent();
    }
}

查询SQL如下:

Hibernate: select userinfo0_.ID as ID1_0_, userinfo0_.ADDRESS as ADDRESS2_0_, userinfo0_.AGE 
as AGE3_0_, userinfo0_.BIRTHDAY as BIRTHDAY4_0_, userinfo0_.CREATE_TIME as CREATE_T5_0_, 
userinfo0_.NAME as NAME6_0_, userinfo0_.SEX as SEX7_0_ from USER_INFO userinfo0_ where 
userinfo0_.SEX=? and userinfo0_.CREATE_TIME>? limit ?, ?

四、问题总结
1、java.sql.SQLSyntaxErrorException: Table ‘FA.user_info’ doesn’t exist

参考:https://blog.csdn.net/jiangyu1013/article/details/80395579

原因:由于mysql区分表名大小写导致,一种方案是配置数据库,一种是配置项目
解决方案一:
添加配置:

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

解决方案二:
原因:
MySQL对lower_case_table_names使用区分大小写的表名比较设置 (可能值为’0’)。但是,FishEye在表名 FE-4276中不一致-数据库表OPEN的大小写不一致。您可以使用以下查询确认设置:

show variables like ‘lower_case_table_names’;
解决:
在MySQL中设置 lower_case_table_names的值为’0’
重新启动MySQL和FishEye / Crucible。

发布了40 篇原创文章 · 获赞 31 · 访问量 62万+

猜你喜欢

转载自blog.csdn.net/weixin_38422258/article/details/104165452