SpringDataJPA详解

本文详细介绍了Spring Data JPA的概念和使用,包括ORM思想、JPA规范、SpringDataJPA框架以及JPQL查询语言。内容涵盖JPA的配置、实体类注解、动态查询、多表关系(一对一、一对多、多对多)以及分页查询的实现。通过实例展示了如何利用Spring Data JPA简化DAO层代码,实现数据库操作。
摘要由CSDN通过智能技术生成

概念

ORM思想

对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。

实际应用中即在关系型数据库和业务实体对象之间作一个映射,这样,我们在具体的操作业务对象的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它就可以了。

简而言之,ORM思想就是通过实体对象操纵数据库的持久化数据。

常见的ORM框架,如hibernatemybatis

JPA

JPA是Java Persistence API的简称,中文名Java持久层API。

JPA支持XML和JDK5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中;

JPA是SUN公司推出的一套基于ORM思想的规范,提供统一的内部接口由各类框架去实现这种规范

SpringDataJPA

Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套JPA应用框架。不是为了取代现有的ORM框架,只是提供便捷开发,易于维护和切换ORM框架使用。

JPQL

JPQL全称Java Persistence Query Language,旨在以面向对象表达式语言的表达式,将SQL语法和简单查询语义绑定在一起·使用这种语言编写的查询是可移植的,可以被编译成所有主流数据库服务器上的SQL。

其特征与原生SQL语句类似,并且完全面向对象,通过类名和属性访问,而不是表名和表的字段。

举个栗子:
当你想把大象装进冰箱里,你需要制定大概思想要怎么去做;(ORM思想)
其次你可以将你的操作步骤记录下来,将打开冰箱门,装进大象,关上冰箱门封装成一套规范;(JPA规范)
而为了以防下次出现另一种冰箱,你再将对所有冰箱的操作封装;(SpringDataJPA)
你在开门关门用的是左手还是右手?(JPQL)

JPA的使用

使用JPA离不开它的实现框架,用hibernate作为它的实现商使用。

导入hibernate的jar包

		<!-- hibernate对jpa的支持包 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>5.0.7.Final</version>
        </dependency>

        <!-- c3p0 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-c3p0</artifactId>
            <version>5.0.7.Final</version>
        </dependency>

创建大象的数据库表

 CREATE TABLE elephant(
  e_id int(32) NOT NULL AUTO_INCREMENT COMMENT '大象的id',
  e_name VARCHAR(32) NOT NULL COMMENT '大象名字',
  e_address VARCHAR(32) DEFAULT NULL COMMENT '大象的住址',
  PRIMARY KEY (e_id)

) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

创建大象的实体类

public class Elephant {

	//大象id
    private int eleId;
    //大象名字			
    private String eleName;
    //大象住址     
    private String eleAddress;  
    
	/* getter and setter */
	
}

编写JPA的配置文件
在resources目录的META-INF目录下创建persistence.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<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_2_0.xsd"
             version="2.0">

    <!--配置持久化单元
		name:持久化单元名称
		transaction-type:事务类型
		 	RESOURCE_LOCAL:本地事务管理
		 	JTA:分布式事务管理 -->

    <persistence-unit name="jpa" transaction-type="RESOURCE_LOCAL">
        <!--配置JPA规范的服务提供商 -->
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <!--数据库信息-->
        <properties>
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpa"/>
            <property name="javax.persistence.jdbc.user" value="root"/>
            <property name="javax.persistence.jdbc.password" value="****"/>
        <!--jpa提供的配置信息-->
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true" />
            <!--
                create:总是创建新的表删除旧表
                update:有表则不会创建新的表
            -->
            <property name="hibernate.hbm2ddl.auto" value="create" />
        </properties>
    </persistence-unit>

</persistence>

实体类加注解

@Entity
@Table(name="elephant")
public class Elephant {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="e_id")
    private int eleId;
    
    @Column(name = "e_name")
    private String eleName;
    
    @Column(name = "e_address")
    private String eleAddress;

	/* getter和setter   */
    
}

注解:
@Entity
属性:name:默认为实体类非限定类名
表示该类是实体类

@Table
属性:
name:指定数据库表的名称,默认为实体类名
catalog: 表的目录,默认为" “。指定数据库实例名
schema: 模式名,默认为” "

@Id
可以放在属性或者对应的get方法上
指定该属性为表的主键

