演示环境
MySQL 5.7
JDK1.8
spring-data-jpa 1.10.4.RELEASE
hibernate 5.1.2.Final
这里演示一个余额宝的例子,一个用户一天一条记录,表示一个用户一天的收益情况。其中,用户ID,日期是复合主键
项目总体结构如下:
下面依次贴出源代码
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;
最后说一句,余额宝的利息好低啊,一万块钱存一天,只有1块钱左右