EJB3学习笔记_JPA

<p>1、简介:EJB 过去用EntityBean,在EJB3后不推荐使用,而是用JPA代替。</p>
<p></p>
<p>2、JPA简介</p>
<ul>
<li>对流行的ORM框架做了抽象,做到更一般化,抽象了各框架中的交叉部分,所以没有特定框架来得强大</li>
<li>JPA不提供实现,委托具体产品实现</li>
</ul>
<p>3、规范</p>
<p></p>
<p>配置persistence.xml,放在META-INF下</p>
<p></p>
<p>注:在eclipse中定义xsd: Preferences - Files and Edite - XML - XML Category - add - Location(找到xsd) - key 上也配置斜杠后的名称与Location一致。</p>
<p>这样就省去了xml头的声明,也无需一直连接网络,创建的时候由Schema中创建,选中对应的xsd。</p>
<p></p>
<p><span style="color: #0000ff;">关于数据库:</span></p>
<ul>
<li><span style="color: #0000ff;">过去单一应用时,我们使用配置文件设定数据库url,name等直接访问数据库</span></li>
<li><span style="color: #0000ff;">现在在容器中,应该让容器去连接数据库,然后给我们数据源(ds)</span></li>
</ul>
<p><span style="color: #0000ff;">注意:在jboss中连接数据库,就是将数据库驱动jar 和 数据库连接的xml文件 都放到deploy中, 然后通过JNDI去访问这个DS。</span></p>
<p><span style="color: #0000ff;"></span></p>
<p><span style="color: #0000ff;">然后在persistence.xml中 添加 &lt;jta-data-source&gt;java:DerbyDS&lt;/jta-data-source&gt; &lt;!--这里就是JNDI名字--&gt;</span></p>
<p></p>
<p><textarea cols="106" rows="15" name="code" class="xhtml:collapse">&lt;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" version="1.0"&gt;
  &lt;persistence-unit name="clat" transaction-type="RESOURCE_LOCAL"&gt;&lt;!--持久化单元clat--&gt;
  &lt;!-- name实体化单元名  transaction-type事务类型 RESOURCE_LOCAL本地事务 JTA全局事务类型,使用容器提供的事务服务--&gt;
  &lt;provider&gt;org.hibernate.ejb.HibernatePersistence&lt;/provider&gt;
        &lt;!--&lt;jta-data-source&gt;java:DerbyDS&lt;/jta-data-source&gt; 如果由容器得到ds ,事务类型选择JTA--&gt;
    &lt;properties&gt;
      &lt;property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect"/&gt;
      &lt;property name="hibernate.connection.driver_class" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/&gt;
      &lt;property name="hibernate.connection.username" value="chat"/&gt;
      &lt;property name="hibernate.connection.password" value="123456"/&gt;
      &lt;property name="hibernate.connection.url" value="jdbc:sqlserver://localhost:1433;databaseName=chatroom"/&gt;
      &lt;property name="hibernate.hbm2ddl.auto" value="update"/&gt;
      &lt;property name="hibernate.show_sql" value="true"/&gt;
    &lt;/properties&gt;
  &lt;/persistence-unit&gt;
&lt;/persistence&gt;</textarea></p>
<p></p>
<p></p>
<p>4、实体的生命周期图</p>
<ul>
<li>new 内存中新建</li>
<li>persist 内存持久化到数据库</li>
<li>refresh 数据库数据同步到内存中 DB -&gt; object</li>
<li>remove 删除受管状态的实体对应的表,实体还在</li>
<li>clear 所有受管的实体都会处于分离状态,脱离上下文</li>
<li>close 收回资源,entityManager就不可用了</li>
<li>merge 对分离对象调用,根据实体ID更新,并实体再次进入受管状态。如果该ID不存在,会抛异常。</li>
</ul>
<p>其他一些方法</p>
<ul>
<li>
<span style="color: #000000;">contains </span>判断对象是否处于受管状态</li>
<li>flush 实体向数据库同步 , object -&gt; DB , 虽然将数据写到表中,但事务并未提交,所以还可能被回滚。</li>
<li>setFlushMode()/getFlushMode() 刷新模式,AUTO/COMMIT</li>
</ul>
<p><img src="http://hi.csdn.net/attachment/201005/5/0_1273064716lZ0L.gif" alt="" width="455" height="294"></p>
<p></p>
<p></p>
<p>5、生命周期中对应回调函数的注释(annotations)(apply for entity class methods or in listener class)</p>
<p> 对应 增删改查</p>
<ul>
<li>PrePersist</li>
<li>PostPersist</li>
<li>PreRemove</li>
<li>PostRemove</li>
<li>PreUpdate</li>
<li>PostUpdate</li>
<li>PostLoad</li>
</ul>
<p>创建 监听器</p>
<p><textarea cols="74" rows="15" name="code" class="java">package entity;
import static java.lang.System.out;
import javax.persistence.*;