@GeneratedValue
作用:指定主键的生成策略
属性:
strategy :指定主键生成策略,默认为AUTO。
生成策略:
IDENTITY:主键由数据库自动生成(主要是自动增长型)
SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列
AUTO:主键由程序控制
TABLE:使用一个特定的数据库表格来保存主键

@Column
作用:指定实体类属性和数据库表之间的对应关系
属性: name:指定数据库表的列名称。
unique:是否唯一
nullable:是否可以为空
inserttable:是否可以插入
updateable:是否可以更新
length: String属性的长度,默认为255
scale:列的小数位数,默认为0

抽取工具类

public final class JPAUtil {

    // JPA的实体管理器工厂:相当于Hibernate的SessionFactory
    private static EntityManagerFactory factory;

    static {
        // 该方法参数必须和persistence.xml中persistence-unit标签name属性取值一致
        factory = Persistence.createEntityManagerFactory("jpa");
    }

    public static EntityManager getEntityManager() {
        return factory.createEntityManager();
    }

}

EntityManagerFactory:
方法:createEntityManager:返回一个实体管理器
getCache:访问二级缓存

EntityManager:
persist(Object entity):保存实体到表中
T merge(T entity):更新
void remove(Object entity):删除
T find(Class entityClass, Object primaryKey):通过主键查询
T getReference(Class entityClass, Object primaryKey):延迟加载查询

测试CRUD

public class Test {
    
    //保存添加
    @Test
    public void test1(){
        //
        EntityManager em = JPAUtil.getEntityManager();
        //获取事务对象
        EntityTransaction et = em.getTransaction();
        et.begin();
        Elephant elephant = new Elephant();
        elephant.setEleName("跳舞的大象");
        elephant.setEleAddress("森林");
        em.persist(elephant);
        et.commit();
        em.close();
    }

    //查询
    @Test
    public void test2(){
        //
        EntityManager em = JPAUtil.getEntityManager();
        //获取事务对象
        EntityTransaction et = em.getTransaction();
        et.begin();

        Elephant elephant = em.find(Elephant.class, 1);
        System.out.println(elephant);
        et.commit();
        em.close();
    }

    //更新
    @Test
    public void test3(){
        EntityManager em = JPAUtil.getEntityManager();
        //获取事务对象
        EntityTransaction et = em.getTransaction();
        et.begin();
        Elephant elephant = em.find(Elephant.class, 1);
        elephant.setEleName("不爱跳舞的大象");
        em.merge(elephant);
        et.commit();
        em.close();
    }

    //删除
    @Test
    public void test4(){
        EntityManager em = JPAUtil.getEntityManager();
        //获取事务对象
        EntityTransaction et = em.getTransaction();
        et.begin();
        Elephant elephant = em.find(Elephant.class, 1);
        em.remove(elephant);
        et.commit();
        em.close();
    }



}

JPQL使用

查询全部

	@Test
    public void findAll(){
        EntityManager em = JPAUtil.getEntityManager();
        EntityTransaction et = em.getTransaction();
        et.begin();
        // 创建query对象
        String jpql = "from Elephant";
        Query query = em.createQuery(jpql);

        List resultList = query.getResultList();
        for (Object o : resultList) {
            System.out.println(o);
        }
        et.commit();
        em.close();
    }

createQuery(String qlString) :创建Query的实例以执行Java Persistence查询语言语句(jpql)。
Query接口:用于控制查询执行的接口。
方法:
List getResultList(); 执行SELECT查询,并以无类型的List返回查询结果
Object getSingleResult();执行SELECT查询,该查询返回单个结果
int executeUpdate();执行更新或删除语句

分页查询

	@Test
    public void findPage(){
        EntityManager em = JPAUtil.getEntityManager();
        EntityTransaction et = em.getTransaction();
        et.begin();
        String jpql = "from Elephant";
        Query query = em.createQuery(jpql);
        query.setFirstResult(0);
        query.setMaxResults(1);
        List resultList = query.getResultList();
        for (Object o : resultList) {
            System.out.println(o);
        }
        et.commit();
        em.close();
    }

setFirstResult(); 设置要检索的第一个结果的位置
setMaxResult();设置要检索的最大结果数

