ホームページ  >  記事  >  Java  >  SpringBoot JPA共通アノテーションの使用方法

SpringBoot JPA共通アノテーションの使用方法

WBOY
WBOY転載
2023-05-13 09:40:191146ブラウズ

    1. はじめに

    Jpa は ORM 仕様のセットです
    hibernate は単なる ORM フレームワークではありませんJPA

    JPA (Java Persistence API): java 永続性 API

    2 の実装を提供します。共通のアノテーション

    2.1 @ Entity

    は、現在のクラスをエンティティ クラスとしてマークし、指定されたデータベース テーブル

    @Entity
    public class Users {
    		
    }

    2.2 にマップされます。@Table

    は通常、@Entity とともに注釈が付けられます。使用します。データベースのテーブル名とクラス名が一致している場合は、@Table アノテーションを使用しなくても問題ありません。
    それ以外の場合は、@Table アノテーションを使用する必要があります。テーブル名を指定します

    @Entity
    @Table(name="t_users")
    public class Users {
    		
    }

    2.3 @Id、@GeneratedValue、@SequenceGenerator、@Column

    2.3.1 @Id

    はエンティティ クラスの属性をマップするために使用されます主キーに

    2.3.2 @ GeneratedValue

    主キー生成戦略を指定します

    package javax.persistence;
    /**
     * 策略类型
     */
    public enum GenerationType {
      /**
       * 通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植
       */
      TABLE,
      /**
       * 通过序列产生主键,通过 @SequenceGenerator 注解指定序列名
       * MySql 不支持这种方式
       * Oracle 支持
       */
      SEQUENCE,
      /**
       * 采用数据库 ID自增长的方式来自增主键字段
       * Oracle 不支持这种方式;
       */
      IDENTITY,
      /**
       * 缺省值,JPA 根据数据库自动选择
       */
      AUTO;
    
      private GenerationType() {
      }
    }
    2.3.3 @SequenceGenerator
    2.3.4 @Column

    エンティティ クラスの属性名とデータベースの列名が一致しない場合、このアノテーションを使用する必要があります

    @Entity
    @Table(name="t_users")
    public class Users {
    
      @Id
      @Column(name = "user_id")
      @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_seq")
      @SequenceGenerator(name = "user_seq", sequenceName = "user_seq")
      private Long userId;
    		
    }

    2.4 @Transient

    現在の属性を使用する必要がないことを示しますデータベースにマッピングされます

    2.5 @Temproal

    主に日付型属性に使用され、このアノテーション

    @Entity
    @Table(name="t_users")
    public class Users {
    
      @Temporal(TemporalType.DATE) 
      private Date time1;
      
      @Temporal(TemporalType.TIME)
      private Date time2;
      
      @Temporal(TemporalType.TIMESTAMP)
      private Date time3;
    }

    3を通じて時間の精度を指定できます。

    は Hibernate の SessionFactory

    4 に似ています。4 種類の EntityManager エンティティ Status

    新しいステータス: 新しい作成にはまだありません永続的な主キー 永続ステータス: すでに永続的な主キーがあり、永続性とのコンテキスト関係が確立されています 空き状態: 永続的な主キーがありますが、永続性とのコンテキスト関係がありません 削除状態: 永続的な主キーがあり、永続性とのコンテキスト関係がありますが、データベースから削除されています

    4.1 find(ClassentityClass, ObjectprimaryKey)

    休止状態でのセッションの get() と同様

    #find はクエリが見つからない場合に null を返します

    4.2 getReference(ClassentityClass, ObjectprimaryKey)

    休止状態でのセッションのload()と同様に
    オブジェクト内の属性が実際に取得された場合のみクエリが実行されます。SQL文のgetReference()はプロキシオブジェクトを返すだけです


    ##getReference は、クエリされない場合は null を返さず、EntityNotFoundException をスローします。

    注: このメソッドを使用すると、遅延読み込み例外が発生する可能性があります。つまり、属性がまだ取得されていないためです。

    #4.3persist

    休止状態でのセッションの Save() と同様

    注: メソッドの実行時に渡されるオブジェクトは主キー値を設定できないため、例外がスローされます

    4.4 削除

    類似休止状態でセッションの delete() を実行します。

    注: このメソッドは永続オブジェクトのみを削除できますが、解放オブジェクトは削除できません (休止状態では削除できます)

    	/**
    	 * 删除游离态(失败)
    	 */
    	public void testRemove(){
    		Users user = new Users();
    		Users.setUserId(1);
    		entityManager.remove(customer);
    	}
    	
    	/**
    	 * 删除持久化状态(成功)
    	 */
    	public void testRemove(){
    		Users user = entityManager.find(Users.class, 1);
    		entityManager.remove(user);
    	}

    4.5 マージ(T エンティティ)

    休止状態でのセッションの saveOrUpdate() と同様

    #
    	// 新建状态
    	public void testMerge	(){
    		Users user= new Users();
    		// 省略一系列的set
    		// user.set.....
    		Users newUser = entityManager.merge(user);
    		// user.getUserId() == null  ==> true
    		// newUser.getUserId() == null ==> false
    	}

    4.6 flash()

    SpringBoot JPA共通アノテーションの使用方法休止状態のセッションでの flash() と同様

    #コンテキスト内のすべての未保存エンティティをデータベースに保存します

    4.6 fresh()

    #休止状態のセッションrefresh()と同様

    すべてのエンティティの属性値を更新します

    5.EntityTransaction

    EntityManager.getTransaction()

    #5.1 begin

    5.2 commit

    5.3 rollback

    6. マッピング関係

    6.1 一方向 one-to -many

    ユーザーと注文の関係を例に挙げます。ユーザーには複数の注文があり、1 つの注文は 1 人のユーザーにのみ属します。

    ペアの場合 複数の関係を挿入する場合、多数の関係を挿入する場合、側または一方の側が最初に挿入されると、多側は挿入中に外部キー列を挿入しないため、追加の更新ステートメントが生成されます。

    /**
     * 订单和用户是多对一的关系
     */
    @Entity
    @Table(name="t_order")
    public class Order {
    	// lazy为懒加载,默认为eager立即查询
    	@ManyToOne(fetch=FetchType.Lazy)
    	// @JoinColumn标注字段是一个类,userId为该类的主键
    	@JoinColumn(name="user_id")
    	private Users user;
    }

    6.2 一方向多対 1

    ユーザーと注文の関係を例に挙げます。ユーザーには複数の注文があり、注文は 1 人のユーザーにのみ属します

    多対 1 の関係での挿入の場合、次のようになります。最善から最初に、一人を救う終わり、そして多くの人を救う終わり。
    最初に多端を保存し、次に一端を保存する場合、外部キー関係を維持するために、多端で追加の更新操作を実行する必要があります

    /**
     * 订单和用户是多对一的关系
     */
    @Entity
    @Table(name="t_order")
    public class Order {
    	// lazy为懒加载,默认为eager立即查询
    	@ManyToOne(fetch=FetchType.Lazy)
    	// @JoinColumn标注字段是一个类,userId为该类的主键
    	@JoinColumn(name="user_id")
    	private Users user;
    }

    6.3 双方向多対 1

    ユーザーと注文の関係を例に挙げます。ユーザーには複数の注文があり、注文は 1 人のユーザーにのみ属します。
    双方向の多対1 つは、上記 2 つを組み合わせたもので、@OneToMany と @ManyToOne

    /**
     * 用户和订单是一对多的关系
     */
    @Entity
    @Table(name="t_users")
    public class User {
    	// 如果两侧都要描述关联关系的话,维护关联关系的任务要交给多的一方
    	// 使用 @OneToMany 了 mappedBy 的代表不维护关联关系,也就是不会产生额外的update语句
    	// @OneToMany 和 @JoinColumn 不能同时使用会报错
    	@OneToMany(mappedBy="user")
    	private Set<Orders> orders;
    }
    
    /**
     * 订单和用户是多对一的关系
     */
    @Entity
    @Table(name="t_orders")
    public class Order {
    	// lazy为懒加载,默认为eager立即查询
    	@ManyToOne(fetch=FetchType.Lazy)
    	// @JoinColumn标注字段是一个类,userId为该类的主键
    	@JoinColumn(name="user_id")
    	private Users user;
    }

    を使用します。

    6.4 双向一对一

    以学校和校长之间的关系为例,一个学校只有一个校长,一个校长也只属于一个学校
    一方使用 @OneToMany + @JoinColumn,另一方使用 @OneToOne(mappedBy=“xx”)
    具体由哪一方维护关联关系都可以,这里我们以学校一端维护关联关系为例
    保存时先保存不维护关联关系的一方(也就是使用@OneToOne(mappedBy=“xx”)的一方),否则会产生额外的 update 语句

    /**
     * 学校
     */
    @Entity
    @Table(name="t_school")
    public class School {
    	// 默认为eager立即查询
    	@OneToOne
    	// 添加唯一约束
    	@JoinColumn(name="school_master_id", unique = true)
    	private SchoolMaster schoolMaster;
    }
    
    /**
     * 校长
     */
    @Entity
    @Table(name="t_school_master")
    public class SchoolMaster {
    	// 不维护关联关系要使用 mappedBy
    	@OneToOne(mappedBy="schoolMaster")
    	private School school;
    }

    6.5 双向多对多

    以学生和课程之间的关系为例,一个学生可以选多门课,一个课程也有多个学生,多对多需要一个中间表,也就是选课表
    维护关联关系的一方需要使用 @JoinTable
    关联关系也是只有一方维护即可,这里我们由学生表进行维护

    /**
     * 学生
     */
    @Entity
    @Table(name="t_student")
    public class Student {
    	@GeneratedValue
    	@Id
    	private Long student_id;
    	
    	// 要使用 set 集合接收
    	// 默认为lazy懒加载
    	@ManyToMany
    	// name 为中间表的表名
    	@JoinTable(name="t_student_choose_course",
    			// name 为与中间表与当前表所关联的字段的名称,referencedColumnName 为当前表中与中间表关联的字段的名称
    			joinColumns={@JoinColumn(name="student_id", referencedColumnName="student_id")},
    			// name 为与中间表与多对多另一方表所关联的字段的名称,referencedColumnName 为多对多另一方与中间表关联的字段的名称
    			inverseJoinColumns={@JoinColumn(name="course_id", referencedColumnName="course_id")})
    	private Set<Course> courses;
    }
    
    /**
     * 课程
     */
    @Entity
    @Table(name="t_course")
    public class Course {
    	@GeneratedValue
    	@Id
    	private Long course_id;
    	
    	// 要使用 set 集合接收
    	// 默认为lazy懒加载
    	@ManyToMany(mappedBy="courses")
    	private Set<Student> students;
    }

    7. 二级缓存

    开启了二级缓存之后,缓存是可以跨越 EntityManager 的,
    默认是一级缓存也就是在一个 EntityManager 中是有缓存的
    二级缓存可以实现,关闭了 EntityManager 之后缓存不会被清除
    使用 @Cacheable(true) 开启二级缓存

    8. JPQL

    8.1 查询接口

    8.1.1 createQuery
    	public void testCreateQuery(){
    		// 这里我们使用了一个 new Student,因为我们是查询 Student 中的部分属性,如果不适用 new Student 查询返回的结果就不是 Student 类型而是一个 Object[] 类型的 List
    		// 也可以在实体类中创建对应的构造器,然后使用如下这种 new Student 的方式,来把返回结果封装为Student 对象
    		String jpql = "SELECT new Student(s.name, s.age) FROM t_student s WHERE s.student_id > ?";
    		// setParameter 时下标是从1开始的
    		List result = entityManager.createQuery(jpql).setParameter(1, 1).getResultList();
    	}
    8.1.2 createNamedQuery

    需要在类上使用 @NamedQuery 注解,事先声明 sql 语句

    @NamedQuery(name="testNamedQuery", query="select * from t_student WHERE student_id = ?")
    @Entity
    @Table(name="t_student")
    public class Student {
    	@GeneratedValue
    	@Id
    	private Long student_id;
    	
    	@Column
    	private String name;
    	
    	@Column
    	private int age;
    }
    	public void testCreateNamedQuery(){
    		Query query = entityManager.createNamedQuery("testNamedQuery").setParameter(1, 3);
    		Student student = (Student) query.getSingleResult();
    	}
    8.1.3 createNativeQuery
    	public void testCreateNativeQuery(){
    		// 本地sql的意思是只能在数据库中执行的sql语句
    		String sql = "SELECT age FROM t_student WHERE student_id = ?";
    		Query query = entityManager.createNativeQuery(sql).setParameter(1, 18);
    		Object result = query.getSingleResult();
    	}

    8.2 关联查询

    存在一对多关系时,当我们查询一的一端时,默认多的一端是懒加载。此时我们如果想要一次性查询出所有的数据就需要使用关联查询

    注意: 下面 sql 中的重点就是要加上 fetch u.orders,表示要查询出用户所关联的所有订单

    	public void testLeftOuterJoinFetch(){
    		String jpql = "FROM t_users u LEFT OUTER JOIN FETCH u.orders WHERE u.id = ?";
    		
    		Users user = (Users) entityManager.createQuery(jpql).setParameter(1, 123).getSingleResult();
    	}

    以上がSpringBoot JPA共通アノテーションの使用方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明:
    この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。