在本文中,您将学习如何在 hibernate 中使用 Embeddable 类型将线性数据库表映射到由各种值类型组成的实体类。
考虑下表存储有关应用程序用户的信息。信息包括用户的基本详细信息,如姓名、电子邮件和他的地址 -
从数据库的角度来看,表结构很好。但是如果我们需要将此表映射到我们应用程序中的实体类中,我们可能希望将 Name
和 Address
详细信息抽象到单独的类中,以实现更好的抽象和可重用性 -
可嵌入类型可以由任意数量的实体在您的项目中重复使用。我们将从头开始创建一个项目,并学习如何将上述 users
表映射到一个实体类,该实体类将名称和地址详细信息抽象为单独的类。
我们将使用 Spring Boot CLI 来生成我们的应用程序。打开终端并键入以下命令以生成应用程序 -
spring init -n=jpa-embeddable-demo -d=web,jpa,mysql --package-name=com.example.jpa jpa-embeddable-demo
您还可以使用 Spring Initializr 网络应用程序生成应用程序。按照以下说明使用 Spring Initializr Web 工具生成应用程序 -
以下是完整应用的目录结构,供大家参考——
此时,您的引导项目将没有 model
和 repository
包以及所有其他类。我们将在进行下一部分时创建它们。
我们需要配置 MySQL 数据库 URL、用户名和密码。打开 src/main/resources/application.properties
文件并向其添加以下属性 -
# DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url=jdbc:mysql://localhost:3306/jpa_embeddable_demo?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
spring.datasource.username=root
spring.datasource.password=root
# Hibernate
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type=TRACE
我已经将 Hibernate 的 ddl-auto
属性指定为 update
。每当我们更新应用程序中相应的实体类时,这将自动创建/更新数据库表。
请注意,您需要创建一个名为 jpa_embeddable_demo
的数据库。另外,不要忘记根据您的 MySQL 安装更改 spring.datasource.username
和 spring.datasource.password
属性。
让我们首先定义将嵌入 User
模型中的可嵌入类型。我们将在 com.example.jpa
包中创建一个名为 model
的包,并将所有模型类添加到该包中。
我们使用 JPA 的 @Embeddable
注释来声明一个类旨在被其他实体嵌入。
1.姓名
package com.example.jpa.model;
import javax.persistence.Embeddable;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@Embeddable
public class Name {
@NotNull
@Size(max = 40)
private String firstName;
@Size(max = 40)
private String middleName;
@Size(max = 40)
private String lastName;
public Name() {
}
public Name(String firstName, String middleName, String lastName) {
this.firstName = firstName;
this.middleName = middleName;
this.lastName = lastName;
}
// Getters and Setters (Omitted for brevity)
}
2.地址
package com.example.jpa.model;
import javax.persistence.Embeddable;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@Embeddable
public class Address {
@NotNull
@Size(max = 100)
private String addressLine1;
@NotNull
@Size(max = 100)
private String addressLine2;
@NotNull
@Size(max = 100)
private String city;
@NotNull
@Size(max = 100)
private String state;
@NotNull
@Size(max = 100)
private String country;
@NotNull
@Size(max = 6)
private String zipCode;
public Address() {
}
public Address(String addressLine1, String addressLine2, String city,
String state, String country, String zipCode) {
this.addressLine1 = addressLine1;
this.addressLine2 = addressLine2;
this.city = city;
this.state = state;
this.country = country;
this.zipCode = zipCode;
}
// Getters and Setters (Omitted for brevity)
}
现在让我们创建将嵌入 Name
和 Address
类型的 User
模型 -
package com.example.jpa.model;
import org.hibernate.validator.constraints.Email;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Embedded
private Name name;
@NotNull
@Email
@Column(unique = true)
private String email;
@Embedded
@AttributeOverrides(value = {
@AttributeOverride(name = "addressLine1", column = @Column(name = "house_number")),
@AttributeOverride(name = "addressLine2", column = @Column(name = "street"))
})
private Address address;
public User() {
}
public User(Name name, String email, Address address) {
this.name = name;
this.email = email;
this.address = address;
}
// Getters and Setters (Omitted for brevity)
}
我们使用 JPA 的 @Embedded
注释在模型类中嵌入一个类型。注意 @AttributeOverrides
和 @AttributeOverride
注释的使用。这些注释可帮助您自定义/覆盖可嵌入类型的字段。
接下来,让我们创建用于从数据库访问用户数据的存储库。首先在com.example.jpa
包中创建一个名为repository
的包,然后在repository
包中添加如下接口——
package com.example.jpa.repository;
import com.example.jpa.model.Name;
import com.example.jpa.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
我们从 Spring Data JPA 的 JpaRepository
接口扩展了 UserRepository
。 JpaRepository
接口包含实体上所有 CRUD 操作的方法。 Spring Boot 在运行时自动注入一个名为 SimpleJpaRepository
的接口实现。
这有助于我们在实体上执行所有 CRUD 操作,而无需自己实现任何东西。
最后,让我们编写一些代码来测试我们的 Embeddable 类型设置。打开主类 JpaEmbeddableDemoApplication.java
并将其替换为以下代码 -
package com.example.jpa;
import com.example.jpa.model.Address;
import com.example.jpa.model.Name;
import com.example.jpa.model.User;
import com.example.jpa.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class JpaEmbeddableDemoApplication implements CommandLineRunner {
@Autowired
private UserRepository userRepository;
public static void main(String[] args) {
SpringApplication.run(JpaEmbeddableDemoApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
// Cleanup the users table
userRepository.deleteAllInBatch();
// Insert a new user in the database
Name name = new Name("Rajeev", "Kumar", "Singh");
Address address = new Address("747", "Golf View Road", "Bangalore", "Karnataka", "India", "560008");
User user = new User(name, "rajeev@callicoder.com", address);
userRepository.save(user);
}
}
在上面的类中,我实现了 Spring 的 CommandLineRunner 接口并编写了代码来测试我们在 run()
方法中的设置。 run()
方法在应用程序启动成功时被调用。
在 run()
方法中,我们首先清理用户的表,然后在数据库中插入一个新的用户。
您可以通过从项目的根目录键入以下命令来运行该应用程序 -
mvn spring-boot:run
查看日志以查看 hibernate 已执行的 SQL 语句 -
org.hibernate.SQL : delete from users
org.hibernate.SQL : insert into users (city, country, house_number, state, street, zip_code, email, first_name, last_name, middle_name) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
如果您在运行应用程序后检查 MySQL 中的 users
表,您将找到我们使用 hibernate 插入的条目。
mysql> select * from users;
+----+------------+-------------+-----------+-----------------------+--------------+----------------+-----------+-----------+---------+----------+
| id | first_name | middle_name | last_name | email | house_number | street | city | state | country | zip_code |
+----+------------+-------------+-----------+-----------------------+--------------+----------------+-----------+-----------+---------+----------+
| 1 | Rajeev | Kumar | Singh | rajeev@callicoder.com | 747 | Golf View Road | Bangalore | Karnataka | India | 560008 |
+----+------------+-------------+-----------+-----------------------+--------------+----------------+-----------+-----------+---------+----------+
1 row in set (0.00 sec)
注意表结构是如何线性的,但在应用程序级别,我们将 Name
和 Address
细节抽象为单独的类。
Spring Data JPA 有一个很好的特性,它可以根据我们在存储库中指定的方法名称生成查询。
例如,要查找带有电子邮件的用户,您可以在 UserRepository
和 Sp 中添加如下查询方法 JPA 将自动从中生成查询,而无需您实施任何操作 -
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
// Find user by email
User findByEmail(String email);
}
您可以查看官方 Spring Data JPA 的文档以了解有关 Query 方法的更多信息。
所以想法是您使用实体类的字段名称编写查询方法。 当您使用可嵌入类型并且需要使用可嵌入类型的字段查询实体时,您可以指定这样的查询方法 -
// Find users by firstName
List<User> findByNameFirstName(String firstName);
// Find users by lastName
List<User> findByNameLastName(String lastName);
// Find users by country
List<User> findByAddressCountry(String country);
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://www.callicoder.com/hibernate-spring-boot-jpa-embeddable-demo/
内容来源于网络,如有侵权,请联系作者删除!