条件查询

	//创建query对象
	String jpql = "from Elephant where eleName like ? ";
	Query query = em.createQuery(jpql);
	//对占位符赋值,从1开始
	query.setParameter(1, "跳舞的大象%");
	//查询并得到返回结果
	Object object = query.getSingleResult(); //得到唯一的结果集对象

排序查询

	String jpql = "from Elephant order by eleId desc";
	Query query = em.createQuery(jpql);
	// 查询并得到返回结果
	List list = query.getResultList(); // 得到集合返回类型
	for (Object object : list) {
		System.out.println(object);
	}

统计查询

	String jpql = "select count(eleId) from Elephant";
	Query query = em.createQuery(jpql);
	// 查询并得到返回结果
	Object count = query.getSingleResult(); // 得到集合返回类型

SpringDataJPA

导入坐标

使用Spring Data JPA,需要整合Spring与Spring Data JPA,并且需要提供JPA的服务提供者hibernate,所以需要导入spring相关坐标,hibernate坐标,数据库驱动坐标等

	<properties>
        <spring.version>4.2.4.RELEASE</spring.version>
        <hibernate.version>5.0.7.Final</hibernate.version>
        <slf4j.version>1.6.6</slf4j.version>
        <log4j.version>1.2.12</log4j.version>
        <c3p0.version>0.9.1.2</c3p0.version>
        <mysql.version>5.1.6</mysql.version>
    </properties>

    <dependencies>
        <!-- junit单元测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        
        <!-- spring beg -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.8</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        
        <!-- spring end -->

        <!-- hibernate beg -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.2.1.Final</version>
        </dependency>
        <!-- hibernate end -->

        <!-- c3p0 beg -->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>${c3p0.version}</version>
        </dependency>
        <!-- c3p0 end -->

        <!-- log end -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <!-- log end -->

        
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>1.9.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
        
        <!-- el beg 使用spring data jpa 必须引入 -->
        <dependency>  
            <groupId>javax.el</groupId>  
            <artifactId>javax.el-api</artifactId>  
            <version>2.2.4</version>  
        </dependency>  
          
        <dependency>  
            <groupId>org.glassfish.web</groupId>  
            <artifactId>javax.el</artifactId>  
            <version>2.2.4</version>  
        </dependency> 
        <!-- el end -->
    </dependencies>

整合SpringDataJPA和Spring

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
		http://www.springframework.org/schema/data/jpa 
		http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
	
	<!-- 1.dataSource 配置数据库连接池-->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="com.mysql.jdbc.Driver" />
		<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/jpa" />
		<property name="user" value="root" />
		<property name="password" value="****" />
	</bean>
	
	<!-- 2.配置entityManagerFactory -->
	<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="packagesToScan" value="com.**.domain" />
		<property name="persistenceProvider">
			<bean class="org.hibernate.jpa.HibernatePersistenceProvider" />
		</property>
		<!--JPA的供应商适配器-->
		<property name="jpaVendorAdapter">
			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
				<property name="generateDdl" value="false" />
				<property name="database" value="MYSQL" />
				<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
				<property name="showSql" value="true" />
			</bean>
		</property>
		<property name="jpaDialect">
			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
		</property>
	</bean>
    
	
	<!-- 3.事务管理器-->
	<!-- JPA事务管理器  -->
	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
		<property name="entityManagerFactory" ref="entityManagerFactory" />
	</bean>
	
	<!-- 整合spring data jpa-->
	<jpa:repositories base-package="com.**.dao"
		transaction-manager-ref="transactionManager"
		entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>
		
	<!-- 4.txAdvice-->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="save*" propagation="REQUIRED"/>
			<tx:method name="insert*" propagation="REQUIRED"/>
			<tx:method name="update*" propagation="REQUIRED"/>
			<tx:method name="delete*" propagation="REQUIRED"/>
			<tx:method name="get*" read-only="true"/>
			<tx:method name="find*" read-only="true"/>
			<tx:method name="*" propagation="REQUIRED"/>
		</tx:attributes>
	</tx:advice>
	
	<!-- 5.aop-->
	<aop:config>
		<aop:pointcut id="pointcut" expression="execution(* cn.itcast.service.*.*(..))" />
		<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" />
	</aop:config>
	
	<context:component-scan base-package="com.**"></context:component-scan>
		
	<!--组装其它 配置文件-->
	
</beans>

SpringDataJPA使用

