精华内容
下载资源
问答
  • 一对一关联保存: ps:这里都是拿工作中的项目做例子,所有不会有完整的业务代码,提供思路 说明: 留言状态表: 记录用户的留言信息,如留言人openid,留言时间等…(主表) 用户留言内容表: 记录用户的留言内容,id与状态表...

    一对一关联保存:

    说明: 留言状态表: 记录用户的留言信息,如留言人openid,留言时间等…(主表)
    用户留言内容表: 记录用户的留言内容,id与状态表一对一(从表)

    留言表实体类配置:(主表)
    添加一对一关联的从表

    // one to one
        private com.rhtcms.cms.entity.main.CustomerMessageContent customerMessageContent;//对应内容表信息
    

    留言内容表配置:(从表)
    添加一对一关联的主表:

     //one to one
        private com.rhtcms.cms.entity.main.CustomerMessage customerMessage;//对应客户留言状态表
    

    留言表hbm.xml配置:(主表)
    1.主表id采用uuid随机生成
    2.设置one-to-one 的从表

    <id name="id" type="string" column="id"><generator class = "uuid"/></id>
    <one-to-one name="customerMessageContent" class="CustomerMessageContent"  cascade="all"></one-to-one>
    

    留言内容表hbm.xml配置:(从表)
    1.主键生成策略使用:foreign 使用另外一个相关联的对象的主键作为该对象主键。主要用于一对一关系中。
    2.设置one-to-one 的主表

    <id name="messageId" type="string" column="message_id">
                <generator class="foreign"><param name="property">customerMessage</param></generator>
    </id>
     
    <one-to-one name="customerMessage" class="CustomerMessage"  constrained="true"  ></one-to-one>
    

    保存方法:
    思路:1.保存时先set主表数据,先将主表保存
    2: set从表数据,其中关键一步,从表须set刚刚保存的主表,然后再保存从表

    CustomerMessage customerMessageSave = mng.save(customerMessage); //保存状态表信息,并获取uuid
    CustomerMessageContent customerMessageContent = new CustomerMessageContent();
                //首先对留言,反馈信息进行敏感词过滤
    String wordCensor = cmsMng.replaceSensitivity(questionText);
    customerMessageContent.setQuestionText(wordCensor);//设置内容表内容
    customerMessageContent.setCustomerMessage(customerMessageSave);//设置从表中主表的属性
    contentMng.save(customerMessageContent);//同时保存内容表信息
    

    一对多/多对一保存

    说明:1.活动表:保存活动信息,记录活动报名的信息,如场景,主办方,报名时间…(主表)
    2.自定义报名信息表,因为报名要素不确定性,eg: 报名要素有 ,电话,姓名,门票id依据…(从表)

    活动表实体类配置:(主表)
    1.添加自定义报名信息从表

    private Set<ActivitySign> signs = new HashSet<ActivitySign>();
    

    自定义报名要素实体类配置:(从表)
    1.添加关联的活动表实体类

    private Activity activity;//活动表信息
    

    活动表hbm.xml配置:(主表)
    1.主键采用 "native"策略(hilo+identity+sequence三选一)
    ps:根据底层数据库对自动生成标识符的能力来选择i dentity、sequence、hilo三种生成器中的一种,适合跨数据库平台开发
    2.配置一对多的报名信息从表

    <id name="id" type="java.lang.Integer" column="activity_id"><generator class="native"/></id>
    <set name="signs" cascade="save-update" lazy="false">
    			<cache usage="read-write"/>
    			<key column="activity_id" />
    			<one-to-many class="ActivitySign"/>
    </set>
    

    报名信息表:(从表)
    配置多对一: name:主表多对一的属性 ,class: 主表实体类 column: 多对一字段

    <id name="id" column="sign_id">
    			<generator class="native"></generator>
    </id>
    <many-to-one name="activity" class="Activity" column="activity_id"></many-to-one>
    

    保存方法:
    保存思路
    1:保存方法带两个参数: 参数1: 主表的数据 ;参数2: 从表的数据
    2.实现层首先保存主表,然后再遍历从表,还是一样的,从表先设置主表,然后再保存从表

    activityMng.save(bean,set);
    //......下面是save方法
     bean = dao.save(bean);
    // update by 2021年1月23日10:36:56 zqy 优化保存接口
     for (ActivitySign activitySign : set) {
     activitySign.setActivity(bean);
     signDao.save(activitySign);
     }
    
    展开全文
  • Mybatis一对一、一对多、多对多查询。+MYSQL

    万次阅读 多人点赞 2018-08-09 10:03:28
    场景:使用三张数据表:student学生表、teacher教师表、...一对一关系,从老师角度:老师对职位一对一 一对多关系,从职位角度:职位对老师一对多 多对多关系:查找被教授教导的所有学生(首先职位对老师一对多...

    场景:使用三张数据表:student学生表、teacher教师表、position职位表

    一个学生可以有多为老师、一位老师可以有多个学生、但是一个老师只能有一个职位:教授、副教授、讲师;但是一个职位可以有多个老师:例如教授可以多人

    这里则产生了:

    一对一关系,从老师角度:老师对职位一对一

    一对多关系,从职位角度:职位对老师一对多

    多对多关系:查找被教授教导的所有学生(首先职位对老师一对多,老师再对学生再对多、这里便有了一对多对多)

    数据表:

    老师表

    CREATE TABLE `tb_teacher` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `t_no` varchar(20) DEFAULT NULL,
      `t_name` varchar(20) DEFAULT NULL,
      `position_id` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
    
    /*Data for the table `tb_teacher` */
    
    insert  into `tb_teacher`(`id`,`t_no`,`t_name`,`position_id`) values
    (1,'163314001','张文远',1),
    (2,'163314002','赵传智',1),
    (3,'163314003','风清扬',2),
    (4,'163314004','王汇智',2),
    (5,'163314005','汪思远',3);

    学生表

    CREATE TABLE `tb_student` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `t_stu_name` varchar(20) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
    
    /*Data for the table `tb_student` */
    
    insert  into `tb_student`(`id`,`t_stu_name`) values 
    
    (1,'赵依'),
    
    (2,'钱迩'),
    
    (3,'张山'),
    
    (4,'李石'),
    
    (5,'王武'),
    
    (6,'马柳');

    职位表

    CREATE TABLE `tb_position` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `t_pos_name` varchar(20) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
    
    /*Data for the table `tb_position` */
    
    insert  into `tb_position`(`id`,`t_pos_name`) values 
    
    (1,'教授'),
    
    (2,'副教授'),
    
    (3,'讲师');

    最后是教师学生关系表

    CREATE TABLE `tb_stu_teach` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `t_stu_id` int(11) DEFAULT NULL,
      `t_teach_id` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;
    
    /*Data for the table `tb_stu_teach` */
    
    insert  into `tb_stu_teach`(`id`,`t_stu_id`,`t_teach_id`) values 
    
    (1,1,1),
    
    (2,1,2),
    
    (3,1,3),
    
    (4,2,2),
    
    (5,2,3),
    
    (6,2,4),
    
    (7,3,3),
    
    (8,3,4),
    
    (9,3,5),
    
    (10,4,4),
    
    (11,4,5),
    
    (12,4,1);
    

    最后在eclipse中的目录结构如下:

    希望您明白sqlMapConfig该如何配置,以及jdbc.properties和log4j的作用。

    贴出POJO中的三个实体(注意:以下的POJO都用了lombok来快速生成setter和getter等,lomok具体使用,请见此文):

    Position.java

    package com.pojo;
    
    import java.io.Serializable;
    
    import lombok.Data;
    
    @Data
    public class Position implements Serializable {
    	private int id;
    	private String name;
    	
    	private Teacher teacher;
    
    }
    

    Student.java

    package com.pojo;
    
    import java.io.Serializable;
    import java.util.List;
    
    import lombok.Data;
    
    @Data
    public class Student implements Serializable {
    	private String id;
    	private String name;
    	
    	private List<Teacher> list;
    }

    Teacher.java

    package com.pojo;
    
    import java.io.Serializable;
    import java.util.List;
    
    import lombok.Data;
    
    @Data
    public class Teacher implements Serializable {
    	private int id;
    	
    	private String no;
    	private String name;
    	private List<Student> studentList;
    	
    	private Position pos;
    }
    

    注意:关系表不用以实体表示出来,表示外键关系的ID也不用写在实体中(一般我们也不使用外键)

     

    再贴另一个MybatisUtil.java工具类

    package com.util;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    
    public class MyBatisUtil {
    	private static SqlSessionFactory sqlSessionFactory = null;
    	
    	static {
    		String resource = "sqlMapConfig.xml";
    		// 首先要加载核心配置文件:从classpath下开始找。
    		InputStream in;
    		try {
    			in = Resources.getResourceAsStream(resource);
    			
    			sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
    		} catch (IOException e) {
    			throw new RuntimeException(e.getMessage());
    		}	
    	}
    	
    	public static SqlSession getSqlSession() {
    		
    		return sqlSessionFactory.openSession();
    	}
    	
    	public static SqlSessionFactory getSqlSessionFactory() {
    		return sqlSessionFactory;
    	}
    }
    

    一对一:老师对职位

    TeacherMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.mapper.TeacherMapper">
    	<resultMap type="Teacher" id="teacherPositionResultMap">
    		<id property="id" column="id"/>
    		<result property="no" column="t_no"/>
    		<result property="name" column="t_name"/>
    		<!-- association:配置的一对一属性 -->
    		<!-- property:名字
    			 javaType:类型
    		 -->
    		<association property="pos" javaType="Position">
    			<id property="id" column="id"/>
    			<result property="name" column="t_pos_name"/>
    		</association>
    	</resultMap>
    	
    	<!-- 一对一关联查询,查询老师及其对应的职位 -->
    	<!-- 注意:id不能相同,当多个值传入,比如包装类的时候,我们才能够用SQL片段的形式来做if判断,单个值是不行的 -->
    	<select id="queryTeacherPositionResultMapById" resultMap="teacherPositionResultMap" parameterType="Integer">
    		SELECT *
    		FROM tb_teacher t
    		LEFT JOIN tb_position p
    		ON t.position_id = p.id
    		where t.id = #{id}
    	</select>
    
    	<select id="queryTeacherPositionResultMap" resultMap="teacherPositionResultMap">
    		SELECT *
    		FROM tb_teacher t
    		LEFT JOIN tb_position p
    		ON t.`position_id` = p.id
    	</select> 
    </mapper>

    TeacherMapper.java接口

    package com.mapper;
    
    import java.util.List;
    
    import com.pojo.Teacher;
    
    public interface TeacherMapper {
    	public List<Teacher> queryTeacherPositionResultMap();
    	
    	public Teacher queryTeacherPositionResultMapById(Integer id);
    }
    

    测试一对一:

    package com.test;
    
    import java.util.List;
    
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import com.mapper.TeacherMapper;
    import com.pojo.Teacher;
    import com.util.MyBatisUtil;
    
    public class TestOneToOne {
    	@Test
    	public void testOneToOne() {
    		SqlSession sqlSession = MyBatisUtil.getSqlSession();
    		System.err.println(sqlSession);
    		
    		TeacherMapper teacherMapper = sqlSession.getMapper(TeacherMapper.class);
    		
    		List<Teacher> list = teacherMapper.queryTeacherPositionResultMap();
    		
    		System.out.println(list);
    		
    		Teacher teacher = teacherMapper.queryTeacherPositionResultMapById(1);
    		System.out.println(teacher);
    	}
    }
    

     

    一对多:职位对老师

    PositionMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.mapper.PositionMapper"> 
    	<resultMap type="Position" id="positionTeacherResultMap">
    		<id property="id" column="id"/>
    		<result property="name" column="t_pos_name"/> <!-- t_name -->
    		<!-- 
    		property同association中的一样是属性名称(javaBean中的);
    		javaType也同association中的是类型,
    		最后多了一个OfType,因为一对多,不像一对一是单个的!我们这里是List集合,list和List都可以。
    		一对多其中是放的一个集合所以这个是集合的泛型的类型,这里我们的list中放的是Teacher:
    		所以这里是Teacher。
    		 -->
    		<collection property="teacherList" javaType="list" ofType="Teacher" >
    			<!-- 
    				一对多出现的问题:
    					当数据库表中,主表的主键id和明细表的 ...
    					当表中的字段名相同时怎么办?多表联查?
    					
    					注意:Mybatis中做多表联查的时候,不管是
    					一对一、一对多、一对多对多:多对多:
    					都不能有字段重名的情况:不管是主键还是普通字段。
    					一旦字段重名的话,就会造成数据少自动赋值,或者覆盖,甚至重复赋值!
    					规避和解决此类问题的方法:
    						1.尽量不要表间重名,mybatis里处理起来很麻烦!id和普通字段都是。
    						但是在表多的时候,很难不会出现字段重名的情况。主键id最容易重名!
    						那么就要用以下的办法了!
    						
    						2.在mybatis中写原生SQL进行查询的时候,查的字段尽可能的少,这
    						也影响速率,强烈禁止使用*,用多少查多少!这样也能及时发现字段重
    						名的情况!
    						
    						3.最后如果真的需要查出重名的字段,并且修改数据库字段名造成的更改
    						过大,这里推荐的方式是给字段取别名,在写resultMap映射的时候,其
    						中的column属性就填写SQL语句中查出字段取的别名,这样就能解决重复
    						问题了!
    			 -->
    			<id property="id" column="t_id"/>
    			<result property="no" column="t_no"/>
    			<result property="name" column="t_name"/>	
    		</collection>
    	</resultMap>
    	
    	<select id="queryPositionTeacherResultMapById" resultMap="positionTeacherResultMap" 
    		parameterType="Integer">
    		<!-- 
    		SELECT *
    		FROM tb_position p
    		LEFT JOIN tb_teacher t
    		ON p.id = t.position_id
    		WHERE p.id = #{id}
    		-->
    		
    		SELECT 
    		p.*, 
    		t.id t_id,
    		t.t_name,
    		t.t_no
    		FROM tb_position p
    		LEFT JOIN tb_teacher t
    		ON p.id = t.position_id
    		WHERE p.id = #{id}
    	</select>
    	
    	<select id="queryPositionTeacherResultMap" resultMap="positionTeacherResultMap" >
    		<!-- 
    		SELECT *
    		FROM tb_position p
    		LEFT JOIN tb_teacher t
    		ON p.id = t.position_id
    		-->
    		
    		SELECT 
    		p.*, 
    		t.id t_id,
    		t.t_name,
    		t.t_no
    		FROM tb_position p
    		LEFT JOIN tb_teacher t
    		ON p.id = t.position_id
    		
    	</select>
    </mapper>
    
    

    TeacherMapper.java接口

    package com.mapper;
    
    import java.util.List;
    
    import com.pojo.Position;
    
    public interface PositionMapper {
    	public Position queryPositionTeacherResultMapById(Integer id);
    	
    	public List<Position> queryPositionTeacherResultMap();
    }
    

    测试一对多:

    package com.test;
    
    import java.util.List;
    
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import com.mapper.PositionMapper;
    import com.pojo.Position;
    import com.util.MyBatisUtil;
    
    public class TestOneToMany {
    	
    	@Test
    	public void testOneToMany() {
    		SqlSession sqlSession = MyBatisUtil.getSqlSession();
    		PositionMapper positionMapper = sqlSession.getMapper(PositionMapper.class);
    		List<Position> list = positionMapper.queryPositionTeacherResultMap();
    		
    		System.out.println(list);
    		
    		Position pos = positionMapper.queryPositionTeacherResultMapById(1);
    		
    		System.out.println(pos);
    	}
    }
    

    多对多:职位是教授的老师教授的所有学生(一对多对多:只要你愿意可以一直对多下去...)

    PositionMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.mapper.PositionMapper"> 
    	<resultMap type="Position" id="positionStudentResultMap">
    		<!-- <id property="id" column="id"/> -->
    		<result property="name" column="t_pos_name"/>
    		<collection property="teacherList" javaType="list" ofType="Teacher" >
    			<result property="name" column="t_name"/>	
    			<collection property="studentList" javaType="list" ofType="Student">
    				<result property="name" column="t_stu_name"/>
    			</collection>
    		</collection>
    	</resultMap>
    	
    	<select id="selectPositionStudentByPosId" resultMap="positionStudentResultMap" parameterType="Integer">
    		SELECT p.t_pos_name, t.t_name, s.t_stu_name
    		FROM tb_position p
    		INNER JOIN tb_teacher t ON p.id = t.position_id
    		LEFT JOIN tb_stu_teach st ON st.t_teach_id = t.id
    		LEFT JOIN tb_student s ON s.id = st.t_stu_id
    		WHERE p.id = #{id}
    	</select>
    </mapper>
    
    

    PositionMapper.java接口

    package com.mapper;
    
    import com.pojo.Position;
    
    public interface PositionMapper {
    	public Position selectPositionStudentByPosId(Integer id);
    	
    }
    

    测试:

    package com.test;
    
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import com.mapper.PositionMapper;
    import com.pojo.Position;
    import com.util.MyBatisUtil;
    
    public class TestManyToMany {
    	
    	@Test
    	public void testManyToMany() {
    		SqlSession sqlSession = MyBatisUtil.getSqlSession();
    		PositionMapper positionMapper = sqlSession.getMapper(PositionMapper.class);
    		Position pos = positionMapper.selectPositionStudentByPosId(1);
    		
    		System.out.println(pos);
    	}
    }

     

    展开全文
  • 数据库一对一、一对多、多对多关系

    万次阅读 多人点赞 2018-01-10 15:54:10
    数据库一对一、一对多、多对多关系  本来数据库一对一、一对多、多对多关系并不复杂,但是最近在理解的时候感觉又感觉多了写新意,所以现在在来总结一下吧 一、首先给出三种关系的实例 1、一对一关系实例 ...
    数据库一对一、一对多、多对多关系

         本来数据库一对一、一对多、多对多关系并不复杂,但是最近在理解的时候感觉又感觉多了写新意,所以现在在来总结一下吧
    一、首先给出三种关系的实例
    1、一对一关系实例
       * 一个人对应一张身份证,一张身份证对应一个人
    2、一对多关系实例
       * 一个班级拥有多个学生,一个学生只能够属于某个班级
    3、多对多实例
       * 一个学生可以选修多门课程,一个课程可以被多个学生选修

    二、一对一关系

    一对一关系是最好理解的一种关系,在数据库建表的时候可以将人表的主键放置与身份证表里面,也可以将身份证表的主键放置于人表里面

    三、一对多关系


    • 班级是1端,学生是多端,结合面向对象的思想,1端是父亲,多端是儿子,所以多端具有1端的属性,也就是说多端里面应该放置1端的主键,那么学生表里面应该放置班级表里面的主键

    四、多对多关系

    对于多对多关系,需要转换成1对多关系,那么就需要一张中间表来转换,这张中间表里面需要存放学生表里面的主键和课程表里面的主键,此时学生与中间表示1对多关系,课程与中间表是1对多关系,学生与课程是多对多关系

    四、总结

    总而言之,最重要的关系就是1对多关系,根据面向对象思想在建表的时候将1端主键置于多端即可。


    展开全文
  • Spring Data JPA 之 一对一,一对多,多对多 关系映射

    万次阅读 多人点赞 2018-06-10 17:01:10
    JPA使用@OneToOne来标注一对一的关系。 实体 People :用户。 实体 Address:家庭住址。 People 和 Address 是一对一的关系。 这里用两种方式描述JPA的一对一关系。 一种是通过外键的方式(一个实体通过外键...

     

    一、@OneToOne关系映射

    JPA使用@OneToOne来标注一对一的关系。

    实体 People :用户。

    实体 Address:家庭住址。

    People 和 Address 是一对一的关系。

    这里用两种方式描述JPA的一对一关系。

    一种是通过外键的方式(一个实体通过外键关联到另一个实体的主键);

    另外一种是通过一张关联表来保存两个实体一对一的关系。

     

    1、通过外键的方式

    people 表(id,name,sex,birthday,address_id

    address 表(id,phone,zipcode,address)

     

    People.java

    1. @Entity
    2. public class People {
    3.     @Id
    4.     @GeneratedValue(strategy = GenerationType.IDENTITY)
    5.     @Column(name = "id", nullable = false)
    6.     private Long id;//id
    7.     @Column(name = "name", nullable = true, length = 20)
    8.     private String name;//姓名
    9.     @Column(name = "sex", nullable = true, length = 1)
    10.     private String sex;//性别
    11.     @Column(name = "birthday", nullable = true)
    12.     private Timestamp birthday;//出生日期
    13.     @OneToOne(cascade=CascadeType.ALL)//People是关系的维护端,当删除 people,会级联删除 address
    14.     @JoinColumn(name = "address_id", referencedColumnName = "id")//people中的address_id字段参考address表中的id字段
    15.     private Address address;//地址
    16. }

    关联的实体的主键一般是用来做外键的。但如果此时不想主键作为外键,则需要设置referencedColumnName属性。当然这里关联实体(Address)的主键 id 是用来做主键,所以这里第20行的 referencedColumnName = "id" 实际可以省略。

     

     

    Address.java

    1. @Entity
    2. public class Address {
    3.     @Id
    4.     @GeneratedValue(strategy = GenerationType.IDENTITY)
    5.     @Column(name = "id", nullable = false)
    6.     private Long id;//id
    7.     @Column(name = "phone", nullable = true, length = 11)
    8.     private String phone;//手机
    9.     @Column(name = "zipcode", nullable = true, length = 6)
    10.     private String zipcode;//邮政编码
    11.     @Column(name = "address", nullable = true, length = 100)
    12.     private String address;//地址
    13.     //如果不需要根据Address级联查询People,可以注释掉
    14. //    @OneToOne(mappedBy = "address", cascade = {CascadeType.MERGE, CascadeType.REFRESH}, optional = false)
    15. //    private People people;
    16. }

     

    2、通过关联表的方式来保存一对一的关系。

    people 表(id,name,sex,birthday)

    address 表 (id,phone,zipcode,address)

    people_address (people_idaddress_id)

    只需要创建 People 和 Address 两个实体

     

    People.java

    1. @Entity
    2. public class People {
    3.     @Id
    4.     @GeneratedValue(strategy = GenerationType.IDENTITY)
    5.     @Column(name = "id", nullable = false)
    6.     private Long id;//id
    7.     @Column(name = "name", nullable = true, length = 20)
    8.     private String name;//姓名
    9.     @Column(name = "sex", nullable = true, length = 1)
    10.     private String sex;//性别
    11.     @Column(name = "birthday", nullable = true)
    12.     private Timestamp birthday;//出生日期
    13.     @OneToOne(cascade=CascadeType.ALL)//People是关系的维护端
    14.     @JoinTable(name = "people_address",
    15.             joinColumns = @JoinColumn(name="people_id"),
    16.             inverseJoinColumns = @JoinColumn(name = "address_id"))//通过关联表保存一对一的关系
    17.     private Address address;//地址
    18. }

     

    Address.java

    不变

     

    二、@OneToMany 和 @ManyToOne

    实体 Author:作者。

    实体 Article:文章。

    Author 和 Article 是一对多关系(双向)。那么在JPA中,如何表示一对多的双向关联呢?

    JPA使用@OneToMany和@ManyToOne来标识一对多的双向关联。一端(Author)使用@OneToMany,多端(Article)使用@ManyToOne。

    JPA规范中,一对多的双向关系由多端(Article)来维护。就是说多端(Article)为关系维护端,负责关系的增删改查。一端(Author)则为关系被维护端,不能维护关系。

    一端(Author)使用@OneToMany注释的mappedBy="author"属性表明Author是关系被维护端

    多端(Article)使用@ManyToOne和@JoinColumn来注释属性 author,@ManyToOne表明Article是多端,@JoinColumn设置在article表中的关联字段(外键)

     

    Author.java

    1. @Entity
    2. public class Author {
    3.     @Id // 主键
    4.     @GeneratedValue(strategy = GenerationType.IDENTITY) // 自增长策略
    5.     private Long id; //id
    6.     @NotEmpty(message = "姓名不能为空")
    7.     @Size(min=2, max=20)
    8.     @Column(nullable = false, length = 20)
    9.     private String name;//姓名
    10.     @OneToMany(mappedBy = "author",cascade=CascadeType.ALL,fetch=FetchType.LAZY)
    11.     //级联保存、更新、删除、刷新;延迟加载。当删除用户,会级联删除该用户的所有文章
    12.     //拥有mappedBy注解的实体类为关系被维护端
    13.      //mappedBy="author"中的author是Article中的author属性
    14.     private List<Article> articleList;//文章列表
    15. }

     

    Article.java

    1. @Entity
    2. public class Article {
    3.     @Id
    4.     @GeneratedValue(strategy = GenerationType.IDENTITY) // 自增长策略
    5.     @Column(name = "id", nullable = false)
    6.     private Long id;
    7.     @NotEmpty(message = "标题不能为空")
    8.     @Size(min = 2, max = 50)
    9.     @Column(nullable = false, length = 50// 映射为字段,值不能为空
    10.     private String title;
    11.     @Lob  // 大对象,映射 MySQL 的 Long Text 类型
    12.     @Basic(fetch = FetchType.LAZY) // 懒加载
    13.     @NotEmpty(message = "内容不能为空")
    14.     @Size(min = 2)
    15.     @Column(nullable = false// 映射为字段,值不能为空
    16.     private String content;//文章全文内容
    17.     @ManyToOne(cascade={CascadeType.MERGE,CascadeType.REFRESH},optional=false)//可选属性optional=false,表示author不能为空。删除文章,不影响用户
    18.     @JoinColumn(name="author_id")//设置在article表中的关联字段(外键)
    19.     private Author author;//所属作者
    20. }

     

    最终生成的表结构

    article 表(id,title,conten,author_id)

    author 表(id,name)

     

    三、多对多 @ManyToMany

    实体 User:用户。

    实体 Authority:权限。

    用户和权限是多对多的关系。一个用户可以有多个权限,一个权限也可以被很多用户拥有。

    JPA中使用@ManyToMany来注解多对多的关系,由一个关联表来维护。这个关联表的表名默认是:主表名+下划线+从表名。(主表是指关系维护端对应的表,从表指关系被维护端对应的表)。这个关联表只有两个外键字段,分别指向主表ID和从表ID。字段的名称默认为:主表名+下划线+主表中的主键列名,从表名+下划线+从表中的主键列名。

     

    需要注意的:

    1、多对多关系中一般不设置级联保存、级联删除、级联更新等操作

    2、可以随意指定一方为关系维护端,在这个例子中,我指定 User 为关系维护端,所以生成的关联表名称为: user_authority,关联表的字段为:user_id 和 authority_id。

    3、多对多关系的绑定由关系维护端来完成,即由 User.setAuthorities(authorities) 来绑定多对多的关系。关系被维护端不能绑定关系,即Game不能绑定关系。

    4、多对多关系的解除由关系维护端来完成,即由Player.getGames().remove(game)来解除多对多的关系。关系被维护端不能解除关系,即Game不能解除关系。

    5、如果 User 和 Authority 已经绑定了多对多的关系,那么不能直接删除 Authority,需要由 User 解除关系后,才能删除 Authority。但是可以直接删除 User,因为 User 是关系维护端,删除 User 时,会先解除 User 和 Authority 的关系,再删除 Authority

     

    User.java

    1. @Entity
    2. public class User {
    3.     @Id
    4.     @GeneratedValue(strategy = GenerationType.IDENTITY)
    5.     private Long id;
    6.     @NotEmpty(message = "账号不能为空")
    7.     @Size(min=3, max=20)
    8.     @Column(nullable = false, length = 20, unique = true)
    9.     private String username; // 用户账号,用户登录时的唯一标识
    10.     @NotEmpty(message = "密码不能为空")
    11.     @Size(max=100)
    12.     @Column(length = 100)
    13.     private String password; // 登录时密码
    14.     @ManyToMany
    15.     @JoinTable(name = "user_authority",joinColumns = @JoinColumn(name = "user_id"),
    16.     inverseJoinColumns = @JoinColumn(name = "authority_id"))
    17.     //1、关系维护端,负责多对多关系的绑定和解除
    18.     //2、@JoinTable注解的name属性指定关联表的名字,joinColumns指定外键的名字,关联到关系维护端(User)
    19.     //3、inverseJoinColumns指定外键的名字,要关联的关系被维护端(Authority)
    20.     //4、其实可以不使用@JoinTable注解,默认生成的关联表名称为主表表名+下划线+从表表名,
    21.     //即表名为user_authority
    22.     //关联到主表的外键名:主表名+下划线+主表中的主键列名,即user_id
    23.     //关联到从表的外键名:主表中用于关联的属性名+下划线+从表的主键列名,即authority_id
    24.     //主表就是关系维护端对应的表,从表就是关系被维护端对应的表
    25.     private List<Authority> authorityList;
    26. }

    注意:如注释中所言,上面的第20-21行的@JoinTable可以省略,默认可以生成

     

    Authority.java

    1. @Entity
    2. public class Authority {
    3.     @Id
    4.     @GeneratedValue(strategy = GenerationType.IDENTITY)
    5.     private Integer id;
    6.     @Column(nullable = false)
    7.     private String name; //权限名
    8.     @ManyToMany(mappedBy = "authorityList")
    9.     private List<User> userList;
    10. }

     

    测试 添加

    1. @SpringBootTest
    2. @RunWith(SpringRunner.class)
    3. public class UserRepositoryTest {
    4.     @Autowired
    5.     private UserRepository userRepository;
    6.     @Autowired
    7.     private AuthorityRepository authorityRepository;
    8.     @Test
    9.     public void saveAuthority() {
    10.         Authority authority = new Authority();
    11.         authority.setId(1);
    12.         authority.setName("ROLE_ADMIN");
    13.         authorityRepository.save(authority);
    14.     }
    15.     @Test
    16.     public void saveUser() {
    17.         User user = new User();
    18.         user.setUsername("admin");
    19.         user.setPassword("123456");
    20.         Authority authority = authorityRepository.findById(1).get();
    21.         List<Authority> authorityList = new ArrayList<>();
    22.         authorityList.add(authority);
    23.         user.setAuthorList(authorityList);
    24.         userRepository.save(user);
    25.     }
    26. }

    先运行 saveAuthority 添加一条权限记录,

    然后运行 saveUser 添加一条用户记录,与此同时,user_authority 表中也自动插入了一条记录

     

    测试 删除

    删除用户

    1. @SpringBootTest
    2. @RunWith(SpringRunner.class)
    3. public class UserRepositoryTest {
    4.     @Autowired
    5.     private UserRepository userRepository;
    6.     @Test
    7.     public void deleteUser() {
    8.         userRepository.deleteById(1L);
    9.     }
    10. }

    user 表中删除一条记录,同时 user_authority 能够级联删除一条记录

     

     

    参考:http://www.cnblogs.com/luxh/archive/2012/05/30/2527123.html

     

     

    再次更新

    其中 @OneToMany  和 @ManyToOne 用得最多,这里再补充一下

     

    关于级联,一定要注意,要在关系的维护端,即 One 端。

    比如 作者和文章,作者是One,文章是Many;文章和评论,文章是One,评论是Many。

    cascade = CascadeType.ALL 只能写在 One 端,只有One端改变Many端,不准Many端改变One端。

    特别是删除,因为 ALL 里包括更新,删除。

    如果删除一条评论,就把文章删了,那算谁的。所以,在使用的时候要小心。一定要在 One 端使用。

    举例

    One 端

     

    Spring Data JPA 之 一对一,一对多,多对多 关系映射

     

    Many 端

     

    本文转自:Spring Data JPA 之 一对一,一对多,多对多 关系映射 | 言曌博客

    展开全文
  • MyBatis实现一对一,一对多关联查询

    万次阅读 多人点赞 2019-09-25 00:20:31
    MyBatis如何实现一对一,一对多查询的? 可以通过关联查询实现。关联查询是几个表联合查询,只查询一次,通过在resultMap里面的association,collection节点配置一对一,一对多的类就可以完成 具体实现如下 准备...
  • mybatis-generator这是原来的github地址 现在在此基础上添加了一对一和一对多映射配置,配置在table标签上 如果需要一对一配置生成,需要添加插件配置 在context中添加如下配置<!-- 生成一对一配置 --> ...
  • 数据库建模多表一对多和多对一、一对一、多对多

    万次阅读 多人点赞 2018-06-13 18:29:30
    ----------------------------------------数据库建模多表一对多和多对一、一对一、多对多-------------------------------------------------------一对多和多对一我们再创建一张订单表,用户表和订单表之间的关系...
  • 其实一对一和一对多映射,在前面的配置中已经接触到,我没在日志里直接说明,是因为想要在之后写一篇总结日志(就是本篇),总结这些高级映射的配置。例如一对一查询在关联的嵌套结果集查询中就涉及到,一对多查询则...
  • Flask04-模型的一对一,一对多,多对多

    万次阅读 2018-06-23 23:22:29
    1. 一对一关系主要通过一个 uselist=False 来约束, 因为在一对多中通过 查询得到的是一个列表, 所以, uselist=False禁用列表, 使我们只能查找到一个, 就构成了一对一关系人和身份证的一对一一关系 ​ from flask_...
  • MyBatis关联映射:一对一、一对多

    万次阅读 2017-06-20 21:00:59
    一、一对一场景:生活中每一个人都有一个身份证,这是最简单的一对一的关系。(1)用户表(2)身份证表(3)用户实体对象,com.xuliugen.mybatis.demo.bean.User(4)身份证实体对象,...
  • 一对一操作 一对多操作 多对多操作 常用方法 了不起的双下划线 准备表 创建如下几张表 from django.shortcuts import HttpResponse, render, redirect from django.db import models class Class...
  • 转自:https://blog.csdn.net/zhongshan_c/article/details/8210196数据库建表-- 一对多/多对一/一对一/多对多 关系 关联映射:一对多/多对一存在最普遍的映射关系,简单来讲就如球员与球队的关系;一对多:从...
  • 数据库一对一、一对多、多对多设计

    万次阅读 多人点赞 2016-11-18 10:21:03
    做一个项目,必然是少不了数据库... 数据库实体间有三种对应关系:一对一,一对多,多对多。  一对一关系示例: 一个学生对应一个学生档案材料,或者每个人都有唯一的身份证编号。  一对多关系示例:
  • MySQL关系&一对多&一对一&多对多

    千次阅读 2018-09-04 09:34:36
    将实体与实体的关系,反应到最终数据库表的设计上,将关系分为三种:一对一,一对多(多对一)和多对多,所有的关系都是表与表之间的关系 一对一 一对一:一张表的一条记录只能与另外一条记录进行对应,反之亦然 ...
  • 关联映射:一对一 一对一关系就如球队与球队所在地址之间的关系,一支球队仅有一个地址,而一个地址区也仅有一支球队。 数据表间一对一关系的表现有两种,一种是外键关联,一种是主键关联。 一对一外键关联,图示...
  • 假设有 A,B 两个实体,首先判断一个 A 对应...如果两边都是 1:1,那么 A 与 B 就是一对一的关系; 如果两边只有一个 1:n,那么 A 与 B 就是一对多的关系; 如果两边都是 1:n,那么 A 与 B 就是多对多的关系 ...
  • 一对一关系实例 ***********一个学生对应唯一的身份证号码。 一对多关系实例 ***********一个班级对应多位学生。 多对多关系实例 ***********一位学生可以选多门课程,一门课程也对应多位学生。 一...
  • Mybatis 关联查询(一对一与一对多)

    千次阅读 2019-08-18 19:55:11
    1、一对一查询 需求:查询所有订单信息,关联查询下单用户信息。 注意:因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的订单信息则...
  • tp5.1模型一对一和一对多查询

    千次阅读 2018-10-11 17:58:32
    不管是一对一还是一对多,我们进行总结一下, 一共是三个参数,第一个参数不用说是需要关联的模型名 第二个参数跟第三个参数,我们也不需要理解谁是主键谁是外键了 在操作过程中,总结出,一对一是从本表进行触发...
  • Mybatis关联查询一对一和一对多的实现

    万次阅读 多人点赞 2015-05-13 09:20:43
    本文主要讲了使用Mybatis实现关联查询,分为一对一和一对多两种情况,最后并对ResultMap进行一个简要说明。
  • 数据库实体间有三种关联关系:一对一,一对多,多对多。一对一实例:一个学生只有个身份证编号。 一对多实例:一个班级有多个学生。 多对多实例:多对多就是双向一对多,一个学生可以选择多门课,一门课也有多名学生...
  • 数据库:一对一,一对多,多对多

    千次阅读 2018-08-16 10:08:11
    一对一:就是说A表中的一条记录对应着B表的一条记录。大家可能会觉得这不是变得复杂了吗?其实不然,如果,当一张表的字段过于太多,而很多字段可能只有在某些情况下,才会使用到,这时也可以考虑使用一对一设计。 ...
  • 使用springboot完成一对一,一对多: 一对一: 主要是与   一对多: 主要是 多对多:
  • 一对一的关系:例如 一个人只能有一个身份证,一个身份证只能有一个人 6 表与表一对多的关系: 在一对多时 多的表中添加一个外键,用来和一的表的主键。产生联系。 7 多对多关系介绍: 多对对建表原则:创建第三张表
  • 一对一的关系最简单,一个实体创建一张表就行了; 一对多和多对一的关系建表原则是一样的,在多的一方用外键列引用‘一’的一方的主键,来保证两者之间的联系; 多对多的关系,就是新创建一张中间表,以保证二者...
  • mybatis实现多表一对一,一对多,多对多关联查询

    万次阅读 多人点赞 2018-02-03 15:40:08
    1、一对一 关键字:association 作用:针对pojo对象属性的映射  property:pojo的属性名  javaType:pojo类名 (1) 嵌套结果: 使用嵌套结果映射来处理重复的联合结果的子集 <!-- 1、...
  • 关联映射:一对多/多对一 存在最普遍的映射关系,简单来讲就如球员与球队的关系; 一对多:从球队角度来说一个球队拥有多个球员 即为一对多 ...数据表间一对一关系的表现有两种,一种是外键关联
  • 关联映射:一对多/多对一 存在最普遍的映射关系,简单来讲就如球员与球队的关系; 一对多:从球队角度来说一个球队拥有多个球员 即为一对多 多对一:从球员角度来说多个球员属于一个球队 即...数据表间一对一关系的表现
  • java实现简单的tcp一对一及一对多连接。
  • 第一种:resultMap实现一对一的查询1.1.1 使用resultMap映射的思路使用resultMap将查询结果中的订单信息映射到Orders对象中,在orders类中添加User属性,将关联查询出来的用户信息映射到orders对象中的user属性中。...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,662,171
精华内容 1,464,868
关键字:

一对一