JPA
配置文件:persistence.xml,定义与数据库连接相关的数据源、持久化实现、事务属性等内容。
<persistence-unit name=”JPADemoPU” transaction-type=”JTA”>...</persistence-unit>
Entity:JPA操作的基本单元,采用注解@Entity、@Id、@GeneratedValue(strategy = GenerationType.IDENTITY)等。
EntityManager:
@PersistenceContext(unitName = “MyJPADemoPU”)
private EntityManager em;
@Resource
private UserTransaction utx;
...
utx.begin();
em.persist(person);
utx.commit();
3.ORM
(1)Entity
@Entity @ID @Table(name=”customer”)
(2)主键
@GenerateValue Table(表生成主键) Sequence(数据库机制) Identity(自动增长列) Auto四种策略
(3)复合主键
主键类用@Embeddable注解,重写equals(),hashCode(),实现Serializable接口,@EmbeddedId
@WebServlet(name=”CreateOrderServlet”, urlPattern{“/CreateOrderServlet”})
...
@PersistenceContext(unnitName=”MyJPADemoPU”)
private EntityManager em;
@Resource
private javax.transaction.UserTransaction utx;
...
MyOrder temp = em.find(MyOrder.class, oid);
...
(4)属性
@Column: name unique nullable insertable updateable length precision scale
@Temporal 如果使用java.util包中的时间日期类型,必须额外标注@Temporal注解来说明转化成java.sql包中的哪种类型
@Transient 标识不需要持久化的属性
@Lob char[]、Character[]映射为CLOB,byte[]、Byte[]映射为Blob,通常使用惰性加载方式,与@Basic(fetch=FetchType.LAZY)同时使用
@ElementCollection 将集合属性映射到一个单独的子表中,CollectionTable(name=”Tag”),@Column(name=”Value”),@OrderColumn、@MapKeyColumn
@Enumerated 可以持久化名称或值,枚举类型默认为int,可以用@Enumerated(EnumType.STRING)
(5)关联映射
一对一:
cascade:CascadeType.PERSIST, CascadeType.MERGE, CascadeType.Remove, CascadeType.refresh
fetch:EAGER, LAZY
optional:true
单向关联:
@Entity
...Customer {
@OneToOne(fetch=FetchType.LAZY, optional=true)
private Address address;
...
}
双向关联:
@Entity
...Discoount {
@OneToOne(mappedBy=”discount”)
Customer cid;
private Address address;
...
}
一对多:
@OneToMany
@JoinColumn(name=”customer_id”)
Private List<CUstomerOrder> orders;
多对一:
@ManyToOne
private Customer customerid;
...
@OneToMany(mappedBy=”customerid”)
Private List<CustomerOrder> orders;
多对多:
可以使用@ManyToMany
(6)加载方式
EGER:主动加载
LAZY:被动加载
(7)顺序
@OrderBy(“name DESC”)
Private List<Subject> subjects;
(8)继承映射
Single-table 父类和子类新添加的属性映射到一张数据库表
Joined-subclass 子Entity不含有从根Entity继承来的属性,通过共享主键关联
Table-per-concrete-class 每一个Entity映射到一个单独的表,含有继承来的属性
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
4.Entity管理
(1)获取EntityManager
同8.2节,通过@PersistContext注解找到配置文件,声明EntityManager实例
(2)持久化上下文
EM对E的任何操作都是首先保存到持久化上下文,最后才更新到数据库
有两种类型,事务范围的和扩展范围的
操作Entity之前如果没有事务范围的上下文会要求创建否则抛出异常,事务提交时Entity同步到数据库,上下文销毁
扩展范围的上下文应用在有状态会话Bean中,移除Bean时,Entity同步到数据库,上下文销毁
(3)Entity操作
新增:utx.persist(c)
查询:em.find(Address.class, 2L)或em.getReference(Address.class, 2L),区别find返回null,getReference抛异常,另外getReference不保证Entity已被初始化
修改:c.setName(“hyl”),在事务中同一个id只存在一个实例,不使用事务find会获得新的实例
c=em.find...
c.setName(“Peter”);
utx.begin();
em.flush();
c2=em.find...
c2.getName();
utx.commit();//属性没有修改,因为begin新开事务,flush清空了之前的上下文,将修改放在事务中即可
除了将修改放在事务中,还可以在begin和flush之间em.merge(c)将detached状态的c加入到新的持久化上下文
删除:em.remove(c)
EM还有一些有用的方法如refresh,clear,contains,detach
EM管理下的E有四种状态:New,Managed,Detached,Removed
(4)级联操作
cascade属性包含PERSIST,MERGE,REMOVE,REFRESH,DETACH,ALL关联主体进行操作时,关联的另一端做相应的操作
5.JPQL
与SQL语法一致,区别是JPQL操作的是抽象的持久化模型,包括Entity,属性,关联等。
(1)动态查询:
Em.createQuery(“SELECT c FROM Customer c”)
query.getResultList()或query.getSingleResult返回第一个Entity
query可以是TypedQuery<Customer>得到的是类型安全的
(2)参数设置
命名参数:...where c.id=:Id;query.setParameter(“Id”, new Integer(1))
位置参数:...where c.id=?1;query.setParameter(1, new Integer(1))
(3)命名查询
@Entity
@NamedQueries({
@NamedQuery(name=..., query=...),
@NamedQuery(name=..., query=...)
})
...
em.createNamedQuery(“(name)”);
(4)属性查询
查询不是整个Entity提高性能
Iterator iterator = Result.iterator();
Object[] row = iterator.next();
row[1],row[2]...c.id,c.Name
(5)使用构造器
“select new com.jpa.demo.SimpleCustomer(c.id, c.Name) from ...”
6.本地查询
@Entity
@NamedNativeQuery(name=”findAll”, query=”select * from t_customer”)//返回的是Customer集合
@Table(name=”t_customer”)
7.基于Criteria API的安全查询
针对查询字符串中存在语法错误
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Customer> query = builder.createQuery(Customer.class);
Root<Customer> c = query.from(Customer.class);
Query.select(c).where(builder.equal(c.get(“Name”),”zx”));
TypedQuery<Customer> typedQuery = em.createQuery(query);
...
Criteria API要求每个Entity生成一个原模型类,一般由开发工具自动生成,可以防止参数值拼写错误与Entity属性不一致
...
@Generated(value...
@StaticMetamodel(Customer.class)
public class Customer_{
Public static volatile SingularAttribute<Customer, Long> id;
...
}
Query.select(c).where(builder.greaterThan(c.get(Customer_.id),100L));
8.生命周期回调方法
@PreUpdate @PostUpdate @PreRemove @PostRemove @PostLoad
9.校验框架
支持Bean Validation API,@Pattern(regexp=..., message=”{invalid.email}”)