JPA实现CURD

话说:

生活中离不开吃喝玩乐,代码世界自然离不开CURD。到现在为止,我也觉得CURD蛮好的,很多东西不都是建立在基础之上的么。

目录


1.创建JPA工程
2.基本注解解释
3.实现CURD
4.总结


开发工具:Eclipse
难度系数:★★☆☆☆
建议用时:1H

1.创建JPA工程

Eclipse==》new Project ==>new JPA Project

==》添加Tomcat 和jre环境 ==》处理 At least one user library must be selected 这个问题!

这一句表明:JPA在Eclipse中是需要这些包包的。

这里写图片描述

这里写图片描述

如果联网环境不好,请参考这篇博客链接下载:

https://blog.csdn.net/baidu_37107022/article/details/76554393


https://www.eclipse.org/eclipselink/downloads/ 处下载 EclipseLink 2.5.2 Installer Zip (38 MB) 资源(也可以选择其它版本)。EclipseLink中提供了所有持久化服务的的实现。
● 持久化服务将会用到下面三个jar包:
    ①、eclipselink.jar
    ②、javax.persistence.source_2.1.0.v201304241213.jar
    ③、javax.persistence_2.1.0.v201304241213.jar
● 将下载好的EclipseLink 2.5.2压缩包解压到任何你想用于完成安装的文件夹中。我将文件解压到 “.\workspace\libraries\EclipseLink 2.5.2” 文件夹下。


创建完成后,项目初步结构是这样的:

这里写图片描述

2.基本注解解释

  1. @Table  标注类对应的表 
  2.  * 若表名和类型相同时,省略@Table,比如类Users 和表 users; 
  3.  * 若不相同时,必须有@Table,并设置name,为该类对应的表名。@Table(name="users") 
  4.  *  
  5.  * @Entity 标注实体 
  6.  *  
  7.  * @Id 标注id 
  8.  *  
  9.  * @Transient 标注该属性不做与表的映射(原因:可能表中没有该属性对应的字段) 
  10.  * 有该注解,在执行sql语句时,就不会出现该属性,否则会有,若表中没有该字段则会报错 
  11.  *  
  12.  * @Basic 默认所有属性都有该注解(主键需要单独使用@Id),所以可以省略 
  13.  *          该注解可以放在属性上,也可以放在对应的getter方法上。 
  14.  *           注意:要么统一将@Basic放在属性上,要么统一放在对应的getter方法上。(一般都放在属性上,可读性比较好) 
  15.  *  
  16.  * @Column 类中属性名和表中对应字段名不相同时,会使用该注解,指明在类中对应的字段 
  17.  *          @Column(name="对应的表中字段名") 

@GeneratedValue:主键的产生策略,通过strategy属性指定。 
主键产生策略通过GenerationType来指定。GenerationType是一个枚举,它定义了主键产生策略的类型。 
1、AUTO自动选择一个最适合底层数据库的主键生成策略。如MySQL会自动对应auto increment。这个是默认选项,即如果只写@GeneratedValue,等价于@GeneratedValue 
(strategy=GenerationType.AUTO)。

2、IDENTITY 表自增长字段,Oracle不支持这种方式。

3、SEQUENCE 通过序列产生主键,MySQL不支持这种方式。

4、TABLE 通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植。不同的JPA实现商生成的表名是不同的,如 OpenJPA生成openjpa_sequence_table表,Hibernate生成一个hibernate_sequences表,而TopLink则生成sequence表。这些表都具有一个序列名和对应值两个字段,如SEQ_NAME和SEQ_COUNT。

3.实现CURD

1.项目结构
2.配置文件
3.代码
4.总结
整体参考这篇博客即可:
https://blog.csdn.net/baidu_37107022/article/details/76572195
这篇有完整的包结构:
https://blog.csdn.net/hmk2011/article/details/6289151

我的这个跟别人的博客有啥区别?


1)有明确的运行结果
2)代码最后有明确的处理异常过程。


1.项目结构

这里写图片描述

注意,按照图示包的内容,在src下新建一个folder,存放各种包包,然后build path即可。

