JPA入门

1、JPA简介

  JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。由SUN(已被oracle公司收购)提出,希望整合ORM技术,实现统一。JPA由EJB 3.0软件专家组开发,作为JSR-220实现的一部分。但它不囿于EJB 3.0,你可以在Web应用、甚至桌面应用中使用。JPA的宗旨是为POJO提供持久化标准规范。现在Hibernate、TopLink 已经OpenJPA都已经实现了这一规范。

2、实现

  这里所用到的实现是hibernate,下载地址是http://www.hibernate.org/downloads。下载好hibernate之后新建一个Pava Project,添加如下的jar包依赖。  JPA入门

数据库使用的是mysql,添加依赖mysql的驱动,mysql-connector-java-5.1.18-bin.jar

准备工作完成。

1)、新建Person类,并把这个类放在com.test.bean这个包中,我们使用annotation的方式对实体bean进行配置。Person类代码如下:

package com.test.bean;

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.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

enum Gender {
    MAN, WOMEN
}

@Entity
@Table(name = "person")
public class Person {// 表名根据实体名称取名

    // @Id
    private Integer id;// 字段
    private String name;
    private Date birthday;// 1987-12-10
    private Gender gender = Gender.MAN;
    private String info;
    private Byte[] file;
    private String imagepath;// 不希望被持久化

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }

    @Id
    @GeneratedValue
    // strategy = GenerationType.AUTO默认值
    public Integer getId() {// 属性的名称这里由get和set方法决定的,Id,
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Column(length = 10, nullable = false, name = "personName")
    public String getName() {// 对于名字最长的
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Temporal(TemporalType.DATE)
    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    // 枚举类型
    // @Enumerated(EnumType.ORDINAL)//数据库保存索引值,从0开始,建议保存String类型
    @Enumerated(EnumType.STRING)
    @Column(length = 5, nullable = false)
    public Gender getGender() {
        return gender;
    }

    public void setGender(Gender gender) {
        this.gender = gender;
    }

    // 大文本类型
    @Lob
    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    // 文件字节数组
    @Lob
    @Basic(fetch = FetchType.LAZY)
    // 延迟加载,若文件太大,使用的时候加载,否则浪费内存,推荐若超过M就该使用延迟加载
    public Byte[] getFile() {
        return file;
    }

    public void setFile(Byte[] file) {
        this.file = file;
    }

    // 不与数据库表中的字段做映射
    @Transient
    public String getImagepath() {
        return imagepath;
    }

    public void setImagepath(String imagepath) {
        this.imagepath = imagepath;
    }
}

2)、在src下新建一个名称为META-INF的package,并在META-INF下新建一个名称为persistence.xml的xml文件。persistence.xml文件的内容如下:

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
    version="2.0">
    <persistence-unit name="jpatest" transaction-type="RESOURCE_LOCAL">
  <!--  JTA事务只能运行在J2EE的环境中,即EJB容器中和Web容器中;而在J2SE环境中只能使用RESOURCE_LOCAL管理事务。 -->
<properties> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" /><!-- 数据库数据库方言 --> <property name="hibernate.hbm2ddl.auto" value="update" /><!-- 数据库用户名 --> <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" /><!-- 数据库驱动 --> <property name="hibernate.connection.username" value="root" /><!-- 数据库用户名 --> <property name="hibernate.connection.password" value="123456" /><!-- 数据库密码 --> <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/jpatest?useUnicode=true&amp;characterEncoding=UTF-8" /><!-- 数据库连接url --> <property name="hibernate.show_sql" value="true"></property><!-- 操作时显示sql语句 --> <property name="Hibernate.format_sql" value="true"></property><!-- 将显示的sql语句格式化 --> </properties> </persistence-unit> </persistence>

3)、生成数据库表

  此时连接的数据库是jpatest,这个数据库需要我们先在mysql中建好,jpa不会给我们自动生成数据库,只能自动帮我们生成表。

  @Test
  public void testSave() {
    // -->SessionFactory -->session -->begin事务    
    EntityManagerFactory factory
= Persistence.createEntityManagerFactory("jpatest");//jpatest为persistence.xml里面persistence-unit的name值
    // 得到SessionFactory,EntityManagerFactory对象的时候,就会创建表
    EntityManager manager
= factory.createEntityManager();
    manager.close();
    factory.close();
  }

通过这行代码我们可以为jpatest这个数据库生成表,表结构如下:

