JPA单向多对一实体映射

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值