JPA 简单实体映射和EntityManagerAPI

时间:2022-09-04 21:42:01

【常用注解】

使用JPA 指定映射关系时,有两种方式,一种是使用xml 方式,另一种是注解方式,笔者推荐使用注解方式。在JPA 映射简单实体时,常用的注解如下:

@Entity:修饰实体类对象,表示该实体类对象进行数据库映射

@Table(name="***"):指定实体类对象映射的表名称

@Id: 指定主键

@GeneratedValue(strategy=GenerationType.AUTO):指定主键生成方式,默认为Auto。

IDENTITY:采用数据库 ID自增长的方式来自增主键字段,Oracle 不支持这种方式;
    AUTO: JPA自动选择合适的策略,是默认选项;
    SEQUENCE:通过序列产生主键,通过 @SequenceGenerator 注解指定序列名,MySql 不支持这种方式
    TABLE:通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植。

@Column(name="s_name",length=20,unique=true,nullable=false, insertable=true, updatable=true):修饰属性, 指定列名称和相关限制

@Enumerated(EnumType.STRING):修饰枚举类属性,

EnumType.STRING: 指定数据库中存储的是字符串类型,

EnumTypee.ORDINAL:指定数据库 存储的类型为枚举的索引(0,1,2,3...)

@Temporal(TemporalType.TIME):修饰日期类型:

TemporalType.DATE: 指定映射数据库中的DATE 类型,只存储日期

TemporalType.TIME: 指定映射数据库 中的TIME类型, 只存储时间

TemporalType.TIMESTAMP:指定映射数据库中的TIMESTAMP类型

@Transient:指定不映射的属性

@Lob:修饰 byte[] 数组,二进制文件

@Basic(fetch=FetchType.LAZY) : 默认注解,如果字段不添加任何注解,则默认添加了此注解。可以通过fetch 属性指定大数据字段延时加载,目前在Hibernate中并未能实现,或许是Hibernate的一个bug。

@NamedQueries({
@NamedQuery(name="***",query="*** hql ***"),
@NamedQuery(name="***",query="*** hql ***")
}): 命名查询注解,指定命名查询语句,query字段只能写JPQL 查询语句,不能写普通的sql 语句。

【JPA 常用API】

JPA 简单实体映射和EntityManagerAPI

【简单实体对象:PersonEntity.java】

package org.zgf.jpa.entity;
 
import java.util.Date;
 
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
 
import org.zgf.jpa.enumer.Gender;
 
 
 
@Table(name="tb_person")
@Entity
@NamedQueries({ //命名查询注解:只能写JPQL 语句
    @NamedQuery(name="queryAllByJpql",query="from PersonEntity personEntity"),
    @NamedQuery(name="queryByName",query="from PersonEntity personEntity where personEntity.name = :name")
})
public class PersonEntity {
    
    /**
     * 测试主键生成策略
     * GenerationType.AUTO: 根据数据库的默认规则来生成主键
     * GenerationType.IDENTITY:数据库自增(mysql 适用,Oracle不适用)                                                                                                        
     * GenerationType.SEQUENCE:序列生成方式,(Oracle适用,mysql 不适用)
     */
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Integer id;
    
    /***
     * 数据库字段限制:
     * Column可以指定数据库 字段的名称 ,长度,唯一性,是否可以为空,是否可以插入,是否可以更新
     */
    @Column(name="s_name",length=20,unique=true,nullable=false, insertable=true, updatable=true)
    private String name;
    private int age;
    
    /**
     * 枚举类型:
     * EnumType.STRING: 指定数据库中存储的是字符串类型
     * EnumTypee.ORDINAL:指定数据库 存储的类型为枚举的索引
     */
    @Enumerated(EnumType.STRING)
    private Gender gender;
    
    private Double englishScore;
    private Float mathScore;
    
    /**
     * 日期类型: TimeStamp 会根据当地的时间做自动转换
     * TemporalType.DATE: 指定映射数据库中的DATE 类型,只存储日期
     * TemporalType.TIME: 指定映射数据库 中的TIME类型, 只存储时间
     * TemporalType.TIMESTAMP:指定映射数据库中的TIMESTAMP类型
     */
    @Temporal(TemporalType.TIME)
    private Date birthdayTime;
    @Temporal(TemporalType.DATE)
    private Date birthdayDate;
    @Temporal(TemporalType.TIMESTAMP)
    private Date birthday;
    
    @Lob  //大数据文件
    @Basic(fetch=FetchType.LAZY, optional=true)  //延迟加载为true,貌似是Hibernate的一个bug,并不能实现延迟加载
    private byte[] info;
    
