Springboot集成mysql+jpa实现增删改查示例

 引用的gradle依赖

implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("mysql:mysql-connector-java")

 application.yml配置文件

spring:
  datasource:
    hikari:
      # 最大连接数,默认值10.
      maximum-pool-size: 100
      # 最小空闲连接,默认值10.
      minimum-idle: 10
      # 连接超时时间(毫秒),默认值30秒.
      connection-timeout: 60000
      #空闲连接超时时间,默认值600000(10分钟),只有空闲连接数大于最大连接数且空闲时间超过该值,才会被释放
      #如果大于等于 max-lifetime 且 max-lifetime>0,则会被重置为0.
      idle-timeout: 600000
      auto-commit: true
      # 连接超时时间(毫秒),默认值30秒.
      max-lifetime: 3000000
      #连接测试查询
      connection-test-query: select 1
    tomcat:
      initial-size: 10
      max-active: 100
      max-age: 300000
      max-idle: 100
      min-idle: 10
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/base?serverTimezone=Asia/Shanghai&characterEncoding=utf-8&useSSL=false&parseTime=true
    username: root
    password: root
    
  jpa:
    database: MYSQL
    properties:
      hibernate:
        jdbc:
          batch_size: 500
          batch_versioned_data: true
        order_inserts: true
        order_updates: true
      format_sql: true
      dialect: org.hibernate.dialect.MySQL55Dialect
    show-sql: false
    hibernate:
      ddl-auto: update
      naming:
        implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
        physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
    generate-ddl: true
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect

下面以用户管理为例,实现用户信息的增删改查,JacksonUtil是序列化和反序列化工具,可根据自己的修改,未用到的可删除。

@Entity定义对象将会成为被JPA管理的实体,将映射到指定的数据库表。

@Table指定数据库的表名。

@Id定义属性为数据库的主键,一个实体里面必须有一个。

@GeneratedValue(strategy = GenerationType.IDENTITY ):数据库自增长。

@Column定义该属性对应数据库中的列名。

@Enumerated很好用,直接映射enum枚举类型的字段。

@Convert属性转换器用于数据库属性类型与java存储的类型做转换,其方便之处在于存储与读取的时候能自动转换,可以自定义转换规则。

package com.hmbase.user.pojo

import com.hmbase.jackson.JacksonUtil
import org.hibernate.annotations.Where
import java.math.BigDecimal
import javax.persistence.*

@Entity
@Table(name = "us_user", uniqueConstraints = [UniqueConstraint(name = "unique_account", columnNames = ["account"])])
@Where(clause = "deleted=0")
class UserEntity {
    /**
     * 登录账号
     */
    var account: String = ""

    /**
     * 姓名
     */
    var userName: String = ""

    /**
     * 密码
     */
    var password: String = ""

    /**
     * 收入
     */
    @Column(columnDefinition = "decimal(11,2)")
    var income: BigDecimal? = null

    /**
     * 职业
     */
    @Enumerated(EnumType.STRING)
    var workType: WorkType? = WorkType.OTHER

    /**
     * 学校
     */
    @Column(columnDefinition = "json")
    @Convert(converter = SchoolConverter::class)
    var school: School? = null

    fun toUserDto(): UserDto {
        return UserDto().also {
            it.id = this.id
            it.account = this.account
            it.userName = this.userName
            it.password = this.password
            it.income = this.income
            it.workType = this.workType
            it.school = this.school
        }
    }
}

class School {
    var schoolName: String = ""
    var schoolAddress: String = ""
}

/**
 * 用于数据库属性类型与java存储的类型做转换,例如枚举类型,在存储到数据库时或者在数据库取出来时,不用手动转换。必须实现接口AttributeConverter<X,Y>
 * convertToDatabaseColumn(X attribute)用于把输入的类型转成数据库存储的类型
 * convertToEntityAttribute (Y dbData) 用于把数据库搜出来的类型转成实体中想要的类型
 */
@Converter
class SchoolConverter : AttributeConverter<School, String> {
    override fun convertToDatabaseColumn(attribute: School?): String? {
        if (attribute == null) return null
        return JacksonUtil.toJson(attribute)
    }

    override fun convertToEntityAttribute(dbData: String?): School? {
        if (dbData == null) {
            return null
        }
        return JacksonUtil.toBean(dbData, School::class.java)
    }
}

enum class WorkType(val desc: String) {
    TEACHER("老师"), STUDENT("学生"), OTHER("其他")
}
package com.hmbase.tools.pojo

import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
import org.hibernate.annotations.Where
import java.io.Serializable
import java.util.*
import javax.persistence.*

