zoukankan      html  css  js  c++  java
  • JPA 简单实体映射和EntityManagerAPI

    【常用注解】

    使用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】





    【简单实体对象: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

  • 相关阅读:
    从Linux内核中获取真随机数【转】
    linux下pthread_cancel无法取消线程的原因【转】
    LINUX-内核-中断分析-中断向量表(3)-arm【转】
    ARM中断向量表与响应流程【转】
    小任务与工作队列的区别【转】
    GNU Readline 库及编程简介【转】
    Linux 内核同步之自旋锁与信号量的异同【转】
    Professional Linux Kernel Architecture 笔记 —— 中断处理(Part 2)【转】
    Linux中断(interrupt)子系统之二:arch相关的硬件封装层【转】
    浅谈C语言中的强符号、弱符号、强引用和弱引用【转】
  • 原文地址:https://www.cnblogs.com/baobeiqi-e/p/10534923.html
Copyright © 2011-2022 走看看