今天继续学习jpa,黎老师准备了对jpa重点的部分学习的很多例子程序,对实体bean持久化建模的思想,持久化实体bean中各种类型的属性要用到的注解,对实体bean进行增,删,改,查操作以及jpql语言的使用。敲了一遍例子代码,基本掌握了jpa的使用,再学新项目也把它整合进去。
两种建模思想,
1先建表,后再根据表来编写配置文件和实体bean,使用这种方案的开发人员受到了传统数据库建模的影响。现在很流行的。
2先编写配置文件和实体bean,然后再生成表,使用这种方案的开发人员采用的是领域建模思想,这种实现相对的更加的面向对象。 这种思想的使用会越来越多。
实体bean的创建。
以javax开头的都是sun的一些规范,下面是javax.Persistence.*中实体bean中要使用的比较重要的注解。
@Entity注解实体bean
@Id 指定实体的标识属性 ,要标注在属性的getter方法上面,也可以标在字段上
@GenrateValue (strategy=GenerationType.)主键的生成方式,不再细究了。
Oracle默认不支持identity mysql默认不支持sequence方式生成主键值,
Table通用,效率不高。可以设置为auto 由hibernate根据方言来决定主键的生成方式。它也是默认值
jpa和hibernate对实体bean进行增删改查
//先获得实体管理工厂 itcast 为实体持久化单元的名称
EntityManagerFactory factory=Persistence.createEntityManagerFactory("itcast");
//创建实体管理器,内部操纵hibernate的Session对象
EntityManager em=factory.createEntityManager();
//开始事务
em.getTransaction().begin();
//对实体对象持久化,不推荐使用save方法
em.persist(new Person("李四"));//这里添加的实体bean的构造函数,要再添一个无参数的默认构造函数,对象的创建是由hibernate内部通过反射技术来实现的,反射技术必须要使用实体bean的一个无参数的构造函数
//提交事务
em.getTransaction().commit();
//关闭实体管理器
em.close();
//关闭工厂
factory.close();
如果生成不了表,可能是映射文件配置错误
生成的表默认情况下根据实体bean的名称来命名,字段的名称默认采用实体bean属性的名称。
字段设置太长,占用数据库的存储空间,可以使用在属性的getter方法上添加注解注解配置要生成表中字段的长度,并设置是否可以为空
@Column(length=20,nullable=false)
也可以设置该注解的name属性修改表中字段的名称
@Table(name="xxx") 设置要生成表的名字
@Temporal(TemporalType.DATE)设置日期的类型,yyyy-MM-dd
枚举类型的属性添加的注解
@Enumerated(EnumType.STRING) @Column(length=6,nullable=false)
字段的长度默认255,对于大文本类型的属性是不能满足需要的,可以用注解@Lob表示属性是大文本类型,在mysql中是longtext类型。也可以在字节数组类型的属性上标注这个注解,映射为mysql中的longblob类型
@Transient 属性不与数据库表做映射,数据库中不生成相应的字段。
如果数据太大,而我们又不访问这个属性,可以使用注解
@Basic(fetch=FetchType.LAZY),延迟初始化,在初次创建实体对象时,就不会把数据从数据库加载到内存,事务必须是打开的,不然就出现异常。
这些是实际工作中经常用到几个类型的属性和他们的注解
对实体bean进行增,删,改,查操作以及jpql语言的使用
获取实体bean 使用实体管理器的find方法,类似于hibernate中的get方法,
//第一个参数是实体类,第二是实体标识符属性的值
//不需要类型转换,不需要开事务,有更改数据的动作才开事务。
Person person=em.find(Person.class, 1);
还有一个getReference方法类似于hibernate中的load方法,延迟初始化,不会立刻立刻从数据库里得到这个记录,只是返回一个代理对象,当我们对代理对象的属性访问的时候,才会得到这个数据。如果得不到实体,getReference方法执行是不会抛出异常,只有在访问实体的属性的时候才会抛出异常
Person person=em.getReference(Person.class, 1);
//没有下面这句代码,就不访问数据库,没有数据加载行为
System.out.println(person.getName());
修改实体
关联事务 实体状态,1new 新建 2 managed 托管 3 游离 4删除
对象托管时 就可以调用他属性的setter方法 更新数据,同步回数据库,不用在调用实体管理器的其他方法。
还有一种方法,先把实体变成游离状态,即不与事务相关联,再更改他。
//把实体bean变成游离对象
em.clear();
person.setName("zhangs");
//修改
em.merge(person);
删除
实体在托管状态下,可以调用EntityManager的remove()方法删除这个实体。
jpql查询语句
@Test //删除
public void deletequery(){
EntityManagerFactory factory=Persistence.createEntityManagerFactory("itcast");
EntityManager em=factory.createEntityManager();
Query query=em.createQuery("delete from Person o where o.id=?1");
query.setParameter(1, 1);
em.getTransaction().begin();
query.executeUpdate();
em.getTransaction().commit();
em.close();
factory.close();
}
@Test //更新
public void updatequery(){
EntityManagerFactory factory=Persistence.createEntityManagerFactory("itcast");
EntityManager em=factory.createEntityManager();
Query query=em.createQuery("update Person o set o.name=:name where o.id=:id");