    @Transient  //不映射 此字段
    private String transientProperty;
 
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    public Gender getGender() {
        return gender;
    }
 
    public void setGender(Gender gender) {
        this.gender = gender;
    }
 
    public Double getEnglishScore() {
        return englishScore;
    }
 
    public void setEnglishScore(Double englishScore) {
        this.englishScore = englishScore;
    }
 
    public Float getMathScore() {
        return mathScore;
    }
 
    public void setMathScore(Float mathScore) {
        this.mathScore = mathScore;
    }
 
    public Date getBirthdayTime() {
        return birthdayTime;
    }
 
    public void setBirthdayTime(Date birthdayTime) {
        this.birthdayTime = birthdayTime;
    }
 
    public Date getBirthdayDate() {
        return birthdayDate;
    }
 
    public void setBirthdayDate(Date birthdayDate) {
        this.birthdayDate = birthdayDate;
    }
 
    public Date getBirthday() {
        return birthday;
    }
 
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
 
    public byte[] getInfo() {
        return info;
    }
 
    public void setInfo(byte[] info) {
        this.info = info;
    }
 
    public String getTransientProperty() {
        return transientProperty;
    }
 
    public void setTransientProperty(String transientProperty) {
        this.transientProperty = transientProperty;
    }
 
    @Override
    public String toString() {
        return "PersonEntity [id=" + id + ", name=" + name + ", age=" + age + ", gender=" + gender + ", englishScore=" + englishScore + ", mathScore=" + mathScore + ", birthdayTime=" + birthdayTime + ", birthdayDate=" + birthdayDate + ", birthday=" + birthday + ", transientProperty=" + transientProperty + "]";
    }
    
}

【EntityManger 常用API 使用方法:Test_PersonEntity.java】

package org.zgf.jpa.entity;
 
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
 
import javax.persistence.Query;
 
import org.junit.Test;
import org.zgf.jpa.enumer.Gender;
/**
 * @Description: 主要测试EntityManager类提供的常用接口
 * @author zonggf
 * @date 2015年11月4日-下午3:38:14
 */
public class Test_PersonEntity extends BasicJPATest {
    
    private PersonEntity getPersonEntity(){
        Date date = new Date();
        PersonEntity person = new PersonEntity();
        person.setName("zhangsan");
        person.setAge(20);
        person.setBirthday(date);
        person.setBirthdayDate(date);
        person.setBirthdayTime(date);
        person.setEnglishScore(20.20);
        person.setMathScore(89.8f);
        person.setGender(Gender.BOY);
        StringBuffer sb = new StringBuffer();
        for(int i=0; i<100;i++){
            sb.append("heladn asndsk nasfjgnas nsd gaksn a sdnkg asdn asndk asnd  ansf asd n  asngjka s");
        }
        person.setInfo(sb.toString().getBytes());
        return person;
    }
    
    //Test API 1: 测试persiste
    @Test
    public void test_persist(){
        PersonEntity personEntity = getPersonEntity();
        this.entityManager.persist(personEntity);
    }
    
    //Test API 2:测试remove接口
    @Test
    public void test_remove_right(){
        //正确删除方式,必须先从数据库中查询,然后再进行删除,而且查询结果不能为空
        PersonEntity personEntity = new PersonEntity();
        personEntity.setId(3);
        personEntity = this.entityManager.find(PersonEntity.class, personEntity.getId());
        if(null != personEntity){
            this.entityManager.remove(personEntity);;
        }
    }
    
    //Test API 2:测试remove接口
    @Test(expected=java.lang.IllegalArgumentException.class)
    public void test_remove_wrong(){
        //如果是自己创建的实体 对象,使用remove方式的时候,将会报错
        PersonEntity personEntity = getPersonEntity();
        personEntity.setId(3);
        this.entityManager.remove(personEntity);;
    }
    
    //Test API 3:测试mege 接口
    @Test
    public void test_merge(){
        //先根据主键进行查询,然后根据主键进行更新
        PersonEntity personEntity = getPersonEntity();
        personEntity.setId(7);
        personEntity.setName("zhangsan_merge" + 172);
        this.entityManager.merge(personEntity);
    }
    
    //Test API 4:测试find 接口
    @Test
    public void test_find(){
        //find 方法,是根据主键进行查询的,所以传的参数必须是主键
        int id = 5;
        PersonEntity person = this.entityManager.find(PersonEntity.class, id);
        System.out.println(person);
    }
    
    
    //Test API 5:测试createQuery(String jpql)接口
    @Test
    public void test_createQuery_String(){
        String jpql = "from PersonEntity personEntity";
        Query query = this.entityManager.createQuery(jpql);
        List<PersonEntity> personList = query.getResultList();
        for (PersonEntity personEntity : personList) {
            System.out.println(personEntity);
        }
    }
    
