JPA单向多对一实体映射
程序员文章站
2022-04-24 11:33:54
...
1、建表, 在多的一方创建外键关联
# 产品 - 多的一方
drop table if exists product;
create table product(
id varchar(64) primary key
,name varchar(20)
,product_type_id varchar(64)
# 添加外键映射
,constraint fk_product_id foreign key (product_type_id) references product_type(id)
) engine InnoDB charset 'utf8';
# 产品类型名称 - one的一方
create table product_type(
id varchar(64) primary key
,name varchar(20)
) engine InnoDB charset 'utf8';
2、做实体映射
many一方的实体映射代码如下:
package com.jiang.jpa.otm.entity;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
package com.jiang.jpa.otm.entity;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
*
* many的一方
*
* @author Luosj
*
* @date 2020/2/16 5:09 PM
*/
@Entity
@Table(name = "product")
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class Product{
@Id
private String id;
private String name;
@ManyToOne
// @Column(name="product_type_id") // 多的一方不能使用@Column来配置外键列名
@JoinColumn(name = "product_type_id")
private ProductType productType;
@Override
public String toString() {
return "{id:"+this.getId()+",name:"+this.getName()+"}";
}
}
/**
* @author Luosj
* @desc: from spring-data-jpa-demo
*/
One一方的实体如下:
package com.jiang.jpa.otm.entity;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
* one的一方
*
* @author Luosj
*
* @date 2020/2/16 5:12 PM
*/
@Entity
@Table(name = "product_type")
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class ProductType{
@Id
private String id;
private String name;
}
实体映射 - DAO接口
package com.jiang.jpa.otm.dao;
import com.jiang.jpa.otm.entity.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* @author Luosj
* @date 2020/2/16 5:28 PM
*/
@Repository
public interface ProductDao extends JpaRepository<Product, String> {
}
package com.jiang.jpa.otm.dao;
import com.jiang.jpa.otm.entity.ProductType;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* @author Luosj
* @date 2020/2/16 5:29 PM
*/
@Repository
public interface ProductTypeDao extends JpaRepository<ProductType, String> {
}
3、数据初始化操作
数据初始化过程需要保证One的一方存在数据, 才能实现多的一方数据存储
这里展示的是正确的代码
@Autowired
private ProductDao productDao;
@Autowired
private ProductTypeDao productTypeDao;
/**
*
* 数据初始化测试 - 先保证一的一方存在数据, 才能存储多的一方
*
*/
@Test
public void init(){
// one
ProductType type = new ProductType();
type.setId(String.valueOf(System.currentTimeMillis()));
type.setName("水果3");
// many
Product p1 = new Product(UUID.randomUUID().toString(), "苹果", type);
Product p2 = new Product(UUID.randomUUID().toString(), "梨子", type);
Product p3 = new Product(UUID.randomUUID().toString(), "香蕉", type);
// persistence
productTypeDao.save(type);
productDao.save(p1);
productDao.save(p2);
productDao.save(p3);
}
错误的代码
@Test
public void errorInit(){
// one
ProductType type = new ProductType();
type.setId(String.valueOf(System.currentTimeMillis()));
type.setName("水果3");
// many
Product p1 = new Product(UUID.randomUUID().toString(), "苹果", type);
Product p2 = new Product(UUID.randomUUID().toString(), "梨子", type);
Product p3 = new Product(UUID.randomUUID().toString(), "香蕉", type);
// persistence
productDao.save(p1);
productDao.save(p2);
productDao.save(p3);
productTypeDao.save(type);
}
执行这段代码会抛出的异常:
Caused by: javax.persistence.EntityNotFoundException: Unable to find com.jiang.jpa.otm.entity.ProductType with id 1581848679583
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$JpaEntityNotFoundDelegate.handleEntityNotFound(EntityManagerFactoryBuilderImpl.java:163)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:216)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:332)
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:108)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:74)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:118)
at org.hibernate.internal.SessionImpl.fireLoadNoChecks(SessionImpl.java:1168)
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1033)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:687)
at org.hibernate.type.EntityType.resolve(EntityType.java:464)
at org.hibernate.type.ManyToOneType.resolve(ManyToOneType.java:240)
at org.hibernate.type.EntityType.resolve(EntityType.java:457)
at org.hibernate.type.EntityType.replace(EntityType.java:358)
at org.hibernate.type.AbstractType.replace(AbstractType.java:164)
at org.hibernate.type.TypeHelper.replace(TypeHelper.java:204)
at org.hibernate.event.internal.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:488)
at org.hibernate.event.internal.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:241)
at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:318)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:172)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:70)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:108)
at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:775)
at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:762)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:314)
at com.sun.proxy.$Proxy70.merge(Unknown Source)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:557)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:371)
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:204)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:657)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:621)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:605)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:366)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
... 71 more
下一篇: 利用字节流和字节数组流是实现文件的复制
推荐阅读
-
MyBatis从入门到精通(十一):MyBatis高级结果映射之一对多映射
-
JPA中实现双向一对多的关联关系
-
JPA中实现单向一对多的关联关系
-
JSP开发之hibernate之单向多对一关联的实例
-
SpringDataJpa在一对多、多对多关系映射时出现*Error
-
hibernate多对一关联映射出现的java.lang.*Error问题
-
Mybatis04—注解开发实现CRUD以及实现一对一、一对多及多对多复杂关系映射
-
Mybatis常用的注解开发CRUD&&复杂关系映射(一对一,一对多)&&mybatis 基于注解的二级缓存
-
Mybatis使用注解实现一对多复杂关系映射
-
MyBatis高级映射(一对一、一对多、多对多、延迟加载)