JPA基础(四):第一个JPA实例与JPA主键生成策略

写实体bean,映射的数据可以采用XML配置方式,也可以采用注解方式,在JPA中推荐大家用注解的方式,因为注解的方式开发应用效率是挺高的。

 

每个实体bean都要有个实体标识属性,这个实体标识属性主要用于在内存里面判断对象。通过@Id就可以定义实体标识。可以标识在属性的get方法前面,也可以标识在字段上面

 

如果我们希望采用数据库的id自增长的方式来生成主键值的话,这时候我们要用到一个注解@GeneratedValue,这注解里面有一些属性,其中一个是策略strategy,生成主键值的方案,JPA里没有Hibernate提供的那么多方案,它提供的方案有如下图:

  • AUTO: JPA自动选择合适的策略,是默认选项;
  • IDENTITY: 采用数据库ID自增长的方式来生成主键值,Oracle不支持这种方式;
  • SEQUENCE: 通过序列产生主键,通过@SequenceGenerator注解指定序列名,MySql不支持这种方式;
  • TABLE: 采用表生成方式来生成主键值,那怎么样生成呢?很简单,表里面通常有两个字段,第一个字段是给它一个名称(就是个列名而已),第二个字段专门用来累加用的,就是说每访问一次这个表,第二个字段就会累加1,不断累加。就是说你们要得到这个主键值的话,访问这个表,然后update这个表的这个字段,把它累加1之后,然后再把这个值取出来作为主键,再给他赋进去,表生成就是这样。TABLE表生成方式才是通用的,但是这种方式效率并不高。

Oracle数据库默认情况下,不能支持用id自增长方式来生成主键值;

mysql在默认情况下不能支持SEQUENCE序列的方式来生成主键值,所以我们一定要注意我们使用的数据库。

如果我们开发的应用,我们不可以预测用户到底使用哪种数据库,那么这个时候应该设为哪个值呢?答案是AUTO,就是说由持久化实现产品,来根据你使用的方言来决定它采用的主键值的生成方式,到底是IDENTITY?还是SEQUENCE?还是TABLE? 如果用的是mysql,那么它会用IDENTITY这种生成方式来生成主键值。


注意:如果我们把策略strategy设置成@GeneratedValue(strategy=GenerationType.AUTO)的话,AUTO本身就是策略的默认值,我们可以省略掉,就是说简单写成这样@GeneratedValue

实体bean开发完后,就要用持久化API对实体bean进行添删改查的操作,我们学习持久化API的时候,可以对照Hibernate来学习,接下来建立个单元测试,在开发的过程中,建议大家一定要用单元测试(junit可以用来进行单元测试)。

第一步写:persistence.xml(要求放在类路径的META-INF目录下),具体参照前两节

第二步写:Person.java (实体bean)

 1 import javax.persistence.Column;
2 import javax.persistence.Entity;
3 import javax.persistence.GeneratedValue;
4 import javax.persistence.Id;
5
6 @Entity
7 public class Person {
8 @Id
9 @GeneratedValue
10 private Integer id;
11 @Column(length=10,nullable=false,name="personname")
12 private String name;
13 public Person(){}
14 public Person(String name) {
15 this.name = name;
16 }
17 public Integer getId() {
18 return id;
19 }
20 public void setId(Integer id) {
21 this.id = id;
22 }
23 public String getName() {
24 return name;
25 }
26 public void setName(String name) {
27 this.name = name;
28 }
29 }

第三步:PersonTest.java (junit单元测试)

 1 import javax.persistence.EntityManager;
2 import javax.persistence.EntityManagerFactory;
3 import javax.persistence.Persistence;
4
5 import org.junit.BeforeClass;
6 import org.junit.Test;
7
8 import com.jim.entity.Person;
9
10 public class PersonTest {
11 @BeforeClass
12 public static void setUpBeforeClass() throws Exception {
13 }
14 @Test
15 public void save(){
16 EntityManagerFactory factory=Persistence.createEntityManagerFactory("sample");//形如sessionFactory
17 EntityManager em=factory.createEntityManager();
18 em.getTransaction().begin();
19 em.persist(new Person("jim"));
20 em.getTransaction().commit();
21 em.close();
22 factory.close();
23 }
24 }

关于session.save(obj);persist这方法在Hibernate里也存在,Hibernate的作者已经不太推荐大家用save方法,而是推荐大家用persist方法 。why? 首先并不是代码上的问题,主要是这个名字上的问题,因为我们把这个ORM技术叫做持久化产品,那么我们对某个对象持久化,应该叫持久化,而不应该叫保存,所以后来Hibernate的作者推荐用persist方法。

目前数据库表是不存在的,我们采取实体(领域)建模的思想,让它根据实体bean来生成数据库表,在persistence.xml里,<property name="hibernate.hbm2ddl.auto" value="update"/>,生成策略是update,就是说表不存在的时候,它会创建数据库表。问题是它什么时候创建表啊?创建表的时机是在什么时候创建的啊?答案是得到SessionFactory的时候,在JPA里也一样,是我们得到EntityManagerFactory的时候创建表


另外提一点,虽然JPA规范中暂时还没有UUID这种生成策略,但我们能使用Hibernate的注解来完成(虽然已经和Hibernate产生了耦合),代码如下所示:

1 @Entity
2
3 public class Order {
4 @Id
    @GenericGenerator(name="uuidpk",strategy="uuid")
5 @GeneratedValue(generator="uuidpk")
6 private String orderId;
7 ……
8 }

仅作参考

posted @ 2011-11-29 20:57  一直在等  阅读(4644)  评论(0编辑  收藏  举报