@MappedSuperclass
@JsonIgnoreProperties("createDate", "updateDate", "deleted")
@Where(clause = "DELETED <> 1")
abstract class BaseUIDEntity : Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY )
    var id: Long? = null

    @Temporal(value = TemporalType.TIMESTAMP)
    var createDate: Date? = Calendar.getInstance().time

    @Temporal(value = TemporalType.TIMESTAMP)
    @JsonIgnore
    var updateDate: Date? = null

    @Column(name = "deleted")
    @JsonIgnore
    var deleted: Boolean? = false

    @PreUpdate
    fun preUpdate() {
        updateDate = Date()
    }

    @PrePersist
    fun prePersist() {
        createDate = Date()
        updateDate = Date()
    }
}
package com.hmbase.user.pojo

import java.math.BigDecimal
import javax.validation.constraints.Size

class UserDto {
    /**
     * 用户唯一标识
     */
    var id: Long? = null

    /**
     * 登录账号
     */
    @Size(min = 10, max = 14)
    var account: String = ""

    /**
     * 姓名
     */
    var userName: String = ""

    /**
     * 密码
     */
    var password: String = ""

    /**
     * token
     */
    var token: String? = null

    /**
     * 收入
     */
    var income: BigDecimal? = null

    /**
     * 职业
     */
    var workType: WorkType? = WorkType.OTHER

    var school: School? = null

    fun toUserEntity(): UserEntity {
        return UserEntity().also {
            it.account = this.account
            it.userName = this.userName
            it.password = this.password
            it.income = this.income
            it.workType = this.workType
            it.school = this.school
        }
    }
}
UserRepository:可以根据JPA语法规则自定义的查询方法,也可以自定义sql查询; 
@Query注解来将自定义sql语句绑定到自定义方法上,其中nativeQuery = true代表使用原始sql语句; 
针对修改、删除操作,务必添加@Transactional和@Modifying注解。
package com.hmbase.user.repository

import com.hmbase.user.pojo.UserEntity
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.JpaSpecificationExecutor
import org.springframework.data.jpa.repository.Modifying
import org.springframework.data.jpa.repository.Query
import org.springframework.stereotype.Repository
import javax.transaction.Transactional

@Repository
interface UserRepository : JpaRepository<UserEntity, Long>, JpaSpecificationExecutor<UserEntity> {

    // 按照JPA语法规则自定义的查询方法
    fun findAllByAccountIn(list: List<String>): List<UserEntity>

    // 按照JPA语法规则自定义的查询方法
    fun findAllByAccount(account: String): List<UserEntity>

    // 自定义的查询方法
    @Query(
        "SELECT * FROM us_user WHERE account=?1 ", nativeQuery = true
    )
    @Transactional
    @Modifying
    fun deleteAllByAccount(account: String)
}
UserController:使用了swagger2接口文档的注解,可自行添加或删除。
package com.hmbase.user

import com.hmbase.common.page.PageDto
import com.hmbase.common.page.PagedData
import com.hmbase.tools.formatToDate
import com.hmbase.tools.pojo.Response
import com.hmbase.user.pojo.UserDto
import io.swagger.annotations.Api
import io.swagger.annotations.ApiOperation
import io.swagger.annotations.ApiParam
import org.springframework.web.bind.annotation.*
import java.util.*
import javax.annotation.Resource

@RestController
@RequestMapping("/user")
@Api(description = "用户管理")
class UserController {
    @Resource
    private lateinit var userService: UserService

    @PostMapping("/add")
    @ApiOperation("用户新增")
    fun add(
        @ApiParam("用户信息") @RequestBody userDto: UserDto
    ): Response<Boolean> {
        return Response(userService.add(userDto))
    }

    @DeleteMapping("/delete/{account}")
    @ApiOperation("根据用户账号删除用户")
    fun delete(
        @ApiParam("用户登录账号", example = "zhangsan") @PathVariable account: String
    ): Response<Boolean> {
        return Response(userService.delete(account))
    }

    @PostMapping("/modify/{account}")
    @ApiOperation("根据用户账号修改用户信息")
    fun modify(
        @ApiParam("用户信息") @RequestBody userDto: UserDto
    ): Response<Boolean> {
        return Response(userService.modify(userDto))
    }

    @GetMapping("/find")
    @ApiOperation("用户条件查询")
    fun find(
        @ApiParam("用户登录账号", example = "zhangsan") @RequestParam(required = false) account: String?,
        @ApiParam("用户名称", example = "张三") @RequestParam(required = false) userName: String?,
        @ApiParam("职业,多个用,分割", example = "TEACHER,STUDENT") @RequestParam(required = false) workType: String?,
        @ApiParam("开始时间", example = "2022-11-02 08:30:00") @RequestParam(required = false) startDate: String?,
        @ApiParam("结束时间", example = "2022-11-03 08:30:00") @RequestParam(required = false) endDate: String?,
    ): Response<List<UserDto>> {
        val startTime: Date? = if (!startDate.isNullOrEmpty()) startDate.formatToDate() else null
        val endTime: Date? = if (!endDate.isNullOrEmpty()) endDate.formatToDate() else null
        return Response(userService.find(account, userName, workType, startTime, endTime))
    }

