01 JPA入门

入门项目

搭建开发环境

1、创建maven工程

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

自定义生成策略

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值