Elicpse中搭建SpringData+jpa

框架 专栏收录该内容
19 篇文章 0 订阅

Elicpse中搭建SpringData+jpa

Spring Data JPA是在Spring JPA的基础上,对持久层做了简化。用户只需声明持久层的接口,不需要实现该接口。Spring Data JPA内部会根据不同的策略、通过不同的方法创建Query操作数据库

首选先附上整个案例的工程结构图

jpa_springData_test1
src
com.lhc.bean
Dept6.java
com.lhc.dao
DeptDao3.java
DeptDao3Impl.java
IDeptDao.java
IDeptDao2.java
MyRepository.java
com.lhc.service
DeptServiceImpl.java
IDeptService.java
com.lhc.test
SsspTest.java

applicationContext.xml
db.properties
WebContent
META-INF
MANIFEST.MF
WEB-INF
lib(lib中的jar包,在后面会讲到)
web.xml(web.xml中没有写什么配置内容,因为本案例主要是在text测试类中演示,如果做页面请求交互,可以配置springmvc+spring监听器)

 

1、  在eclipse中新建web工程

2、  项目右键,add library,选择ServerRuntime,添加服务器运行环境 

3、  添加jar包

antlr-2.7.7.jar

c3p0-0.9.2.1.jar

com.springsource.net.sf.cglib-2.2.0.jar

com.springsource.org.aopalliance-1.0.0.jar

com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

commons-logging-1.1.3.jar

dom4j-1.6.1.jar

hibernate-c3p0-4.2.4.Final.jar

hibernate-commons-annotations-4.0.2.Final.jar

hibernate-core-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

log4j-1.2.14.jar

mchange-commons-java-0.2.3.4.jar

mysql-connector-java-5.1.7-bin.jar

ojdbc6.jar

slf4j-api-1.5.8.jar

slf4j-log4j12-1.5.8.jar

spring-aop-4.0.0.RELEASE.jar

spring-aspects-4.0.0.RELEASE.jar

spring-beans-4.0.0.RELEASE.jar

spring-context-4.0.0.RELEASE.jar

spring-core-4.0.0.RELEASE.jar

spring-data-commons-1.5.0.release.jar

spring-data-jpa-1.3.0.release.jar

spring-expression-4.0.0.RELEASE.jar

spring-jdbc-4.0.0.RELEASE.jar

spring-orm-4.0.0.RELEASE.jar

spring-tx-4.0.0.RELEASE.jar

spring-web-4.0.0.RELEASE.jar

spring-webmvc-4.0.0.RELEASE.jar

 

4、  创建实体类 

package com.lhc.bean;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table
public class Dept6 {

	private int id;
	
	private String deptName;
	
	private String loc;

	@Id
	@GeneratedValue
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getDeptName() {
		return deptName;
	}

	public void setDeptName(String deptName) {
		this.deptName = deptName;
	}

	public String getLoc() {
		return loc;
	}

	public void setLoc(String loc) {
		this.loc = loc;
	}
	
	
}

5、  创建一个dao接口,接口需继承Repository,如:

//这里继承接口后,必须告诉它是对哪个实体类进行持久化操作,并且这个实体类的主键的类型是什么
public interface IDeptDao extends Repository<Dept6, Integer> {
           //因为当前dao继承的是Repository,Repository是SpringData的核心接口,它并不提供任何方法,所以用户需要自己定义需要的方法,并且这些方法名称必须遵循一定的规则,比如保存用save,ID查询用findById,具体其他定义规则,请参考http://shensuqiao.iteye.com/blog/2096114中的说明。
           //这个dao接口不需要有实现类,因为使用了springData,springData就是为了简化dao层,不需要写dao接口的实现类
           //如果这个类继承的是CrudRepository(继承Repository,提供增删改查方法)或者PagingAndSortingRepository(继承CrudRepository,增加了分页查询和排序两个方法)或者JpaRepository(继承PagingAndSortingRepository,是针对JPA技术的接口,提供flush(),saveAndFlush(),deleteInBatch()等方法)接口,那么dao中没有特殊的需求,可以不用写方法定义,直接可以调用继承接口中已经定义好的方法
public void save(Dept6 dept);
}


 

6、  创建service接口和service实现类

public interface IDeptService {
public void save(Dept6 dept);
}


 