CREATE TABLE `person` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `birthday` date DEFAULT NULL,
  `file` longblob,
  `gender` varchar(5) NOT NULL,
  `info` longtext,
  `personName` varchar(10) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

4)、保存数据

    @Test
    public void testSave() {   
        EntityManagerFactory factory = Persistence
                .createEntityManagerFactory("jpatest");        manager.getTransaction().begin();// 开始事务
        // session.save() --> persist();
        Person person = new Person("张三");
        person.setBirthday(new Date());
        person.setGender(Gender.MAN);
        person.setInfo("zhang san info");
        byte[] file = "张三是个好孩子".getBytes();
        person.setFile(file);
        manager.persist(person);
        manager.getTransaction().commit();//提交事务
        manager.close();
        factory.close();
    }

5)、查询数据

    @Test
    public void testQuery() {
    EntityManagerFactory factory
= Persistence.createEntityManagerFactory("jpatest");
    EntityManager manager
= factory.createEntityManager();
    
// ====================方式一======================     // Person实体的名称,o是别名,jpa中必须使用select p     Query query = manager.createQuery("select p from Person p where p.id=?1");     query.setParameter(1, 1);     Person person = (Person) query.getSingleResult();// 该记录必须存在,否则会出错    
    
System.out.println(person);
    // ====================方式二======================
    
Person person2 = manager.find(Person.class, 1);// find使用了泛型,所有无需转换,相当于hibernate中的get方法
    System.out.println(person2);
    // ====================方式三======================
    /
/ load延迟初始化,不会立刻调用,只是返回一个代理对象,当对代理对象的属性进行访问的时候,才会从数据库中得到这条记录,不然不会发生数据的加载行为。EntityManager必须没有关闭     Person person3 = manager.getReference(Person.class, 1);
    System.out.println(person3);
// 若没有id为2的记录,此时,才会出现异常  
    manager.close();
    factory.close();
    }

如果执行Person person = manager.getReference(Person.class, 1);之后用来一分钟处理,数据中的person记录已被其他人修改. 此时若再执行manager.find()方法仍无法获取最新修改的person对象,它会从实体管理器EntityManager中的实体bean的缓存中获取原先查询到的对象。此时需要调用manager.refresh(person)这个方法,调用之后会重新到数据库中去查询最新的数据。

6)、修改数据

 

   @Test
    public void testUpdatePerson() {
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("jpatest");
        EntityManager manager = factory.createEntityManager();
        manager.getTransaction().begin();
     // ====================方式一=====================
    
// Person实体的名称,o是别名,jpa中必须使用select p
manager.getTransaction().begin();
     Query query = manager.createQuery("update Person p set p.name=:name where p.id=:id");
        query.setParameter("name", "李四xxx");
        query.setParameter("id", 3);
        query.executeUpdate();
manager.getTransaction().commit();
    
//
====================方式二=====================
        manager.getTransaction().begin(); 
Person person
= manager.find(Person.class, 1);
person.setName(
"李四");// 与事务关联,处于托管状态,可更新
manager.getTransaction().commit();
        // ====================方式二=====================
        manager.getTransaction().begin();
        Person person = manager.find(Person.class, 1);
        manager.clear();// 把实体管理器中的所有实体变成游离状态,
        person.setName("李四33");// 此时person为游离状态,无法同步到数据库
        manager.merge(person);// 把实体在游离状态的更新同步到数据库
        manager.getTransaction().commit();
manager.close(); factory.close();
// new 新建状态 new Person("张三") // managed 托管状态 Person person = manager.find(Person.class, 1); // 游离状体(脱管) // 删除状态 }

 

6)、删除数据

 

    @Test
    public void testdeleteQuery() {
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("jpatest");
        EntityManager manager = factory.createEntityManager();

// ====================方式一===================== manager.getTransaction().begin();
// Person实体的名称,o是别名,jpa中必须使用select p Query query = manager.createQuery("delete from Person p where p.id=?1"); query.setParameter(1, 1); query.executeUpdate(); manager.getTransaction().commit();
        // ====================方式二=====================
        manager.getTransaction().begin();
        Person person = manager.find(Person.class, 1);
        manager.remove(person);// 必须托管状态
        manager.getTransaction().commit();

        manager.close();
        factory.close();
    }   
上一篇:解决jetty7.0.pre5启动时报ClassNotFoundException: javax.interceptor.InvocationContext异常的问题


下一篇:CSS命名法