入门项目
搭建开发环境
1、创建maven工程
![](https://i-blog.csdnimg.cn/blog_migrate/621c90fea59116e89890f57c38ae7a68.png)
![](https://i-blog.csdnimg.cn/blog_migrate/456c09f833a92905d5c8d95158d62b4a.png)
2、引入坐标
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mars</groupId>
<artifactId>spring-data-jpa-01</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.hibernate.version>5.0.7.Final</project.hibernate.version>
</properties>
<dependencies>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- hibernate对jpa的支持包 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${project.hibernate.version}</version>
</dependency>
<!-- c3p0 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>${project.hibernate.version}</version>
</dependency>
<!-- log日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- Mysql and MariaDB -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
</dependencies>
</project>
3、创建Jpa核心配置文件
- 存放位置:配置到类路径下META-INF的文件夹下
- 命名:persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<!--
persistence-unit持久化单元
name:持久化单元名称
transaction-type: 事务管理的方式
JTA:分布式事务管理
RESOURCE_LOCAL:本地事务管理
-->
<persistence-unit name="" transaction-type="RESOURCE_LOCAL">
<!--
第一块:JPA的实现方式
-->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!--
第二块:数据库信息
-->
<properties>
<!--
数据库信息:
用户名:javax.persistence.jdbc.user
密码:javax.persistence.jdbc.password
驱动:javax.persistence.jdbc.driver
数据库地址:javax.persistence.jdbc.url
-->
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="root123"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://192.168.220.112/jpa"/>
<!--
配置JPA实现方的配置信息(可选)
显示sql:hibernate.show_sql=true
自动创建数据库表:hibernate.hbm2ddl.auto
create:程序运行时,创建表。如果有表,先删除表在创建
update:程序运行时,创建表。 如果有表,则不会创建
none:不做任何操作
-->
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="create"/>
</properties>
</persistence-unit>
</persistence>
4、创建实体类
@Entity
@Table(name = "cst_customer")
public class Customer implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "cust_id")
private Long custId;//客户编号(主键)
@Column(name = "cust_name")
private String custName;//客户名称
@Column(name = "cust_source")
private String custSource;//客户信息来源
@Column(name = "cust_industry")
private String custIndustry;//客户所属行业
@Column(name = "cust_level")
private String custLevel;//客户级别
@Column(name = "cust_address")
private String custAddress;//客户联系地址
@Column(name = "cust_phone")
private String custPhone;//客户联系电话
//省略getter、setter方法
}
5、编写符合SpringDataJpa规范的Dao
/**
* 符合SpringDateJpa的dao层接口泛型
* JpaRepository<操作的实体类类型,实体类中主键的类型> 用于简单的查询
* JpaSpecificationExecutor<操作的实体类类型> 用于复杂的查询
*/
public interface CustomerDao extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> {
}
入门配置介绍
关于hibernate.hbm2ddl.auto的使用
create
程序运行时,创建表。如果有表,先删除表在创建
例如:数据库表内容有11条数据
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<!--
persistence-unit持久化单元
-->
<persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">
<!--
第一块:JPA的实现方式
-->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!--
第二块:数据库信息
-->
<properties>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="root123"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://192.168.220.112/jpa?characterEncoding=utf8"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="create"/>
</properties>
</persistence-unit>
</persistence>
测试代码如下:
package com.mars.test;
import com.mars.domain.Customer;
import org.junit.Test;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class JpaTest {
@Test
public void testSave() {
//1、加载配置文件创建工厂
EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJpa");
//2、通过实体管理类工厂获取实体管理器
EntityManager entityManager = factory.createEntityManager();
//3、获取事务对象,开启事物
EntityTransaction entityTransaction = entityManager.getTransaction();
entityTransaction.begin();
//4、完成增删改查操作
Customer customer = new Customer();
customer.setCustName("xx");
customer.setCustIndustry("新科技");
entityManager.persist(customer);
//5、提交事物(回滚事务)
entityTransaction.commit();
//6、释放资源
entityManager.close();
factory.close();
}
}
日志显示结果
Hibernate: drop table if exists cst_customer
Hibernate: create table cst_customer (cust_id bigint not null auto_increment, cust_address varchar(255), cust_industry varchar(255), cust_level varchar(255), cust_name varchar(255), cust_phone varchar(255), cust_source varchar(255), primary key (cust_id))
Hibernate: insert into cst_customer (cust_address, cust_industry, cust_level, cust_name, cust_phone, cust_source) values (?, ?, ?, ?, ?, ?)
通过日志可以看出,先执行drop删除表,然后执行create创建表,再insert添加数据
update
程序运行时,创建表。如果有表,则不会创建
例如:数据库不存在表
配置文件中设置为update
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<!--
persistence-unit持久化单元
-->
<persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">
<!--
第一块:JPA的实现方式
-->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!--
第二块:数据库信息
-->
<properties>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="root123"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://192.168.220.112/jpa?characterEncoding=utf8"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
测试代码如下:
package com.mars.test;
import com.mars.domain.Customer;
import org.junit.Test;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class JpaTest {
@Test
public void testSave() {
//1、加载配置文件创建工厂
EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJpa");
//2、通过实体管理类工厂获取实体管理器
EntityManager entityManager = factory.createEntityManager();
//3、获取事务对象,开启事物
EntityTransaction entityTransaction = entityManager.getTransaction();
entityTransaction.begin();
//4、完成增删改查操作
Customer customer = new Customer();
customer.setCustName("xx2");
customer.setCustIndustry("新科技");
entityManager.persist(customer);
//5、提交事物(回滚事务)
entityTransaction.commit();
//6、释放资源
entityManager.close();
factory.close();
}
}
日志显示结果
Hibernate: insert into cst_customer (cust_address, cust_industry, cust_level, cust_name, cust_phone, cust_source) values (?, ?, ?, ?, ?, ?)
通过日志可以看出,直接执行insert插入语句
none
不做任何操作
例如:数据库不存在表
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<!--
persistence-unit持久化单元
-->
<persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">
<!--
第一块:JPA的实现方式
-->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!--
第二块:数据库信息
-->
<properties>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="root123"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://192.168.220.112/jpa?characterEncoding=utf8"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="none"/>
</properties>
</persistence-unit>
</persistence>
测试代码如下:
package com.mars.test;
import com.mars.domain.Customer;
import org.junit.Test;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class JpaTest {
@Test
public void testSave() {
//1、加载配置文件创建工厂
EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJpa");
//2、通过实体管理类工厂获取实体管理器
EntityManager entityManager = factory.createEntityManager();
//3、获取事务对象,开启事物
EntityTransaction entityTransaction = entityManager.getTransaction();
entityTransaction.begin();
//4、完成增删改查操作
Customer customer = new Customer();
customer.setCustName("xx2");
customer.setCustIndustry("新科技");
entityManager.persist(customer);
//5、提交事物(回滚事务)
entityTransaction.commit();
//6、释放资源
entityManager.close();
factory.close();
}
}
日志显示结果
Hibernate: insert into cst_customer (cust_address, cust_industry, cust_level, cust_name, cust_phone, cust_source) values (?, ?, ?, ?, ?, ?)
javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not execute statement
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'jpa.cst_customer' doesn't exist
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
at com.mysql.jdbc.Util.getInstance(Util.java:381)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1030)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3491)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3423)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1936)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2060)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2542)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1734)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2019)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1937)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1922)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204)
... 44 more
通过日志可以看出,直接报错Table 'jpa.cst_customer' doesn't exist(jpa.cst_customer表不存在)
主键生成策略
通过annotation(注解)来映射hibernate实体的,基于annotation的hibernate主键标识为@Id, 其生成规则由@GeneratedValue设定的.这里的@id和@GeneratedValue都是JPA的标准用法。
源码解析:
@Target({ElementType.METHOD, ElementType.FIELD}) //作用在方法和属性上
@Retention(RetentionPolicy.RUNTIME) //运行时加载
public @interface GeneratedValue {
GenerationType strategy() default GenerationType.AUTO;
String generator() default "";
}
strategy
主键的策略:
- GenerationType.TABLE:JPA提供的一种机制,通过一张数据库表的形式帮助我们完成主表自增
//@TableGenerator的定义:
@Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface TableGenerator {
//表示该表主键生成策略的名称,它被引用在@GeneratedValue中设置的“generator”值中
String name();
//表示表生成策略所持久化的表名,例如,这里表使用的是数据库中的“tb_generator”。
String table() default "";
//catalog和schema具体指定表所在的目录名或是数据库名
String catalog() default "";
String schema() default "";
//属性的值表示在持久化表中,该主键生成策略所对应键值的名称。例如在“tb_generator”中将“gen_name”作为主键的键值
String pkColumnName() default "";
//属性的值表示在持久化表中,该主键当前所生成的值,它的值将会随着每次创建累加。例如,在“tb_generator”中将“gen_value”作为主键的值
String valueColumnName() default "";
//属性的值表示在持久化表中,该生成策略所对应的主键。例如在“tb_generator”表中,将“gen_name”的值为“CUSTOMER_PK”。
String pkColumnValue() default "";
//表示主键初识值,默认为0。
int initialValue() default 0;
//表示每次主键值增加的大小,例如设置成1,则表示每次创建新记录后自动加1,默认为50。
int allocationSize() default 50;
UniqueConstraint[] uniqueConstraints() default {};
}
- GenerationType.SEQUENCE:序列策略
- 底层数据库支持序列
- 支持的数据库:Oracle
配置实例:
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator="payablemoney_seq")
@SequenceGenerator(name="payablemoney_seq", sequenceName="seq_payment")
private Long custId;
//@SequenceGenerator源码中的定义
@Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface SequenceGenerator {
//表示该表主键生成策略的名称,它被引用在@GeneratedValue中设置的“generator”值中
String name();
//属性表示生成策略用到的数据库序列名称。
String sequenceName() default "";
//表示主键初识值,默认为0
int initialValue() default 0;
//表示每次主键值增加的大小,例如设置1,则表示每次插入新记录后自动加1,默认为50
int allocationSize() default 50;
}
- GenerationType.IDENTITY:自增策略。
- 底层数据库必须支持自动增长。支持的数据库:Mysql
- GenerationType.AUTO:由程序自动的帮助我们选择主键生成策略。也是JPA默认的
generator
自定义生成策略