    //Test API 6:测试命名查询
    @Test
    public void test_namedQuery_jpql(){
        String namedQueryName = "queryByName";
        Query query = this.entityManager.createNamedQuery(namedQueryName);
        //设置命名参数
        query.setParameter("name", "zhangsan");
        PersonEntity person = (PersonEntity) query.getSingleResult();
        System.out.println(person);
    }
    
    //Test API 7:测试createNativeQuery(String sql)接口
    @Test
    public void test_sqlQuery(){
        List<PersonEntity> personList = new ArrayList<>();
        String sql = "select p.id, p.s_name, p.age from tb_person p";
        Query query = this.entityManager.createNativeQuery(sql);
        List list = query.getResultList();
        for(int i=0;i<list.size(); i++){
            PersonEntity person = new PersonEntity();
            Object[] objectArray = (Object[]) list.get(i);
            person.setId((Integer)objectArray[0]);
            person.setName((String)objectArray[1]);
            person.setAge((Integer)objectArray[2]);
            personList.add(person);
        }
        for(PersonEntity personEntity: personList){
            System.out.println(personEntity);
        }
    }
    
    
    
    
    
    
    
}

【辅助类:Gender.java】
package org.zgf.jpa.enumer;
/**
 * @Description: 枚举类,映射到数据库中的是BOY 而不是"男"
 * @author zonggf
 * @date 2015年11月4日-下午3:39:36
 */
public enum Gender {
 
    BOY("男"),GIRL("女");
    
    private String gender;
    
    Gender(String gender){
        this.gender = gender;
    }
    
    public static Gender getGender(String gender){
        Gender[] genderEnumers = Gender.values();
        for (Gender genderEnumer : genderEnumers) {
            if(null != gender){
                if(gender.equals(genderEnumer.toString())){
                    return genderEnumer;
                }
            }
        }
        return null;
    }
    
    @Override
    public String toString() {
        return this.gender;
    }
}

【辅助类:BasicJPATest.java】
package org.zgf.jpa.entity;
 
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
 
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
 * 这是一个JPA 的测试类,  该类的功能如下:
 * 1. 在每个测试方法之前调用setup 方法,开启事务并获取entityManager 对象。
 * 2. 在每个测试方法之后调用teardown 方法, 提交事务,并关闭entityManager 对象
 * @author Silence
 */
public abstract class BasicJPATest {
    protected EntityManagerFactory entityManagerFactory;
    protected EntityManager entityManager;
        
    //子类的每个测试方法之前都会调用
    @Before
    public void setup(){
        this.entityManagerFactory = Persistence.createEntityManagerFactory("myJPA");
        this.entityManager = this.entityManagerFactory.createEntityManager();
        this.entityManager.getTransaction().begin();
    }
    
    //子类的每个测试方法之后都会调用
    @After
    public void tearDown(){
        try{
            this.entityManager.getTransaction().commit();
        }catch(Exception ex){
            System.out.println("提交事务等阶段出现了错误哦");
        }finally{
            this.entityManager.close();
            this.entityManagerFactory.close();
        }
        
    }
    
    @Test
    public void testCreateTables(){
        System.out.println("数据库表创建成功。。。");
    }
    
    public void recoverData(){
        //清空表
        String deleteSql = "delete Person";
        Query query = this.entityManager.createQuery(deleteSql);
        query.executeUpdate();
        
    }
}

【注意】
1. @Basic(fetch=FetchType.LAZY) 注解在Hibernate 中不能实现,貌似是Hibernate 的一个bug

2. @Enumerated(EnumType.STRING) 注解映射的是枚举类的Key ,不是value

