jpa eclipse搭建过程和注意事项

环境:Eclipse Jpa2.0 jdk1.7 tomcat7

 

1、在eclipse中 一个jpa项目

创建完成后,可以看到建好的项目

Persistence.xml是jpa项目的全局配置文件

 

2、添加项目需要的jar包

antlr-2.7.7.jar
dom4j-1.6.1.jar
ehcache-core-2.4.3.jar
hibernate-commons-annotations-4.0.2.Final.jar
hibernate-core-4.2.4.Final.jar
hibernate-ehcache-4.2.4.Final.jar
hibernate-entitymanager-4.2.4.Final.jar
hibernate-jpa-2.0-api-1.0.1.Final.jar
javassist-3.15.0-GA.jar
jboss-logging-3.1.0.GA.jar
jboss-transaction-api_1.1_spec-1.0.1.Final.jar
mysql-connector-java-5.1.7-bin.jar
ojdbc6.jar
slf4j-api-1.6.1.jar

这里添加了两个数据库的驱动包,不是必须的,根据自己连接的数据库来添加不同的驱动包

 

3、在src目录下创建bean目录,用于存放于数据库关联的实体类(本案例创建了三个实体类做演示,分别是:Account、Emp4、Dept6)

         实体类可以手动创建,也可以通过工具生成

         如果jpa项目,可以通过在项目右键,选择JPA Tools选项,里面可以反向生成实体类

右侧红线框中,第一个是根据实体构建表,下面那个是根据表构建实体类

         实体类注意事项:

如果单表操作无所谓,但是一旦涉及到多表操作,就会出现很多问题:

1)      数据类型要用Integer这种包装类型,不要用基本数据类型(不然会出现在数据库中生成关联对象列)

2)      所有注解不要放在属性上,要放在get方法上(不然也会出现在数据库中生成关联对象列)

3)      如果是自己新建的实体类,添加@Entity注解后,会出错,需要在persistence.xml中引用此类才行(引用方式在下面会的persistence.xml文件中会介绍);并且还要加上@ID注解,不然也会编译错误

 

4、配置persistence.xml,完整的xml配置如下:

         

<?xmlversion="1.0"encoding="UTF-8"?>
<persistenceversion="2.0"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/persistencehttp://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unitname="jpa_test1">
        <!--
        配置使用什么 ORM产品来作为 JPA的实现
        1. 实际上配置的是 javax.persistence.spi.PersistenceProvider接口的实现类
        2. 若 JPA项目中只有一个 JPA的实现产品,则也可以不配置该节点.
        -->
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
       
        <!-- 加入持久化类 -->
        <class>jpa_test1.Account</class>
        <class>jpa_test1.Emp4</class>
        <class>jpa_test1.Dept6</class>
       
        <!--
        配置二级缓存的策略(不是必须)
        ALL:所有的实体类都被缓存
        NONE:所有的实体类都不被缓存.
        ENABLE_SELECTIVE:标识 @Cacheable(true)注解的实体类将被缓存
        DISABLE_SELECTIVE:缓存除标识 @Cacheable(false)以外的所有实体类
        UNSPECIFIED:默认值,JPA产品默认值将被使用
        -->
        <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
       
        <properties>
            <!-- 连接数据库的基本信息 -->
            <propertyname="javax.persistence.jdbc.driver"value="oracle.jdbc.OracleDriver"/>
            <propertyname="javax.persistence.jdbc.url"value="jdbc:oracle:thin:@localhost:1521:orcl"/>
            <propertyname="javax.persistence.jdbc.user"value="scott"/>
            <propertyname="javax.persistence.jdbc.password"value="tiger"/>
           
            <!-- 配置 JPA实现产品的基本属性.配置 hibernate的基本属性(不是必须) -->
            <propertyname="hibernate.format_sql"value="true"/>
            <propertyname="hibernate.show_sql"value="true"/>
            <propertyname="hibernate.hbm2ddl.auto"value="update"/>
           
            <!-- 二级缓存相关(不是必须) -->
            <propertyname="hibernate.cache.use_second_level_cache"value="true"/>
            <propertyname="hibernate.cache.region.factory_class"value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/>
            <propertyname="hibernate.cache.use_query_cache"value="true"/>
        </properties>
    </persistence-unit>