@Service  //标明当前是一个service层
public class DeptServiceImpl implements IDeptService {
 
         @Autowired  //自定注入dao实例
                  private IDeptDao deptDao;
 
@Transactional  //添加事务控制
         public void save(Dept6 dept) {
                    //TODO Auto-generated method stub
                    deptDao.save(dept);
                  }
}


 

7、  src下创建一个db.properties文件(文件名可以更改,但是需要是一个properties文件),这里配置连接数据库的信息,本案例连接的是oracle,根据自己连接的数据库配置下面的属性值,内容如下:

jdbc.user=scott
jdbc.password=tiger
jdbc.driverClass=oracle.jdbc.OracleDriver
jdbc.jdbcUrl=jdbc:oracle:thin:@localhost:1521:orcl


 

8、  src下创建一个applicationContext.xml并进行配置,具体配置内容如下:

<?xml version="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:tx="http://www.springframework.org/schema/tx"
   xmlns:jpa="http://www.springframework.org/schema/data/jpa"
   xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/data/jpahttp://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
            http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-4.0.xsd
            http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.0.xsd">
 
   <!—自动扫描,为这个包下面带有@Service等这些注解的类创建实例,在遇到@Autowired时进行自动注入-->
   <context:component-scanbase-package="com.lhc"></context:component-scan>
  
<!—加载properties资源文件 --> 
<context:property-placeholderlocation="classpath:db.properties"/>
 
   <!—配置数据源 -->   
   <beanid="dataSource"
            class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <propertyname="user" value="${jdbc.user}"></property>
            <propertyname="password" value="${jdbc.password}"></property>
            <propertyname="driverClass"value="${jdbc.driverClass}"></property>
            <propertyname="jdbcUrl" value="${jdbc.jdbcUrl}"></property>        
   </bean>
  
   <!--配置 EntityManagerFactory -->
   <beanid="entityManagerFactory"
            class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <propertyname="dataSource" ref="dataSource"></property>
            <!--配置 JPA 提供商的适配器. 可以通过内部 bean 的方式来配置 -->
            <propertyname="jpaVendorAdapter">
                     <beanclass="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"></bean>
            </property>        
            <!--配置实体类所在的包 -->
            <propertyname="packagesToScan"value="com.lhc.bean"></property>
            <!--配置 JPA 的基本属性. 例如 JPA 实现产品的属性 -->
            <propertyname="jpaProperties">
                     <props>
                               <propkey="hibernate.show_sql">true</prop>
                               <propkey="hibernate.format_sql">true</prop>
                               <propkey="hibernate.hbm2ddl.auto">update</prop>
                     </props>
            </property>
   </bean>
  
   <!--配置 JPA 使用的事务管理器 -->
   <beanid="transactionManager"
            class="org.springframework.orm.jpa.JpaTransactionManager">
            <propertyname="entityManagerFactory"ref="entityManagerFactory"></property>   
   </bean>
  
   <!--配置支持基于注解是事务配置 -->
   <tx:annotation-driventransaction-manager="transactionManager"/>
  
   <!--让 Spring 为Dao声明的接口创建代理对象, Spring 初始化容器时将会扫描 base-package 指定的包目录及其子目录,
            为继承 Repository或其子接口的接口创建代理对象 -->
   <!--transaction-manager-ref和query-lookup-strategy应该也可以不写 -->
   <jpa:repositoriesbase-package="com.lhc.dao"
           entity-manager-factory-ref="entityManagerFactory"
          transaction-manager-ref="transactionManager"query-lookup-strategy="create-if-not-found"/>
</beans>


 

9、  新建测试包,和测试内

public class SsspTest {
 
         /**
          * 添加
          */
         public void test1() {
                   ApplicationContextctx =
newClassPathXmlApplicationContext("applicationContext.xml");
                   //下面两种方法,得到一个service的实例对象
         //      IDeptServlet deptService = (IDeptServlet)ctx.getBean("deptService");
                   IDeptServicedeptService = ctx.getBean(IDeptService.class);
                   Dept6dept1=new Dept6();
                   dept1.setDeptName("test1");
                   deptService.save(dept1);
         }
}


 

到此为止,一个基本的springData+jpa的案例就做完了。

 

在自己的dao中,也可以支持原生sql写法和jpql写法,这些方法名称可以随意,如下:

//原生SQL
         @Query(value="selectcount(id) as cou from dept6",nativeQuery=true)
         public BigDecimal getDeptCount();


 

也支持jpql写法,如下:

         

//查询
         @Query("fromDept6 d where d.id > ?1")
         public Page<Dept6> findAll(Integer id);

 

         //修改和删除必须要写@Modifying注解,而且必须要有事务,上面的Query也有事务,但是是只读事务,所以修改和删除必须自己开启事务

         //jpql不支持insert

@Modifying
         @Query("updateDept6 d set d.deptName='新部门' where d.id=:id")
         public void updateDeptName(@Param("id") int id);

 

上面的原生sql和jpql,因为使用了@query注解,所以方法名称没有限制,但是如果不使用@query注解,随意写个方法名称,就会报错,因为方面名称,springdata会把根据方面名称的语意来转换成执行的jquery语句,下面备注下在dao中写方法名称的规则:

解析方法名

Spring DataJPA会通过解析用户在持久层接口中定义的方法名来生成相应的query语句。(详细的解析方法名的规则请参照Spring DataJPA官方文档)

例:

持久层接口中定义如下:

public interface UserRepository extends Repository<User, Long> {

List<User> findByEmailAddressAndLastname(String emailAddress, String lastname);

}

将会解析为如下的query

select u from User u where u.emailAddress = ?1 and u.lastname = ?2

 

解析时能被识别的keyword和包含这些keyword的方法会被解析成什么样的Query,如下表所示。

Keyword

Sample

JPQL snippet

And

findByLastnameAndFirstname

… where x.lastname = ?1 and x.firstname = ?2

Or

findByLastnameOrFirstname

… where x.lastname = ?1 or x.firstname = ?2

Between

findByStartDateBetween

… where x.startDate between 1? and ?2

LessThan

findByAgeLessThan

… where x.age < ?1

GreaterThan

findByAgeGreaterThan

… where x.age > ?1

IsNull

findByAgeIsNull

… where x.age is null

IsNotNull,NotNull

findByAge(Is)NotNull

… where x.age not null

Like

findByFirstnameLike

… where x.firstname like ?1

NotLike

findByFirstnameNotLike

… where x.firstname not like ?1

OrderBy

findByAgeOrderByLastnameDesc

… where x.age = ?1 order by x.lastname desc

Not

findByLastnameNot

… where x.lastname <> ?1

In

findByAgeIn(Collection<Age> ages)

… where x.age in ?1

NotIn

findByAgeNotIn(Collection<Age> age)

… where x.age not in ?1

 

使用@Query

可以在自定义的查询方法上使用@Query来指定该方法要执行的查询语句,比如:

public interface UserRepository extends JpaRepository<User, Long> {

  @Query("select u from User u where u.emailAddress = ?1")

  User findByEmailAddress(String emailAddress);

}

注意:

1:方法的参数个数必须和@Query里面需要的参数个数一致

2:如果是like,后面的参数需要前面或者后面加“%”

 

使用@Param可以用命名参数来代替位置编号,将方法参数与 JPQL 中的命名参数对应。JPQL 语句中通过": 变量"的格式来指定参数

例:

public interface UserRepository extends JpaRepository<User, Long> {

 @Query("select u from User u where u.firstname = :firstname or u.lastname = :lastname")

 User findByLastnameOrFirstname(@Param("lastname") String lastname,

                                   @Param("firstname") String firstname);

}

 

如果要生成更新类的Query语句,在@Query之前添加@Modifying即可。

例:

@Modifying

@Query("update User u set u.firstname = ?1 where u.lastname = ?2")

int setFixedFirstnameFor(String firstname, String lastname);

注意:

1:方法的返回值应该是int,表示更新语句所影响的行数。

2:在调用的地方必须加事务,没有事务不能正常执行。

 

使用JPA NamedQueries

在JPA配置文件中定义

在META-INF文件下的JPA的配置文件orm.xml中,通过<named-query/>元素进行定义。

例:

<named-query name="User.findByLastname">

  <query>select u from User u where u.lastname = ?1</query>

</named-query>

 

通过Annotation配置

在Entity Bean中使用@NamedQuery(或@NamedNativeQuery)进行配置。

例:

@Entity

@NamedQuery(name = "User.findByEmailAddress",

  query = "select u from User u where u.emailAddress = ?1")

public class User {

}

 