    @GetMapping("page/users")
    @ApiOperation("分页查询用户数据")
    fun findByPage(
        pageDto: PageDto,
    ): Response<PagedData<List<UserDto>>> {
        val pagedData = userService.findByPage(pageDto)
        return Response(pagedData)
    }
}
UserService
package com.hmbase.user

import com.hmbase.common.page.PageDto
import com.hmbase.common.page.PagedData
import com.hmbase.tools.exception.BadRequestException
import com.hmbase.user.pojo.UserDto
import com.hmbase.user.pojo.UserEntity
import com.hmbase.user.pojo.WorkType
import com.hmbase.user.repository.UserRepository
import org.springframework.data.jpa.domain.Specification
import org.springframework.stereotype.Service
import java.util.*
import javax.annotation.Resource
import javax.persistence.criteria.CriteriaBuilder
import javax.persistence.criteria.CriteriaQuery
import javax.persistence.criteria.Root

@Service
class UserService {
    @Resource
    private lateinit var userRepository: UserRepository


    fun add(userDto: UserDto): Boolean {
        if (userDto.account.isEmpty()) {
            throw BadRequestException("登录账号不能正确,请核实!")
        }
        if (userDto.password.isEmpty()) {
            throw BadRequestException("密码不能正确,请核实!")
        }
        val entity = userRepository.findAllByAccount(userDto.account)
        if (entity.isNotEmpty()) {
            throw BadRequestException("登录账户已存在,请核实!")
        }

        userRepository.save(userDto.toUserEntity())
        return true
    }

    fun delete(account: String): Boolean {
        val entity = userRepository.findAllByAccount(account)
        if (entity.isEmpty()) {
            throw BadRequestException("登录账户不存在,请核实!")
        }

        userRepository.deleteAllByAccount(account)
        return true
    }

    fun modify(userDto: UserDto): Boolean {
        if (userDto.account.isEmpty()) {
            throw BadRequestException("登录账号不能正确,请核实!")
        }
        val list = userRepository.findAllByAccount(userDto.account)
        if (list.isEmpty()) {
            throw BadRequestException("登录户不存在,请核实!")
        }
        val entity = list.first()
        entity.userName = userDto.userName
        entity.password = userDto.password

        userRepository.save(entity)
        return true
    }

    fun find(account: String?, userName: String?, workType: String?, startTime: Date?, endTime: Date?): List<UserDto> {
        val specification =
            Specification { root: Root<UserEntity>, _: CriteriaQuery<*>?, criteriaBuilder: CriteriaBuilder ->
                //增加筛选的条件
                val predicate = criteriaBuilder.conjunction()
                /**模糊查询**/
                if (!userName.isNullOrEmpty()) {
                    predicate.expressions.add(criteriaBuilder.like(root.get("userName"), "%$userName%"))
                }
                /**精确查询**/
                if (!account.isNullOrEmpty()) {
                    predicate.expressions.add(criteriaBuilder.equal(root.get<String>("account"), account))
                }
                /**范围查询**/
                if (!workType.isNullOrEmpty()) {
                    val statusIn = criteriaBuilder.`in`(root.get<WorkType>("workType"))
                    workType.split(",".toRegex()).forEach {
                        statusIn.value(WorkType.valueOf(it))
                    }
                    predicate.expressions.add(statusIn)
                    //第二种方式
                    //predicate.expressions.add(root.get<WorkType>("workType").`in`(listOf(WorkType.STUDENT,WorkType.TEACHER)))
                }
                /**时间段查询**/
                if (startTime != null) {
                    //大于等于开始时间
                    predicate.expressions.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createDate"), startTime))
                }
                if (endTime != null) {
                    //小于等于结束时间
                    predicate.expressions.add(criteriaBuilder.lessThanOrEqualTo(root.get("createDate"), endTime))
                }
                predicate
            }

        return userRepository.findAll(specification).map { it.toUserDto() }
    }

    fun findByPage(pageDto: PageDto): PagedData<List<UserDto>> {
        val pages = userRepository.findAll(pageDto.getPageRequest())

        return PagedData<List<UserDto>>().also { pageDate ->
            pageDate.data = pages.content.map {
                it.toUserDto()
            }
            pageDate.total = pages.totalElements
        }
    }
}
PagedData分页实体
package com.hmbase.common.page

class PagedData<T> {
    /**
     * 数据内容
     */
    var data: T? = null

    /**
     * 数据总数目
     */
    var total: Long = 0
}

转载请注明出处!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值