数据库开发

泄露秘密 提交于 2020-03-11 18:01:48

#MyBatis进阶

  • 复杂Java对象与多张数据库表之间的映射关系
  • 配置数据库连接池提高MyBatis对后端数据库访问的性能 ##更为复杂的E-R图 学员对课程是多对多关系,而教员与课程是一对多关系
    • 学员 User
    • 课程 Couser
    • 教员 Author

以上实体对应的关系图如下:
输入图片说明
以上关系对应的数据库表关系如下:
输入图片说明
各个实体都具有对应的属性,但是由于User与Cousre是多对多关系,则我们还需要一个多对多关系表UserCourse,来保存User与Course的关系。由于Teacher与Course是一对多的关系,则我们在Course中添加Teacher的唯一标示。

##复杂对象关系

  • Java对象
    • 关联 输入图片说明
    • 容器
    • 嵌套 输入图片说明

##ResultMap 复杂Java关系映射解决,帮助我们复杂对象到多张数据库表的转换。

  • ResultMap元素师MyBatis中最重要最强大的元素。
  • 数据库永远不是你想要的或需要它们是什么样的。
  • ResultMap可以实现复杂查询结果到复杂对象关联关系的转化。

##Constructor 通过构造方法的方式,对对象进行赋值建立映射关系,这种方法一般用于处理关联时,使用。

  • 类在实例化时,用对象的构造函数注入到对象中:
    • idArg - ID参数;标记结果作为ID可以帮助提高整体效能
    • arg - 注入到构造方法的一个普通结果

##ResultMap通过构造函数实例 ###定义了MyBatis-conf.xml的SqlSessionFactory的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <!-- 事务管理 -->
            <transactionManager type="jdbc">
                <!--<property name="..." value="..."/>-->
            </transactionManager>
            <!-- 数据库连接数据源 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://192.168.1.200/cloud_study"/>
                <property name="username" value="root"/>
                <property name="password" value="dVHJtG0T:pf*"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="com/hava/cloud_study/repository/userMapper.xml" />
    </mappers>
</configuration>

###声明Java对象 ####User

public class User {
    private int id;
    private String userName;
    private String corp;
    private List<Course> courses;
    ...
    //Getter and Setter
}

####Course

public class Course {
    private int id;
    private String courseName;
    private Teacher teacher;
    ...
    //Getter and Setter
}

####Teacher

public class Teacher {
    private int id;
    private String teacherName;
    ...
    //Getter and Setter
}

###UserOp接口 我们通过获取用户的方式,来获取三张数据库表之间的连接查询,并建立三个对象之间的连接关系。

package com.hava.cloud_study.repository;

import com.hava.cloud_study.entity.User;

/**
 * Created by zhanpeng on 09/10/2016.
 */
public interface UserOp {

    public User getUser(int id);

}

###resultMap核心Mapper 在Mapper文件中添加resultMap的标签属性,id在所表示的这个resultMap将会被用在增持该查中设置中。type表示为要转换的对象结果。constructor标签下面表示的是该类的属性(非连接关系的属性),idArg表示为行记录的唯一id,arg表示一般属性。column必须和对象的属性名称相一致。javaType对应的Java的数据类型。

<?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.hava.cloud_study.repository.UserOp">
    <select id="getUser" parameterType="int" resultMap="UserMap">
        select u.id
        as userId,userName,courseName,corp,c.id as courseId,teacher.id as
        teacherId,teacherName from user u left
        join
        UserCourse uc on u.id
        =uc.user_id left join course c on c.id =
        uc.course_id left join teacher
        on teacher.id = c.teacher_id where u.id
        = #{id}
    </select>

    <resultMap id="UserMap"
               type="com.hava.cloud_study.entity.User">
        <constructor>
            <idArg column="userId" javaType="int" />
            <arg column="userName" javaType="String" />
            <arg column="corp" javaType="String" />
        </constructor>
        <collection property="courses"
                    ofType="com.hava.cloud_study.entity.Course">
            <id property="id" column="courseId" />
            <result property="courseName" column="courseName" />
            <association property="teacher" column="teacher_id"

                         javaType="com.hava.cloud_study.entity.Teacher">
                <id property="id" column="teacherId" />
                <result property="teacherName" column="teacherName" />
            </association>
        </collection>
    </resultMap>
</mapper>

必须在User中加入构造函数,构造函数的属性必须和constructor一致。

###执行

package com.hava.cloud_study.service;

import java.io.InputStream;

import com.hava.cloud_study.entity.User;
import com.hava.cloud_study.repository.UserOp;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class HelloMyBatis {
    public static void main(String[] args) {
        // 1. 声明配置⽂件的⺫录渎职
        String resource = "mybatis-conf.xml";
        // 2. 加载应⽤配置⽂件
        InputStream is = HelloMyBatis.class.getClassLoader()
                .getResourceAsStream(resource);
        // 3. 创建SqlSessonFactory
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
                .build(is);
        // 4. 获取Session
        SqlSession session = sessionFactory.openSession();
        try {
            // 5. 获取操作类
            UserOp userOp = session.getMapper(UserOp.class);
            // 6. 完成查询操作
            User user = userOp.getUser(25);
            System.out.println(user.getId() + " " + user.getUserName() + " ");
                    System.out.println(user.getCourses().get(0).getCourseName() +" ");
            System.out.println(user.getCourses().get(0).getTeacher().getTeacherName());
        } finally {
            // 7.关闭Session
            session.close();
        }
    }
}