创建一个Dao层接口,并实现JpaRepositoryJpaSpecificationExecutor

	public interface ElephantDao extends JpaRepository<Elephant, Integer>, JpaSpecificationExecutor<Elephant> {
}

JpaRepository<实体类类型,主键类型>:用来完成基本CRUD操作
JpaSpecificationExecutor<实体类类型>:用于复杂查询(分页等查询操作)

基础CRUD操作

	@Test
    public void testSave() {
        Elephant e = new Elephant();
        e.setEleName("爱喊麦的大象");
        elephantDao.save(e);
    }

}

save(Entity e):如果实体类中包含主键id,则此方法先查询该id的实体再更新;如果不包含主键id,则直接保存实体
delete(): 删除
findOne():查询一个

dao层没有任何方法,怎么执行的操作呢?

当程序执行的时候,会通过JdkDynamicAopProxy的invoke方法,对elephantDao对象生成动态代理对象SimpleJpaRepository,底层依然是用EntityManager对象进行操作,所以Spring Data JPA只是对标准JPA操作进行了进一步封装,简化了Dao层代码的开发
在这里插入图片描述
结合JPQL方式

public interface ElephantDao extends JpaRepository<Elephant, Integer>,JpaSpecificationExecutor<Elephant> {    
    //@Query 使用jpql的方式查询。
    @Query(value="from Elephant")
    public List<Elephant> findAllElephant();
    
    //@Query 使用jpql的方式查询。?1代表参数的占位符,其中1对应方法中的参数索引
    @Query(value="from Elephant where eleName= ?1")
    public Elephant findElephant(String eleName);

	@Query(value="update Elephant set eleName= ?1 where eleId= ?2")
    @Modifying
    public void updateElephant(String eleName,Integer eleID);

}

使用sql方式

	/**
     * nativeQuery : 使用本地sql的方式查询
     */
    @Query(value="select * from elephant",nativeQuery=true)
    public void findSql();

使用方法名称方式

按照Spring Data JPA 定义的规则,查询方法以findBy开头,涉及条件查询时,条件的属性用条件关键字连接,要注意的是:条件属性首字母需大写。框架在进行方法名解析时,会先把方法名多余的前缀截取掉,然后对剩下部分进行解析。

在这里插入图片描述

动态查询

有时我们在查询某个实体的时候,给定的条件是不固定的,这时就需要动态构建相应的查询语句,在Spring Data JPA中可以通过JpaSpecificationExecutor接口查询。相比JPQL,其优势是类型安全,更加的面向对象。

public interface JpaSpecificationExecutor<T> {
   	//根据条件查询一个对象
 	T findOne(Specification<T> spec);	
   	//根据条件查询集合
 	List<T> findAll(Specification<T> spec);
   	//根据条件分页查询
 	Page<T> findAll(Specification<T> spec, Pageable pageable);
   	//排序查询查询
 	List<T> findAll(Specification<T> spec, Sort sort);
   	//统计查询
 	long count(Specification<T> spec);
}

Specification接口

    /**
    *	root	:Root接口,代表查询的根对象,可以通过root获取实体中的属性
    *	query	:代表一个顶层查询对象,用来自定义查询
    *	cb		:用来构建查询,此对象里有很多条件方法
    **/
    public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);

测试动态查询


	@Autowired
	private ElephantDao elephantDao;	
	@Test
	public void testSpecifications() {
      	//使用匿名内部类的方式,创建一个Specification的实现类,并实现toPredicate方法
		Specification <Elephant> spec = new Specification<Elephant>() {
			public Predicate toPredicate(Root<Elephant> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				//cb:构建查询,添加查询方式   like:模糊匹配
				//root:从实体Elephant对象中按照eleName属性进行查询
				return cb.like(root.get("eleName").as(String.class), "爱喊麦%");
			}
		};
		Elephant elephant= elephantDao.findOne(spec);
		System.out.println(elephant);
	}

