Beginning Spring学习笔记——第5章(一)ORM和JPA基础

ORM和JPA简介,JPA的配置和使用
摘要由CSDN通过智能技术生成

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类:

@Entity
public 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类一对多关联:

@Entity
public 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语句查看两个表:
Student
Book
在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%");
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值