JPA 简单实体映射和EntityManagerAPI的更多相关文章

  1. Spring Boot 入门系列(二十八) JPA 的实体映射关系,一对一,一对多,多对多关系映射!

    前面讲了Spring Boot 使用 JPA,实现JPA 的增.删.改.查的功能,同时也介绍了JPA的一些查询,自定义SQL查询等使用.JPA使用非常简单,功能非常强大的ORM框架,无需任何数据访问层 ...

  2. JPA总结——实体关系映射(一对多&commat;OneToMany)

    JPA总结——实体关系映射(一对多@OneToMany) 注意:本文出自“阿飞”的博客,如果要转载本文章,请与作者联系! 并注明来源: http://blog.sina.com.cn/s/blog_4 ...

  3. JPA 实体映射

    一.实体基本映射 /* * @Entity:将领域对象标注为一个实体,表示保存到数据库中 * @@Table:保存到数据库中表名,默认表名为类名,可通过name属性命名 * * */ @Entity ...

  4. SQLite数据库和JPA简单介绍

    SQLite数据库和JPA简单介绍 一.SQLite简单使用 SQLite是遵循ACID的关系数据库管理系统,它的处理速度很快,它的设计目标是嵌入式的,只需要几百K的内存就可以了. 1.下载SQLit ...

  5. JPA Advanced Mappings&lpar;映射&rpar;

    JPA Advanced Mappings(映射) JPA是一个使用java规范发布的库.因此,它支持所有面向对象的实体持久性概念. 原文链接:http://blogxinxiucan.sh1.new ...

  6. 开源实体映射框架EmitMapper介绍

    开源实体映射框架EmitMapper介绍   综述       EmitMapper是一个开源实体映射框架,地址:http://emitmapper.codeplex.com/.       Emit ...

  7. EF Code First:实体映射,数据迁移,重构&lpar;1&rpar;

    一.前言 经过EF的<第一篇>,我们已经把数据访问层基本搭建起来了,但并没有涉及实体关系.实体关系对于一个数据库系统来说至关重要,而且EF的各个实体之间的联系,实体之间的协作,联合查询等也 ...

  8. EF Code First:实体映射

    二.实体映射 实体与数据库的映射可以通过DataAnnotation与FluentAPI两种方式来进行映射: (一) DataAnnotation DataAnnotation 特性由.NET 3.5 ...

  9. Hibernate&lpar;三&rpar;结构-配置文件-实体映射及配置文件

    一.体系结构 SessionFactory:属于单一数据库的编译过的映射文件的一个线程安全的,不可变的缓存快照.Session的工厂.有可能持有一个可选的数据缓存可以进程级别或者群级别保存可以在事务中 ...

随机推荐

  1. 记录特殊情况的Python脚本的内存异常与处理

    问题 Python 脚本使用 requests 模块做 HTTP 请求,验证代理 IP 的可用性,速度等. 设定 HTTP 请求的 connect timeout 与 read response ti ...

  2. ubuntu系统下wireshark普通用户抓包设置

    dumpcap需要root权限才能使用的,以普通用户打开Wireshark,Wireshark当然没有权限使用dumpcap进行截取封包.   虽然可以使用    sudo wireshark    ...

  3. Jenkins&comma;Maven及TestNG在自动化测试的应用(转)

    转自:http://qa.blog.163.com/blog/static/190147002201581634549893/ 希望实现的场景:Jenkins中的Job可针对不同浏览器,不同环境,运行 ...

  4. (转载)图片左右滚动控件(带倒影)——重写Gallery

    今天在网上找了些资料,做了一个图片左右滚动的Demo,类似幻灯片播放,同时,图片带倒影效果,运行效果如下图: 实现方式是重写Gallery,使用自定义的Gallery来实现这一效果,工程一共三个文件, ...

  5. POJ 2175 spfa费用流消圈

    题意:给出n栋房子位置和每栋房子里面的人数,m个避难所位置和每个避难所可容纳人数.然后给出一个方案,判断该方案是否最优,如果不是求出一个更优的方案. 思路:很容易想到用最小费用流求出最优时间,在与原方 ...

  6. VirtualBox中安装CentOS(新手教程)

    1.VirtualBox下载 官网:http://www.virtualbox.org/wiki/Downloads 下载好之后,一路下一步安装即可 2.CentOS下载 官网:https://www ...

  7. IIS发布网站,访问时出现无法识别的属性&OpenCurlyDoubleQuote;targetFramework”错误

    今天在IIS发布网站后,访问时出现无识别的属性“targetFramework”错误 错误描述: 错误原因: 是由IIS配置该站点的.NET Framework 版本与程序中的.NET Framewo ...

  8. c&num; sql 复制表后提示列无效解决办法

    --CREATE TABLE [dbo].[JinanCount] SELECT * FROM [dbo].[ChengXiangCount]   这条指令错误select * into [dbo]. ...

  9. 洛谷P2444 病毒【AC自动机】

    题目描述 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的.现在委员会已经找出了所有的病毒代码段,试问,是否 ...

  10. hdu 1498 50 years&comma; 50 colors(二分匹配&lowbar;匈牙利算法)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1498 50 years, 50 colors Time Limit: 2000/1000 MS (Ja ...