</persistence>

 

5、创建一个test包,包中创建一个测试类,测试单表操作,代码如下:

public class MyTest {
 
    public static void main(String[] args) {
        String pname="jpa_test1";
       
        //1、EntityManagerFactory相当于hibernate的sessionFactory
        //有两种创建方法,第一种是直接传到persistence.xml中persistence-unit标签的名称
        EntityManagerFactory facotry=Persistence.createEntityManagerFactory(pname);
       
        //另一种是不管可以传递名字,还可以传递一些参数,如下面show_sql的参数来设置连接的配置
        /*Map map=new HashMap();
        map.put("hibernate.show_sql", false);
        EntityManagerFactory facotry=Persistence.createEntityManagerFactory(pname);*/
       
        //2、EntityManager相当于hibernate的session
        EntityManager manager=facotry.createEntityManager();
       
        //3、开启事务
        EntityTransaction tran=manager.getTransaction();
        tran.begin();
       
        //4、进行持久化操作
        //插入,相当于hibernate的save(和hibernate的 save方法的不同之处:若对象有 id, 则不能执行 insert操作,而会抛出异常. )
        /*Account acc=newAccount();
        acc.setUsername("jpatest1");
        acc.setPassword("123");
       
        manager.persist(acc);
        //保存完后可以获取保存成功的ID
        System.out.println(acc.getAid());
        */
       
        //find查询,相当于hibernate的get方法
        /*Account acc=manager.find(Account.class,1);
        System.out.println(acc.getUsername());*/
       
        //getReference,相当于hibernate的load方法(getReference只有使用查询出来的对象才会发送SQL,而get执行查询就立即发送SQL查询)
        Account acc=manager.getReference(Account.class, 1);
        System.out.println(acc.getUsername());
       
        //5、提交事务
        tran.commit();
       
        //6、关闭EntityManager
        manager.close();
       
        //7、关闭EntityManagerFactory
        facotry.close();
    }
}


 

-------------到此为止单表的jpa操作完毕------------

6、单向多对一

   1) 在Emp6中,新建一个private Dept6 dept; 并且提供get/set和注解,配置如下:

@ManyToOne(fetch=FetchType.EAGER)
       @JoinColumn(name="deptid")
       publicDept6 getDept() {
              returndept;
       }
 
       publicvoid setDept(Dept6 dept) {
              this.dept= dept;
       }


2) 在测试类中进行测试

             

 Dept6 dept=new Dept6();
        dept.setDeptname("jpa1");
        dept.setLoc("1111");
       
        Emp4 emp1=newEmp4();
        emp1.setEname("11");
        emp1.setDept(dept);
       
        Emp4 emp2=new Emp4();
        emp2.setEname("222");
        emp2.setDept(dept);
       
        manager.persist(dept);//先保存一方(如果数据库已经有一方数据,需要做多对一的添加,也可以直接创建一个部门对象,设置一个id值,不一定非要先保存dept,才能让员工获得一方dept对象,比如可以像横线下面那段代码写法)
        manager.persist(emp1);//再保存多方
    manager.persist(emp2);
 
Dept6 dept=new Dept6();
        dept.setId(5650);
       
        Emp4 emp1=new Emp4();
        emp1.setEname("11");
        emp1.setDept(dept);
       
        Emp4 emp2=new Emp4();
        emp2.setEname("222");
        emp2.setDept(dept);
       
        manager.persist(emp1);
    manager.persist(emp2);

 

6、单向一对多

   1) 在Dept6中,添加如下集合,存放关联的员工:

private Set<Emp4> emps=new HashSet<Emp4>();
并生成get/set和注解,配置如下:
//注意: 若在 1 的一端的 @OneToMany 中使用 mappedBy 属性, 则 @OneToMany 端就不能再使用 @JoinColumn 属性了.
@OneToMany(fetch=FetchType.LAZY,cascade=CascadeType.ALL)
        @JoinColumn(name="deptid")
        public Set<Emp4>getEmps() {
            returnemps;
        }
 
        public voidsetEmps(Set<Emp4> emps) {
            this.emps =emps;
}
      注意: 定义的set集合需要new,并且需要指定泛型


 

2) 在测试类中进行测试,代码如下:

                  

 Dept6 dept=new Dept6();
        dept.setDeptname("xxx");
       
        Emp4 emp1=new Emp4();
        emp1.setEname("11");
       
        Emp4 emp2=new Emp4();
        emp2.setEname("222");
       
        dept.getEmps().add(emp1);
        dept.getEmps().add(emp2);
       
    manager.persist(dept);

 

6、JPQL查询

   1) 基础jpql

String jpql = "FROM Customer c WHERE c.age > ?";
        Query query= entityManager.createQuery(jpql);
       
        //占位符的索引是从 1 开始
        query.setParameter(1,1);
        List<Customer>customers = query.getResultList();
        System.out.println(customers.size());


 

2) 如果只想查询部分列,那么集合将会存放数组

如果查询部分列,不想集合存放数组,那么需要给实体提供一个对应的构造函数,并如下查询:

Stringjpql = "SELECT new Customer(c.lastName, c.age) FROM Customer c WHERE c.id> ?";
        List result=
entityManager.createQuery(jpql).setParameter(1, 1).getResultList();
       
        System.out.println(result);


 

3)  也可以通过createNamedQuery查询实体类中已经写好的jpql

@NamedQuery(name="testNamedQuery", query="FROM Customer cWHERE c.id = ?")//这里eclipse可能会显示错误,但是不影响运行,也可以写成select c FROM Customer c WHERE c.id = ?
@Table(name="JPA_CUTOMERS")
@Entity
publicclass Customer {
 
Queryquery =
entityManager.createNamedQuery("testNamedQuery").setParameter(1,3);
    Customercustomer = (Customer) query.getSingleResult();
       
    System.out.println(customer);


 

4)  也可以使用sql语句查询:

String sql = "SELECT age FROM jpa_cutomers WHERE id = ?";
        Query query= entityManager.createNativeQuery(sql).setParameter(1, 3);
       
        Objectresult = query.getSingleResult();
        System.out.println(result);


 

5)  使用 hibernate 的查询缓存

在每次查询后面跟上.setHint(QueryHints.HINT_CACHEABLE, true);

如:

第一次查询:Query query =

entityManager.createQuery(jpql)

.setHint(QueryHints.HINT_CACHEABLE, true);

第二次查询:query =

entityManager.createQuery(jpql)

.setHint(QueryHints.HINT_CACHEABLE, true);

 

6)  查询时也可以使用OrderBy、GroupBy、关联查询、子查询,如:

OrderBy:

String jpql = "FROM Customer c WHERE c.age > ? ORDER BY c.ageDESC";

GroupBy:

String jpql = "SELECT o.customer FROM Order o "

                +"GROUP BY o.customer "

                +"HAVING count(o.id) >= 2";

关联查询:

Stringjpql = "FROM Customer c LEFT OUTER JOIN FETCH c.orders WHERE c.id = ?";

子查询:

String jpql = "SELECT o FROM Order o "

+ "WHERE o.customer = (SELECT c FROM Customer c WHERE c.lastName =?)";

7)  使用 jpql 自带的函数

String jpql = "SELECT lower(c.email) FROM Customer c";

 

8)  可以使用 JPQL 完成 UPDATE 和 DELETE 操作

String jpql = "UPDATE Customer c SET c.lastName = ? WHERE c.id =?";

  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值