Beginning Spring学习笔记——第5章(一)ORM和JPA基础
来源:互联网 发布:联通网络电视客户端 编辑:程序博客网 时间:2024/05/18 21:08
ORM和JPA简介
持久化
即数据在瞬时状态(内存)和持久状态(数据库–磁盘)之间的转化。
ORM框架
ORM即Object Relational Mapping对象关系映射。完成表与类,属性与类,表之间关系外键与对象间关系之间的映射,解决了以下问题:
- 对象之间管理的方向性与外键的无方向性的矛盾
- 对象的尽可能细粒度与关联数据往往整合在同一个表的矛盾
- 继承和多态的层次性和外键的无层次性的矛盾
- 数据获取方式彼此不适用
为解决问题,ORM框架应当具备如下功能:
- 对象模型和关系模型之间的元数据映射
- 用来在对象上执行相关操作的CRUD API
- 一种对象查询语言
- 不同数据获取策略和对象网络遍历功能,以便提高内存使用率以及数据获取时间性能
JPA
即Java Persistence API,在Java中处理持久化操作,对JavaEE中的ORM特性和功能执行标准化
将对象模型映射到关系模型
定义实体
实体类——和数据表相对应的类(通常一对一,也可一对多)。采用@Entity注解标识,并用@Table注解表明与其对应的表名。其中的主键用@Id注解标明,如果使用了@GeneratedId标注,说明该值是由ID生成策略生成的。
将属性映射到列
默认情况下实体类中所有属性都会被持久化,除非用@Transient标注。默认列名与属性名相同,如果不同可以用@Column注解进行更改。
在对象之间创建关联
- 一对一关联:@OneToOne注解标注,@JoinColumn指定了外键关系
- 多对一关联:@ManyToOne标注
- 一对多关联:@OneToMany标注,标注的属性为Set、List一类
- 多对多关联:@ManyToMany标注,用@JoinTable指定两个表之间的关联表的各列
单向关联
在关联注解中使用mappedBy属性指定另一方为只读(镜子)属性,镜子属性值的设置对创建和删除关联没有影响。
配置JPA和Hibernate
这一章所需要的所有依赖如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.lonelyquantum.springbeginning.wileybookch4</groupId> <artifactId>JDBCTest</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>JDBCTest</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring.version>4.3.10.RELEASE</spring.version> <junit.version>4.12</junit.version> <h2.version>1.4.196</h2.version> <hibernate.version>5.2.10.Final</hibernate.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <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>com.h2database</groupId> <artifactId>h2</artifactId> <version>${h2.version}</version> </dependency> </dependencies></project>
现在src/main/resource目录下创建META-INF/persistent.xml文件配置JPA,指定数据库使用,连接方式和事务模式:
<?xml version="1.0" encoding="UTF-8"?><persistence version="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/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="test-jpa" transaction-type="RESOURCE_LOCAL"> <properties> <property name="hibernate.connection.driver_class" value="org.h2.Driver" /> <property name="hibernate.connection.url" value="jdbc:h2:tcp://localhost/~/test" /> <property name="hibernate.connection.username" value="sa" /> <property name="hibernate.connection.password" value="" /> <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" /> <property name="hibernate.hbm2ddl.auto" value="update" /> </properties> </persistence-unit></persistence>
然后即可在Main函数中用javax.persistence.Persistence类尝试获取EntityManagerFactory
public class Main { public static void main(String[] args) { EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("test-jpa"); System.out.println(entityManagerFactory.isOpen()); }}
运行测试是否成功获取,返回成功结果
使用JPA来持久化实体及创建关联
JPA配置成功后就可以用上面的注解来进行持久化操作了,首先创建Book类:
@Entitypublic class Book { @Id @GeneratedValue private Long id; private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public Long getId() { return id; }}
该类中主键为生成的id。
然后创建Student类,与Book类一对多关联:
@Entitypublic class Student { @Id @GeneratedValue private Long id; private String firstName; private String lastName; @OneToMany(cascade=CascadeType.ALL) @JoinColumn(name="student_id") private Set<Book> books = new HashSet<Book>(); public Long getId() { return id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public Set<Book> getBooks() { return books; }}
然后就可以在主函数中调用持久化方法了。
public class Main { public static void main(String[] args){ EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("test-jpa"); EntityManager entityManager = entityManagerFactory.createEntityManager(); EntityTransaction transaction = entityManager.getTransaction(); transaction.begin(); Student student = new Student(); student.setFirstName("Madoka"); student.setLastName("Kaname"); Book book1 = new Book(); book1.setName("The Order of Things"); Book book2 = new Book(); book2.setName("Discipline and Punishment"); student.getBooks().add(book1); student.getBooks().add(book2); entityManager.persist(student); transaction.commit(); entityManager.close(); }}
该段代码创建了一个学生和两本书并将两本书和该学生关联。entityManager.commit(student)用于对student类的改动进行持久化。
运行程序,可以在数据库控制台中用select语句查看两个表:
在Book的STUDENT_ID一栏可以看出二者的关系。
使用JPA来查找、更新和删除实体
更改上Main函数再运行
public class Main { public static void main(String[] args) { EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("test-jpa"); EntityManager entityManager = entityManagerFactory.createEntityManager(); EntityTransaction transaction = entityManager.getTransaction(); transaction.begin(); Student student = entityManager.find(Student.class, 67L); Book book2 = entityManager.getReference(Book.class, 68L); student.setFirstName("Homura"); student.setLastName("Akemi"); entityManager.remove(book2); transaction.commit(); entityManager.close(); }}
得到新的数据库如下:
可以看到查找、删除和修改操作完成。
其中用EntityManager查找有find和getReference两种方法,前者立即执行查找,后者在查找实例被使用时才执行查找,返回的是一个代理实例。
使用对象查询语言进行查询
JPA提供了JPA QL(Query Language)查询数据库,该语言不使用表列名而使用实体和属性名。
修改上例中Main函数实现查询:
public class Main { public static void main(String[] args) { EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("test-jpa"); EntityManager entityManager = entityManagerFactory.createEntityManager(); Query query = entityManager.createQuery( "select s from Student s where s.firstName like ?0"); query.setParameter("0", "Hom%"); List<Student> students = query.getResultList(); Student s = students.get(0); System.out.println(students.size()); System.out.println(s.getFirstName()); entityManager.close(); }}
输出结果
注意查询语句有两种写法,把上边JPA占位符表示的代码
Query query = entityManager.createQuery( "select s from Student s where s.firstName like ?0"); query.setParameter("0", "Hom%");
换成命名参数的方式也可以:
Query query = entityManager.createQuery( "select s from Student s where s.firstName like :fn"); query.setParameter("fn", "Hom%");
原来的占位符查询方法则被弃置使用:
Query query = entityManager.createQuery( "select s from Student s where s.firstName like ?"); query.setParameter(1, "Hom%");
- Beginning Spring学习笔记——第5章(一)ORM和JPA基础
- Beginning Spring学习笔记——第5章(二)Spring的JPA支持
- Beginning Spring学习笔记——第3章(一)Spring MVC基础
- Beginning Spring学习笔记——第6章(一)Spring事务管理基础
- Beginning Spring学习笔记——第2章(一)Spring IoC容器
- Beginning Spring学习笔记——第4章(一)Spring JDBC连接的配置
- Beginning Spring学习笔记——第1章
- Beginning Spring学习笔记——第9章 SpEL
- Beginning Spring学习笔记——第10章 缓存
- Beginning Spring学习笔记——第2章(三)Spring的Bean管理
- Beginning Spring学习笔记——第3章(三)文件上传、异常处理和个性化
- Beginning Spring学习笔记——第2章(二)依赖注入
- Beginning Spring学习笔记——第3章(二)表单处理
- Beginning Spring学习笔记——第7章 使用Spring进行测试驱动开发
- Beginning Spring学习笔记——第8章 Spring AOP
- Beginning Spring学习笔记——第4章(二)使用Spring执行数据访问操作
- Beginning Spring学习笔记——第6章(二)使用Spring进行声明式事务管理
- Beginning Spring学习笔记——第6章(三)使用Spring进行编程式事务管理
- 今日头条 2017年秋招编程题 :“最大乘积和”
- KazaQ's Socks
- 面试or笔试2——等概率生成0,1
- jsp的简单了解,6中JSP页面元素的简单应用
- MYSQL触发器T-SQL
- Beginning Spring学习笔记——第5章(一)ORM和JPA基础
- Android签名验证原理解析
- HashSet,TreeSet,LinkedHashSet 的用法和区别
- 剑指offer(十三)调整数组顺序使奇数位于偶数前面
- 在有序但含有空的数组中查找字符串
- ZooKeeper原理浅析
- 拆分PDF文档需要什么软件?如何进行操作?
- C++中类模板和实现分离的方法
- 动态SQL