2.配置文件

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="myjpa01"  transaction-type="RESOURCE_LOCAL" >
        <!-- 配置Jpa ORM  产品 -->
        <provider>org.hibernate.jpa.HibernatePersistenceProvider </provider>
        <!-- 添加对应持久化的类 -->
        <class>com.hmc.pojo.Users</class>       
        <properties>
        <!-- jpa中连接数据库 -->
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpa"/>
            <property name="javax.persistence.jdbc.user" value="root"/>
            <property name="javax.persistence.jdbc.password" value="123456"/>

        <!-- jpa中配置hibernate的基本属性 -->
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
        </properties>
    </persistence-unit>
</persistence>

3.代码
1)pojo
2)test
3)util

1)pojo-Users

package com.hmc.pojo;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

/**
Author:meice Huang
Time:2018年4月4日下午12:37:21
*/


@Table(name="users")
@Entity
public class Users {
    /**
     * create database jpa;
     * use jpa;
     * 
     * create table users(
     *  userId int auto_increment primary key,
     *  userName varchar(50) not null,
     *  age int 
     * 
     * );
     * 
     * #模拟数据
     * insert into users (userName,age) values 
     * ("刘备",52),
     * ("周瑜",35),
     * ("诸葛亮",27);
     */
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="userId")
    private  Integer userId;
    @Column(name="userName")
    private  String userName;
    @Column(name="age")
    private int age;

    public Users() {}
    public Users(Integer userId, String userName, int age) {
        super();
        this.userId = userId;
        this.userName = userName;
        this.age = age;
    }
    public Integer getUserId() {
        return userId;
    }
    public void setUserId(Integer userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Users [userId=" + userId + ", userName=" + userName + ", age=" + age + "]";
    }

}

2)test-Test_jpa

package com.hmc.test;

import java.util.HashMap;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Persistence;
import javax.transaction.Transaction;

import org.junit.Test;

import com.hmc.pojo.Users;
import com.hmc.util.GetJpaManager;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TestGenerator;

/**
Author:meice Huang
Time:2018年4月4日下午2:07:09
*/
public class Test_jpa {

    /**
     * 查-1
     */
    @Test
    public void testFind() {
        //1.获取factory 
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("myjpa01");
        //2.获取Manager
        EntityManager em = factory.createEntityManager();
        //3.获取事务,并开启事务
        EntityTransaction transaction =em.getTransaction();

        transaction.begin();
        Users users =   em.find(Users.class, 1);
        System.out.println(users.getUserName());
        //4.提交事务
        transaction.commit();
        em.close();
        factory.close();
    }

    /**
     * 运行结果:
             * 四月 04, 2018 4:39:54 下午 org.hibernate.dialect.Dialect <init>
        INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
        Hibernate: 
            select
                users0_.userId as userId1_0_0_,
                users0_.age as age2_0_0_,
                users0_.userName as userName3_0_0_ 
            from
                users users0_ 
            where
                users0_.userId=?
        1111
        四月 04, 2018 4:39:56 下午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
        INFO: HHH10001008: Cleaning up connection pool [jdbc:mysql://localhost:3306/jpa]

     */



    /**
     * 查-2   find()和getReference()的区别类似Hibernate的的get()和load() 懒加载
     */

    @Test
    public void testGet() {
        //这里利用自己封装好的GetJpaManager这个Utils
        EntityManager em = (EntityManager)GetJpaManager.getJpaMap().get("EntityManager");
        EntityTransaction transaction = (EntityTransaction)GetJpaManager.getJpaMap().get("EntityTransaction");
        //transaction.begin();
        //采用 懒加载方式执行查询
        Users users =   em.getReference(Users.class, 2);
        System.out.println("懒加载查出的对象是:  "+users);
        //transaction.commit();
        em.close();
    }
    /**
     * 运行结果:
     * 四月 04, 2018 10:27:37 下午 org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
Hibernate: 
    select
        users0_.userId as userId1_0_0_,
        users0_.age as age2_0_0_,
        users0_.userName as userName3_0_0_ 
    from
        users users0_ 
    where
        users0_.userId=?
懒加载查出的对象是:  Users [userId=2, userName=2222, age=57]
     * 
     * 不开启事务,照样可以查询。疑问:find()和getReference()2种方法查询区别和Hibernate的区别真的一样么?
     */


