欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring Data JPA使用复合主键

程序员文章站 2022-04-23 15:58:49
...

演示环境

MySQL 5.7

JDK1.8

spring-data-jpa 1.10.4.RELEASE

hibernate 5.1.2.Final

这里演示一个余额宝的例子,一个用户一天一条记录,表示一个用户一天的收益情况。其中,用户ID,日期是复合主键

项目总体结构如下:

Spring Data JPA使用复合主键


下面依次贴出源代码

pom.xml

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.pp.jpa</groupId>
	<artifactId>springdata-jpa</artifactId>
	<version>1.0.0</version>
	<packaging>jar</packaging>

	<name>springdata-jpa</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
	</properties>

	<dependencies>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.40</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-jpa</artifactId>
			<version>1.10.4.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>5.1.2.Final</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>5.1.2.Final</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

</project>

下面依次是Java源码

package com.pp.jpa.config;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

@Configuration
public class JPAConfiguration {

	@Bean
	public DataSource createDataSource(){
		MysqlDataSource ds = new MysqlDataSource();
		ds.setURL("jdbc:mysql://127.0.0.1:3306/jpa");
		ds.setUser("root");
		ds.setPassword("admin123");
		return ds;
	}
	
	@Bean(name="entityManagerFactory")
	public EntityManagerFactory createEntityManagerFactory(DataSource dataSource){
		LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
		entityManagerFactory.setDataSource(dataSource);
		
		HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
		jpaVendorAdapter.setGenerateDdl(true);
		jpaVendorAdapter.setShowSql(true);
		entityManagerFactory.setPackagesToScan("com.pp.jpa.entity");
		entityManagerFactory.setJpaVendorAdapter(jpaVendorAdapter);
		entityManagerFactory.afterPropertiesSet();
		return entityManagerFactory.getObject();
	}
	
	@Bean(name="transactionManager")
	public PlatformTransactionManager createPlatformTransactionManager(EntityManagerFactory entityManagerFactory){
		JpaTransactionManager transactionManager = new JpaTransactionManager();
		transactionManager.setEntityManagerFactory(entityManagerFactory);
		return transactionManager;
	}
}





package com.pp.jpa.entity;

import java.io.Serializable;

import javax.persistence.Embeddable;

/**
 * 主键 
 * 代表复合主键的实体bean需要实现Serializable接口
 */
@Embeddable
public class UserFundPrimarykey implements Serializable {
	
	private static final long serialVersionUID = 1L;

	//用户ID
	private Integer userId;
	
	/**
	 * 日期,格式yyyy-MM-dd
	 */
	private String date;
	
	public UserFundPrimarykey() {}
	
	public UserFundPrimarykey(Integer userId, String date) {
		this.userId = userId;
		this.date = date;
	}

	public Integer getUserId() {
		return userId;
	}

	public void setUserId(Integer userId) {
		this.userId = userId;
	}

	public String getDate() {
		return date;
	}

	public void setDate(String date) {
		this.date = date;
	}

	@Override
	public String toString() {
		return "UserFundPrimarykey [userId=" + userId + ", date=" + date + "]";
	}
}

package com.pp.jpa.entity;

import java.math.BigDecimal;

import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;

/**
 *  模拟一个余额宝的功能
 *  一条记录代表一个用户一天的收益信息(本金,利率,利息)
 */
@Entity
@Table(name = "user_funds")
public class UserFund {
	
	/**
	 * 主键
	 * 复合主键不能用@Id,需要用@EmbeddedId。插入数据的时候必须手工赋值
	 */
	@EmbeddedId
	private UserFundPrimarykey userFundPK;
	
	//本金
	@Column(precision=18, scale=5)
	private BigDecimal principal;
	
	//利率(5%传0.05)
	@Column(precision=18, scale=5)
	private BigDecimal rate;
	
	/**
	 * 当天收益(日利息=本金*利率/365)
	 * 保留2位小数
	 */
	@Column(precision=18, scale=2)
	private BigDecimal interest;

	public UserFundPrimarykey getUserFundPK() {
		return userFundPK;
	}

	public void setUserFundPK(UserFundPrimarykey userFundPK) {
		this.userFundPK = userFundPK;
	}

	public BigDecimal getPrincipal() {
		return principal;
	}

	public void setPrincipal(BigDecimal principal) {
		this.principal = principal;
	}

	public BigDecimal getRate() {
		return rate;
	}

	public void setRate(BigDecimal rate) {
		this.rate = rate;
	}

	public BigDecimal getInterest() {
		return interest;
	}

