一. 介绍:

持久化是位于JDBC 之上的一个更高层抽象。持久层将对象映射到数据库,以便在查询、装载、更新,或删除对象的时候,无须使用像JDBC 那样繁琐的API。在EJB 的早期版本中,持久化是EJB 平台的一部分。从EJB 3.0开始,持久化已经自成规范,被称为Java Persistence API。Java Persistence API 定义了一种方法,可以将常规的普通Java 对象(有时被称作POJO)映射到数据库。这些普通Java 对象被称作entity bean

 

二.实例:

1.建persistence.xml:

一个实体Bean 应用由实体类和persistence.xml 文件组成。persistence.xml 文件在Jar 文件的META-INF 目录。persistence.xml 文件指定实体Bean 使用的数据源及EntityManager 对象的默认行为。persistence.xml 文件的配置说

明如下:

<persistence> 
   
<persistence-unit name="test"> 
   
<jta-data-source>java:/ MySqlDS</jta-data-source> 
   
<properties> 
   
<property name="hibernate.hbm2ddl.auto" value="create-drop"/> 
   
</properties> 
   
</persistence-unit> 
   
</persistence>

persistence-unit 节点可以有一个或多个,每个persistence-unit 节点定义了持久化内容名称、使用的数据源及持久化产品专有属性。name 属性定义持久化名称。jta-data-source 节点指定实体Bean 使用的数据源JNDI 名称,如果应用发布在jboss 下数据源名称必须带有java:/前缀,数据源名称大小写敏感。properties 节点用作指定持久化产品的各项属性,各个应用服务器使用的持久化产品都不一样如Jboss 使用Hibernate,weblogic10 使用Kodo,glassfish/sun application server/Oralce 使用Toplink。因为jboss 采用Hibernate,Hibernate 有一项属性hibernate.hbm2ddl.auto,该属性指定实体Bean 发布时是否同步数据库结构,如

果hibernate.hbm2ddl.auto 的值设为create-drop,在实体Bean 发布及卸载时将自动创建及删除相应数据库表(注意:Jboss 服务器启动或关闭时也会引发实体Bean 的发布及卸载)。

 

2.编写实体类

 

@SuppressWarnings("serial") 
   
@Entity 
   
@Table(name = "Person") 
   
public class Person implements Serializable { 
   
    private Integer personid; 
   
    private String name; 
   
    private boolean sex; 
   
    private Short age; 
   
    private Date birthday; 
   
    @Id 
   
    @GeneratedValue(strategy = GenerationType.AUTO) //主键自动生成方式 
    
    public Integer getPersonid() { 
   
        return personid; 
   
    } 
   
 
    public void setPersonid(Integer personid) { 
   
        this.personid = personid; 
   
    } 
   
 
    @Column(nullable = false, length = 32) 
   
    public String getName() { 
   
        return name; 
   
    } 
   
 
    public void setName(String name) { 
   
        this.name = name; 
   
    } 
   
 
    @Column(nullable = false) 
   
    public boolean getSex() { 
   
        return sex; 
   
    } 
   
 
    public void setSex(boolean sex) { 
   
        this.sex = sex; 
   
    } 
   
 
    @Column(nullable = false) 
   
    public Short getAge() { 
   
        return age; 
   
    } 
   
 
    public void setAge(Short age) { 
   
        this.age = age; 
   
    } 
   
 
    @Temporal(value = TemporalType.DATE)  
    //@Temporal 注释用来指定java.util.Date 或java.util.Calendar 属性与数据库类型date,time 或timestamp 中的那一种 
    
    //类型进行映射,DATE, //代表date 类型;TIME, //代表时间类型;TIMESTAMP //代表时间戳类型 
    
    public Date getBirthday() { 
   
        return birthday; 
   
    } 
   
 
    public void setBirthday(Date birthday) { 
   
        this.birthday = birthday; 
   
    } 
   
}

3.Session Bean 作为实体Bean的使用者

@Stateless 
   
@Remote(PersonDAO.class) 
   
public class PersonDAOBean implements PersonDAO { 
   
    @PersistenceContext 
   
    protected EntityManager em; 
   
    //EntityManager 是由EJB 容器自动地管理和配置的,不需要用户自己创建,他用作操作实体Bean。 
    
    //容器在实例化SessionBean后,就通过@PersistenceContext 注释动态注入EntityManager 对象。 
    
    public String getPersonNameByID(int personid) { 
   
        Person person = em.find(Person.class, Integer.valueOf(personid)); 
   
        return person.getName(); 
   
    } 
   
 
    public boolean insertPerson(String name, boolean sex, short age,Date birthday) { 
   
        try { 
   
            Person person = new Person(); 
   
            person.setName(name); 
   
            person.setSex(sex); 
   
            person.setAge(Short.valueOf(age)); 
   
            person.setBirthday(birthday); 
   
            em.persist(person); 
   
        } catch (Exception e) { 
   
            e.printStackTrace(); 
   
            return false; 
   
        } 
   
        return true; 
   
    } 
   
 
    public Person getPersonByID(int personid) { 
   
        return em.find(Person.class, personid); 
   
    } 
   
 
    public boolean updatePerson(Person person) { 
   
        try { 
   
            em.merge(person); 
   
        } catch (Exception e) { 
   
            e.printStackTrace(); 
   
            return false; 
   
        } 
   
        return true; 
   
    } 
   
 
    public List getPersonList() { 
   
        Query query = em.createQuery("from Person order by personid asc"); 
   
        List list = query.getResultList(); 
   
        return list; 
   
    } 
   
}

4.测试:

import com.dao.PersonDAO; 
   
public class PersonDAOTest extends TestCase { 
   
    private PersonDAO personDAO; 
   
    protected void setUp() throws Exception { 
   
        personDAO=(PersonDAO) EJBFactory.getEJB("PersonDAOBean/remote"); 
   
    } 
   
    public void testInsertPerson() throws ParseException, UnsupportedEncodingException{ 
   
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); 
   
        assertTrue(personDAO.insertPerson("测试", true, (short)26,formatter.parse(" 
     
    
      1980-9-30 
    ")));//添加一个 
    
    } 
   
    public void testGetPersonList(){ 
   
        assertEquals(4,personDAO.getPersonList().size()); 
   
    } 
   
}

5.其他注意点

@Transient 注释进行标注,则相应属性将不会被持久化成数据库字段

find()方法会返回null,而getReference()方法会抛出javax.persistence.EntityNotFoundException

getDelegate( )方法,你可以获取EntityManager 持久化实现者的引用,如Jboss EJB3 的持久化产品采用Hibernate

 

6.问题解决

a.问题:插入的中文为乱码

解决:1.数据库级设置:   create database `test` DEFAULT CHARSET=gbk

2.表级设置:   gbk
3. URL: jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=gbk

 

b.问题:java.lang.NoClassDefFoundError: antlr/RecognitionException

      at java.lang.Class.getDeclaredMethods0(Native Method)

      at java.lang.Class.privateGetDeclaredMethods(Unknown Source)

      at java.lang.Class.getDeclaredMethod(Unknown Source)

      at java.io.ObjectStreamClass.getPrivateMethod(Unknown Source)

      at java.io.ObjectStreamClass.access$1700(Unknown Source)