    /**
     * 增
     */
    @Test
    public void testAdd() {
        //1.获取Factory
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("myjpa01");
        //2.获取Manager
        EntityManager em =  factory.createEntityManager();
        //3.获取事务,并开启事务
        EntityTransaction transaction = em.getTransaction();
        transaction.begin();

        //4.执行SQL
        Users users = new Users();
        users.setUserName("刘备");
        users.setAge(56);
        em.persist(users);

        //5.提交事务 ,关闭资源
        transaction.commit();
        em.close();
        factory.close();
    }

    /**
     * 运行结果:
     * INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
Hibernate: 
    insert 
    into
        users
        (age, userName) 
    values
        (?, ?)
四月 04, 2018 5:18:50 下午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
INFO: HHH10001008: Cleaning up connection pool [jdbc:mysql://localhost:3306/jpa]
     */



    /**
     * 增 -增的同时加载配置信息
     * 初始化一个实体工厂有2种方式
     */
    @Test
    public void testAdd2() {
        //1.获取factory
        Map<String, Object> properties = new HashMap<>();
        properties.put("hibernate.format_sql", "false");
        EntityManagerFactory factory =      Persistence.createEntityManagerFactory("myjpa01", properties);
        //2.获取manager
        EntityManager em = factory.createEntityManager();
        EntityTransaction transaction = em.getTransaction();
        transaction.begin();
        //3.执行新增
        Users users = new Users();
        users.setUserName("八戒");
        users.setAge(32);
        em.persist(users);
        //4.提交事务并关闭资源
        transaction.commit();
        em.close();
        factory.close();
    }

    /**
     * 运行结果:
     * 
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
Hibernate: insert into users (age, userName) values (?, ?)
四月 04, 2018 5:37:19 下午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
INFO: HHH10001008
     */





    /**
     * 改
     */

    @Test
    public void testUpdate() {
        //不能通过封装的来执行改、删,因为是同一个事务 
        //EntityManager em =(EntityManager) GetJpaManager.getJpaMap().get("EntityManager");
        //EntityTransaction transaction =(EntityTransaction) GetJpaManager.getJpaMap().get("EntityTransaction");


        EntityManager em = Persistence.createEntityManagerFactory("myjpa01").createEntityManager();
        EntityTransaction transaction  = em.getTransaction();
        transaction.begin();
        //先查到想要修改的数据
        Users users = em.find(Users.class, 4);
        users.setUserName("八戒,好吃佬");
        transaction.commit();

        //关闭资源
        em.close();
    }
    /**
     * 运行结果:
四月 05, 2018 11:39:37 下午 org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
Hibernate: 
    select
        users0_.userId as userId1_0_0_,
        users0_.age as age2_0_0_,
        users0_.userName as userName3_0_0_ 
    from
        users users0_ 
    where
        users0_.userId=?
Hibernate: 
    update
        users 
    set
        age=?,
        userName=? 
    where
        userId=?

     */




    /**
     * 删
     */

    @Test
    public void testDel() {
        EntityManager em =Persistence.createEntityManagerFactory("myjpa01").createEntityManager();
        EntityTransaction transaction = em.getTransaction();
        transaction.begin();
        Users users  = em.find(Users.class, 3);
        em.remove(users);
        transaction.commit();
        em.close();
    }
    /**
     * 运行结果:
     * 四月 05, 2018 11:31:04 下午 org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
Hibernate: 
    select
        users0_.userId as userId1_0_0_,
        users0_.age as age2_0_0_,
        users0_.userName as userName3_0_0_ 
    from
        users users0_ 
    where
        users0_.userId=?
Hibernate: 
    delete 
    from
        users 
    where
        userId=?
     */