	public void setInterest(BigDecimal interest) {
		this.interest = interest;
	}

	@Override
	public String toString() {
		return "UserFund [userFundPK=" + userFundPK + ", principal=" + principal + ", rate=" + rate + ", interest="
				+ interest + "]";
	}
}

package com.pp.repository;

import org.springframework.data.repository.CrudRepository;

import com.pp.jpa.entity.UserFund;
import com.pp.jpa.entity.UserFundPrimarykey;

public interface UserFundRepository extends CrudRepository<UserFund, UserFundPrimarykey> {
	
} 

启动类

package com.pp.jpa;

import java.math.BigDecimal;
import java.math.RoundingMode;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import com.pp.jpa.entity.UserFund;
import com.pp.jpa.entity.UserFundPrimarykey;
import com.pp.repository.UserFundRepository;

@ComponentScan
@EnableJpaRepositories(value="com.pp")
@EnableTransactionManagement
public class App {
	public static void main(String[] args) throws Exception {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(App.class);
		
		UserFund uf1 = new UserFund();
		//必须手动设置主键
		uf1.setUserFundPK(new UserFundPrimarykey(1, "2017-07-01"));
		uf1.setRate(new BigDecimal("0.041"));
		uf1.setPrincipal(new BigDecimal("10000"));
		//截断,只保留两位小数
		uf1.setInterest(uf1.getRate().multiply(uf1.getPrincipal()).divide(new BigDecimal("365"), 2, RoundingMode.DOWN));
		
		UserFund uf2 = new UserFund();
		//必须手动设置主键
		uf2.setUserFundPK(new UserFundPrimarykey(2, "2017-07-01"));
		uf2.setRate(new BigDecimal("0.041"));
		uf2.setPrincipal(new BigDecimal("20000"));
		//截断,只保留两位小数
		uf2.setInterest(uf2.getRate().multiply(uf2.getPrincipal()).divide(new BigDecimal("365"), 2, RoundingMode.DOWN));
		
		UserFundRepository ur = context.getBean(UserFundRepository.class);
		ur.save(uf1);
		ur.save(uf2);
		
		ur.findAll().forEach(System.out::println);
		
		//查询用户ID=2,在2017-07-01这一天的收益
		System.out.println(ur.findOne(new UserFundPrimarykey(2, "2017-07-01")));
		context.close();
	}
}

一些注意事项和做法已经在备注中有写,大家模仿着写就OK了


直接运行main方法,控制台输出如下信息

Hibernate: select userfund0_.date as date1_0_0_, userfund0_.userId as userId2_0_0_, userfund0_.interest as interest3_0_0_, userfund0_.principal as principa4_0_0_, userfund0_.rate as rate5_0_0_ from user_funds userfund0_ where userfund0_.date=? and userfund0_.userId=?
Hibernate: insert into user_funds (interest, principal, rate, date, userId) values (?, ?, ?, ?, ?)
Hibernate: select userfund0_.date as date1_0_0_, userfund0_.userId as userId2_0_0_, userfund0_.interest as interest3_0_0_, userfund0_.principal as principa4_0_0_, userfund0_.rate as rate5_0_0_ from user_funds userfund0_ where userfund0_.date=? and userfund0_.userId=?
Hibernate: insert into user_funds (interest, principal, rate, date, userId) values (?, ?, ?, ?, ?)
Hibernate: select userfund0_.date as date1_0_, userfund0_.userId as userId2_0_, userfund0_.interest as interest3_0_, userfund0_.principal as principa4_0_, userfund0_.rate as rate5_0_ from user_funds userfund0_
UserFund [userFundPK=UserFundPrimarykey [userId=1, date=2017-07-01], principal=10000.00000, rate=0.04100, interest=1.12]
UserFund [userFundPK=UserFundPrimarykey [userId=2, date=2017-07-01], principal=20000.00000, rate=0.04100, interest=2.24]
Hibernate: select userfund0_.date as date1_0_0_, userfund0_.userId as userId2_0_0_, userfund0_.interest as interest3_0_0_, userfund0_.principal as principa4_0_0_, userfund0_.rate as rate5_0_0_ from user_funds userfund0_ where userfund0_.date=? and userfund0_.userId=?
UserFund [userFundPK=UserFundPrimarykey [userId=2, date=2017-07-01], principal=20000.00000, rate=0.04100, interest=2.24]

查询数据库

select ** from user_funds;

Spring Data JPA使用复合主键


最后说一句,余额宝的利息好低啊,一万块钱存一天,只有1块钱左右




相关标签: spring data jpa jpa