注意

①  上述两种方法都需要满足”DomainClass.methodName()”的命名规则。

②  无论是在JPA配置文件中使用<named-query/>定义还是在Entity Bean中使用@NamedQuery进行配置,

   在持久层的接口中必须声明对应的方法。

例:

public interface UserRepository extends JpaRepository<User, Long> {

List<User> findByLastname(String lastname);

User findByEmailAddress(String emailAddress);

}

 

 

 

 

下面讲解下其他几个可以继承的接口

1、dao继承CrudRepository接口使用方法

CrudRepository 接口继承于 Repository 接口,并新增了简单的增、删、查等方法方法如下:

T save(T entity);//保存单个实体

Iterable<T> save(Iterable<?extends T> entities);//保存集合       

T findOne(ID id);//根据id查找实体        

boolean exists(ID id);//根据id判断实体是否存在        

Iterable<T> findAll();//查询所有实体,不用或慎用!        

long count();//查询实体数量        

void delete(ID id);//根据Id删除实体        

void delete(T entity);//删除一个实体

void delete(Iterable<?extends T> entities);//删除一个实体的集合        

void deleteAll();//删除所有实体,不用或慎用!


CRUDRepository 的使用很简单,原来我们继承 Repository ,现在我们继承 CRUDRepository ,就可以使用 CRUDRepository 固定的一些方法,我们不用写 SQL 语句。

 

2、dao继承PagingAndSortingRepository接口

         PagingAndSortingRepository继承了CrudRepository接口,除了拥有父接口的增删改查方法外,还增加了分页查询和排序两个方法,添加的方法如下:

         Iterable<T>findAll(Sort sort);//排序

Page<T>findAll(Pageable pageable);//分页查询(含排序功能)

 

分页案例代码如下:

Servcie层关键代码:

          

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
 
@Autowired
private IDeptDao2deptDao2;
 
          public Page<Dept6> queryPage() {
                   // TODOAuto-generated method stub
                   Sort sort =new Sort(Direction.DESC, "id");
                   Page<Dept6>page = deptDao2.findAll(new PageRequest(0, 10, sort));
         
                   return page;
         }

 

         Dao层关键代码:

                  

 publicinterface IDeptDao2 extends PagingAndSortingRepository<Dept6,Integer> {
                           //因为PagingAndSortingRepository已经有了分页和排序方法,所以这里不需要定义任何方法
}

 

3、dao继承JpaRepository接口

         JpaRepository继承了PagingAndSortingRepository接口,这个接口提供了JPA的相关功能,提供了flush(),saveAndFlush(),deleteInBatch()等方法,方法如下:

List<T>findAll();//查找所有实体

        List<T>findAll(Sort sort);//排序 查找所有实体

        List<T>save(Iterable<? extends T> entities);//保存集合

        void flush();//执行缓存与数据库同步

        TsaveAndFlush(T entity);//强制执行持久化

voiddeleteInBatch(Iterable<T> entities);//删除一个实体集合

        

3、自定义Repository接口

         1)创建一个自定义的Repository接口,代码如下:

                   

publicinterface MyRepository {
 
                            public void test();
}

        

         2)创建一个dao接口,代码如下:

                   

publicinterface DeptDao3 extends JpaRepository<Dept6, Integer>,MyRepository {
 
}

3) 创建一个自定义Repository实现类,示例代码如下:

        

 //注意:这个类的类名,必须是DeptDao3这个类名+Impl( 默认情况下, Spring Data 会在base-package 中查找 "接口名Impl" 作为实现类. 也可以通过 repository-impl-postfix 声明后缀)
public class DeptDao3Impl  implements MyRepository {
 
                  @PersistenceContext
                  private EntityManager entityManager;
        
                  public void test() {
                           //TODO Auto-generated method stub
                           Dept6dept=entityManager.find(Dept6.class, 1);
                           System.out.println(dept.getDeptName());
                  }
}

 

                   4)最后就可以在自己的service层调用此dao方法了,关键代码如下:

                            

@Autowired
                            private DeptDao3 deptDao3;
 
                            /**
                             * 调用自定义的Repository
                             */
                            public voidtestMyRepository() {
                                     // TODO Auto-generated method stub
                                     deptDao3.test();
                            }

  • 1
    点赞
  • 0
    评论
  • 0
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

wazz753

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值