###执行结果

25 ZhanPeng 
Java 
OldTeacher

##Collection 容器 User当中的List注入,也是通过resultMap,通过collection的标签来实现。

  • 实现一对多的关联
    • id - 一个ID结果;标记结果作为ID可以帮助提高整体效能
    • result - 注入到字段或者JavaBean属性的普通结果 - 普通属性注入

Collection 标签中property必须和对象的属性一致。

<?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.hava.cloud_study.repository.UserOp">
    <select id="getUser" parameterType="int" resultMap="UserMap">
        select u.id
        as userId,userName,courseName,corp,c.id as courseId,teacher.id as
        teacherId,teacherName from user u left
        join
        UserCourse uc on u.id
        =uc.user_id left join course c on c.id =
        uc.course_id left join teacher
        on teacher.id = c.teacher_id where u.id
        = #{id}
    </select>

    <resultMap id="UserMap"
               type="com.hava.cloud_study.entity.User">
        <constructor>
            <idArg column="userId" javaType="int" />
            <arg column="userName" javaType="String" />
            <arg column="corp" javaType="String" />
        </constructor>
        <!-- 定义对象为List的属性 -->
        <collection property="courses"
                    ofType="com.hava.cloud_study.entity.Course">
            <id property="id" column="courseId" />
            <result property="courseName" column="courseName" />
            <association property="teacher" column="teacher_id"

                         javaType="com.hava.cloud_study.entity.Teacher">
                <id property="id" column="teacherId" />
                <result property="teacherName" column="teacherName" />
            </association>
        </collection>
    </resultMap>
</mapper>

##Association 实现对象与对象之间的连接

  • 实现复杂类型之间的关联
    • id - 一个ID结果;标记结果作为ID可以帮助提高整体效能
    • result - 注入到字段或者JavaBean属性的普通结果 - 普通属性注入
<?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.hava.cloud_study.repository.UserOp">
    <select id="getUser" parameterType="int" resultMap="UserMap">
        select u.id
        as userId,userName,courseName,corp,c.id as courseId,teacher.id as
        teacherId,teacherName from user u left
        join
        UserCourse uc on u.id
        =uc.user_id left join course c on c.id =
        uc.course_id left join teacher
        on teacher.id = c.teacher_id where u.id
        = #{id}
    </select>

    <resultMap id="UserMap"
               type="com.hava.cloud_study.entity.User">
        <constructor>
            <idArg column="userId" javaType="int" />
            <arg column="userName" javaType="String" />
            <arg column="corp" javaType="String" />
        </constructor>
        <!-- 定义对象为List的属性 -->
        <collection property="courses"
                    ofType="com.hava.cloud_study.entity.Course">
            <id property="id" column="courseId" />
            <result property="courseName" column="courseName" />
            <!-- 一对一 -->
            <association property="teacher" column="teacher_id"

                         javaType="com.hava.cloud_study.entity.Teacher">
                <id property="id" column="teacherId" />
                <result property="teacherName" column="teacherName" />
            </association>
        </collection>
    </resultMap>
</mapper>

#MyBatis数据库连接池 ##DataSource

  • MyBatis 3.0 内置数据库连接池
  • dataSource type="POOLED"启动连接池
<!-- 数据库连接数据源 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://192.168.1.200/cloud_study"/>
                <property name="username" value="root"/>
                <property name="password" value="dVHJtG0T:pf*"/>
            </dataSource>
        </environment>

##数据库连接生命周期 MyBatis数据库连接池的内部实现,与之前的DBCP连接池是非常类似的。MyBatis数据库连接池实际上维护了一个空闲连接链和活跃连接链两个队列,当MyBatis要实际执行SQL时,获取一个数据库连接,首先回去判断空闲的队列中是否有空闲的数据库连接,如果有返回数据库连接去执行SQL,如果没有,则判断当前活跃的数据库连接是否已经满,如果没有超过则创建新连接并加入到活跃列表中。如果已满或者超过则回去检查活跃连接队列中,最早的连接是否过期,如果过期则移除数据库连接。在创建新的数据库连接

输入图片说明

##连接池常用配置选项

  • poolMaximumActiveConnections

    • 数据库最大活跃连接数
    • 考虑到随着连接数的增加,性能可能达到拐点,不建议设置过大。
  • poolMaximumIdleConnections

    • 最大空闲连接数
    • 经验值建议设置与poolMaximum相同即可
  • poolMaximumCheckoutTime

    • 获取连接时如果没有idleConnection同时activeConnection达到最大值,则从activeConnections列表第一个连接开始,检查是否超过poolMaximumCheckoutTime,如果超过,则强制使其失效,返回该连接。
    • 由于SQL执行时间受服务器配置、表结构不同,建议设置为预期最大SQL执行时间。
  • poolTimeToWait

    • 获取服务器端数据库连接的超时时间,如果超过该时间,则打印日志,同时重新获取。
    • 建议使用默认值20s
  • poolPingEnabled

    • 启动连接侦测,检查连接池中的连接是否为有效连接
    • 默认关闭,建议启动,防止服务器端异常关闭,导致客户端错误
  • poolPingQuery

    • 侦测SQL,建议使用select 1开销较小
  • poolPingConnectionsNotUsedFor

    • 侦测时间,建议小于服务器端超时时间,MySQL默认超时8小时
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!