public class AccountListener{
  @PrePersist
  public void prePersist(Account a){out.prinltn("PrePersist:"+ a)};
  @PostPersist
  public void postPersist(Account a){out.prinltn("PostPersist:"+ a)};
  @PreUpdate
  public void preUpdata(Account a){out.prinltn("Preupdate:"+ a)};
  @PostUpdate
  public void postUpdate(Account a){out.prinltn("PostUpdate:"+ a)};
  @PostLoad
  public void postLoad(Account a){out.prinltn("PostLoad:"+ a)};
}</textarea></p>
<p>然后注册监听器,绑定到实体上</p>
<p><textarea cols="73" rows="15" name="code" class="java">package entity;
import java.io.Serializable;
import javax.persistence.*;

@Entity
@EntityListeners(AccountListener.class)
public class Account implements Serializable{
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long accountno;
  private String name;
...
}</textarea></p>
<p></p>
<p>6、并发控制逻辑</p>
<p></p>
<p>JPA提供的支持:<span style="color: #ff0000;">乐观锁</span> 和 <span style="color: #ff0000;">显示的读和写锁</span></p>
<p></p>
<p>乐观锁:不对表中记录加任务实际的锁,是假设没有其他人会并发修改记录,如果发现被修改了就抛异常,<span style="color: #ff0000;">避免不可重读</span></p>
<p>实现机制是:使用标记了<span style="color: #ff0000;">@Version</span>的属性(该属性只能是int,Inter,short,long,Long,Timestamp)是否变更异常做判断。</p>
<p></p>
<p>显示的读和写锁:显示得告知数据库应该提供锁</p>
<p>EntityManager.lock(Object entity, LockModeType lockMode) //模式类型有 READ 和 WRITE</p>
<p>EJB规范中指出 此类锁支持提供<span style="color: #ff0000;">@Version</span>属性的实体,但并不强制。</p>
<p></p>
<p><span style="color: #ff0000;">读锁(READ):</span> 可以避免脏读和不可重读。</p>
<p><span style="color: #ff0000;">写锁(WRITE):</span>在读锁基础上,对数据的更新会 使Version属性+1,如果Version值不对就抛出异常。</p>
<p></p>
<p></p>
<p></p>
<p>7、查询方法</p>
<ul>
<li>EntityManager.find() 根据主键查询</li>
<li>EntityManager.createQuery() 使用ejb的 查询语言(类似HQL这种)</li>
<li>EntityManager.createNativeQuery(String sql,Class clazz) 使用SQL查询</li>
<li>EntityManager.createNamedQuery()命名查询,如果在一个类中多次使用了一个查询语句,可以给这个语句一个名字,然后调用,<span style="color: #ff0000;">只能定义在实体类上</span>
</li>
</ul>
<p><textarea cols="72" rows="11" name="code" class="java:collapse">@Entity
@EntityListener(AcdountListener.class)
@NamedQuery(name="findAll",query="select object(a) from Account a")
public class Account implements Serializable{
  @Version
  private int version;
  @Id
  @GernerateValue(strategy = GenerationType.AUTO)
  private long accountno;
  ...
}</textarea></p>
<p></p>
<p>Query对象:相当于查询语句,用于(添加参数,比如从第几条开始,查几条等)调用方法,返回结果。(具体查API)</p>
<p></p>

你可能感兴趣的:(学习笔记)