    /**
     * 类型1:缺包
     * 
     * 1.Caused by: java.lang.ClassNotFoundException: org.jboss.logging.Logger
     * 缺jboss包,下载即可。
     * 
     * 2.Caused by: java.lang.ClassNotFoundException: javax.transaction.SystemException
     * 缺少了一个jta-1.1.0.jar包,加进去就可以了!   去Maven仓库搜索jta下载。
     * 
     * 3.Caused by: java.lang.ClassNotFoundException: org.dom4j.io.STAXEventReader
     * 缺少dom4j包
     * 
     * 4.Caused by: java.lang.ClassNotFoundException: org.hibernate.annotations.common.reflection.ClassLoaderDelegate
     * 有时候你包虽然有,但是是N多年前的包了,要下载最近年限的,因为有变化。
     * 
     * 5.ava.lang.NoSuchMethodError: org.hibernate.annotations.common.reflection.java.JavaReflectionManager.setMetadataProvider(Lorg/hibernate/annotations/common/reflection/MetadataProvider;)V
     * 如果已经有这个包,jar包冲突导致。笔者就是下载了多个hibernate.annotations.common导致的。根据报错信息得知,没有setMetadataProvider()方法
     * 
     * 类型2:驱动加载
     * 
     * 6.   ... 37 more
Caused by: java.lang.ClassNotFoundException: Could not load requested class : com.mysql.jdbc.driver
        加载驱动失败!很明显,这个驱动类全名写错了!好像是6.0版本之后:com.mysql.cj.jdbc.Driver

        7.
        java.lang.IllegalArgumentException: Provided id of the wrong type for class com.hmc.pojo.Users. Expected: class java.lang.Integer
    Caused by: org.hibernate.TypeMismatchException: Provided id of the wrong type for class com.hmc.pojo.Users. Expected: class java.lang.Integer, got class java.lang.String
        这里很明显:数据库userId和实体类类型不一致,查看下,笔者都是int类型,没问题!
        那么就是Users users =   em.find(Users.class, 1); 这个地方,第一次写成了"1",你要找的东西类型要和设计一致!

     */

    /**
     * 1、如果事务没有提交,报错:
     *  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
Caused by: org.hibernate.exception.SQLGrammarException: error performing isolated work 隔离性错误!

2、java.sql.SQLSyntaxErrorException: Table 'jpa.hibernate_sequence' doesn't exist
Caused by: java.sql.SQLSyntaxErrorException: Table 'jpa.hibernate_sequence' doesn't exist
    这里_sequence应该能想到是主键生成策略的问题,所以在注解那一块找。主键生成策略有:AUTO \ IDENTITY \SEQUENCE \TABLE
@GeneratedValue(strategy=GenerationType.IDENTITY)
3.Caused by: org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): com.hmc.pojo.Users
    这里表达:主键生成策略,要手动配置,不能自动生成。@GeneratedValue这样就是默认的,等同于GenerationType.AUTO。不行,需要手动指定为Identity


    4.java.sql.SQLException: Incorrect string value: '\xE4\xB8\x8D\xE4\xB8\x89...' for column 'userName' at row 1
    这个报错背景:我重置了MySQL的编码,之前默认是latin,发现乱码之后,在/etc下新增my.cnf配置,然后重启。
    由于数据库编码已经修改,但是已经建好的jpa数据库和表默认编码还是latin,所以报这个错。
    搞定方法:删掉数据库和表,重建。搞定!


     */




}

3)util-GetJpaManager

package com.hmc.util;
/**
Author:meice Huang
Time:2018年4月4日下午5:44:18
*/

import java.util.HashMap;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

import org.junit.Test;

public class GetJpaManager {


    /**
     * 这么封装仍然不够简洁
     * 事务还是要单独写
     * @return
     */
    @Test
    public static EntityManager getEntityManager() {
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("myjpa01");
        EntityManager em = factory.createEntityManager();
        return em;
    }


    /**
     * 这个方法可以返回2个值:
     * EntiryManager
     * EntiryTransaction
     * @return
     */

    @Test
    public static Map<String, Object> getJpaMap() {
        Map<String, Object> jpaMap = new HashMap<>();
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("myjpa01");
        EntityManager em =  factory.createEntityManager();
        EntityTransaction transaction = em.getTransaction();
        jpaMap.put("EntityManager", em);
        jpaMap.put("EntityTransaction", transaction);
        return jpaMap;
        //问题在于如何关闭?factory
    }

}

4.总结


1.可以直接新建jpa工程,jpa是什么?是一个架构规范。有点类似JDBC.Hibernate是这个规范的一个典型实现。

这里写图片描述

2.JPA的API:
CURD: 查:find(Users.class,2) 增:persist(对象); 改:find()之后修改属性; 删:remove(对象)

3.在研究查的2种方式:find()和getReference()的区别?为什么要设置这种区别?这和Hibernate的get()和load()方法有异曲同工之处?

4.remove()的时候,只能删除持久化对象,不能移除游离对象,这句话如何理解?


好了,下期再会!

感情有时候也像这篇博客一样“难产“,看似那么自然的事情,为什么就如此。。。。。。

猜你喜欢

转载自blog.csdn.net/meiceatcsdn/article/details/79830535
今日推荐