分页查询

 	@Test
	public void testPage() {
		//构造查询条件
		Specification<Elephant> spec = new Specification<Elephant>() {
			public Predicate toPredicate(Root<Elephant> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				return cb.like(root.get("eleName").as(String.class), "%大象%");
			}
		};
		/**
		 * 构造分页参数
		 * 		Pageable : 接口
		 * 			PageRequest实现了Pageable接口,调用构造方法的形式构造
		 * 				第一个参数:页码(从0开始)
		 * 				第二个参数:每页查询条数
		 */
		Pageable pageable = new PageRequest(0, 5);
		
		/**
		 * 分页查询,封装为Spring Data Jpa 内部的page bean
		 * 		此重载的findAll方法为分页方法需要两个参数
		 * 			第一个参数:查询条件Specification
		 * 			第二个参数:分页参数
		 */
		Page<Customer> page = customerDao.findAll(spec,pageable);
	}

多表

一对多

使用冰箱和大象这一对一对多的实体关系,一头大象只能被装进一个冰箱里,一个冰箱可以装多头大象。
冰箱的实体类

@Entity
@Table(name="fridge")
public class Fridge {
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="f_id")
	private int friId;
	
	@Column(name="f_name")
	private String friName;

	@OneToMany(mappedBy="fridge")
	private Set<Elephant> elephants = new HashSet<Elephant>();
	/* getter和setter */
}
@Entity
@Table(name="elephant")
public class Elephant {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="e_id")
    private int eleId;
    
    @Column(name = "e_name")
    private String eleName;
    
    @Column(name = "e_address")
    private String eleAddress;
	
	@ManyToOne(targetEntity=Fridge.class)
	@JoinColumn(name="e_f_id",referencedColumnName="f_id")
	private Fridge fridge;

	/* getter和setter   */
    
}

@OneToMany:
作用:建立一对多的关系映射
属性:
targetEntityClass:指定多的多方的类的字节码
mappedBy:指定从表实体类中引用主表对象的名称。
cascade:指定要使用的级联操作
fetch:指定是否采用延迟加载
orphanRemoval:是否使用孤儿删除

@ManyToOne
作用:建立多对一的关系
属性:
targetEntityClass:指定一的一方实体类字节码
cascade:指定要使用的级联操作
fetch:指定是否采用延迟加载
optional:关联是否可选。如果设置为false,则必须始终存在非空关系。

@JoinColumn
作用:用于定义主键字段和外键字段的对应关系。
属性:
name:指定外键字段的名称
referencedColumnName:指定引用主表的主键字段名称
unique:是否唯一。默认值不唯一

多对多

学生与老师是一对多对多的实体关系

@Entity
@Table(name="student")
public class Student{
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="s_id")
	private int stuId;
	
	@Column(name="s_name")
	private String stuName;

	@ManyToMany(mappedBy="students")
	private Set<Teacher> teachers = new HashSet<Teacher>();
	/* getter和setter */
}
@Entity
@Table(name="teacher")
public class Teacher{
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="t_id")
	private int teaId;
	
	@Column(name="t_name")
	private String teaName;

	//多对多关系映射
	@ManyToMany
	@JoinTable(name="s_t_table",//中间表的名称
			  //中间表s_t_table字段关联teacher表的主键字段t_id
			  joinColumns={@JoinColumn(name="t_id",referencedColumnName="t_id")},
			  //中间表s_t_table的字段关联student表的主键s_id
			  inverseJoinColumns={@JoinColumn(name="s_id",referencedColumnName="s_id")}
	)
	private Set<Student> students= new HashSet<Student>();
	/* getter和setter */
}

@ManyToMany
作用:用于映射多对多关系
属性:
cascade:配置级联操作。
fetch:配置是否采用延迟加载。
targetEntity:配置目标的实体类。映射多对多的时候不用写

@JoinTable
作用:针对中间表的配置
属性:
name:配置中间表的名称
joinColumns:中间表的外键字段关联当前实体类所对应表的主键字段
inverseJoinColumn:中间表的外键字段关联对方表的主键字段

@JoinColumn
作用:用于定义主键字段和外键字段的对应关系。
属性:
name:指定外键字段的名称
referencedColumnName:指定引用主表的主键字段名称
unique:是否唯一。默认值不唯一

查询一个老师,获取该老师教的所有学生

	@Autowired
	private TeacherDao teacherDao;
	
	@Test
	//由于是在java代码中测试,为了解决no session问题,将操作配置到同一个事务中
	@Transactional 
	public void testFind() {
		Teacher teacher= teacherDao.findOne(1);
		Set<Student> stdents= teacher.getStudents();//对象导航查询
		for(Student student: students) {
  			System.out.println(student);
		}
	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值