概念
ORM思想
对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。
实际应用中即在关系型数据库和业务实体对象之间作一个映射,这样,我们在具体的操作业务对象的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它就可以了。
简而言之,ORM思想就是通过实体对象操纵数据库的持久化数据。
常见的ORM框架,如hibernate,mybatis等
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层接口,并实现JpaRepository和JpaSpecificationExecutor
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);
}
}
本文详细介绍了Spring Data JPA的概念和使用,包括ORM思想、JPA规范、SpringDataJPA框架以及JPQL查询语言。内容涵盖JPA的配置、实体类注解、动态查询、多表关系(一对一、一对多、多对多)以及分页查询的实现。通过实例展示了如何利用Spring Data JPA简化DAO层代码,实现数据库操作。
8347

被折叠的 条评论
为什么被折叠?



