mybatis筆記二

 

1.創建springboot項目

2.在pom文件加入mybatis等座標

<dependency>
   <groupId>org.mybatis.spring.boot</groupId>
   <artifactId>mybatis-spring-boot-starter</artifactId>
   <version>2.1.1</version>
</dependency>
<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>6.0.5</version>
</dependency>
<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid</artifactId>
   <version>1.1.12</version>
</dependency>

 

3.配置

server.port=8089

#druid���ݿ�����
spring.datasource.url=jdbc:mysql://localhost:3306/user?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
#ʹ��Druid����Դ
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

mybatis.mapper-locations=classpath:/mapper/*.xml

4.單個用戶插入數據:

代碼:userMapper

@Mapper
public interface UserMapper {
    public void save(User user);

    public User selectById(Long id);
}

 

user:

@Data
@Accessors
@ToString
public class User {
    private Long id;
    private String password;
    private String name;
    private Long roleId;
    private Date createTime;
    private Date updateTime;
    private Role role;
}

 

userMapper.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.example.demo.mapper.UserMapper">
    <resultMap id="user" type="com.example.demo.po.User">
        <id column="id" property="id" jdbcType="BIGINT"></id>
        <result column="name" property="name" jdbcType="VARCHAR"></result>
        <result column="role_id" property="roleId" jdbcType="BIGINT"></result>
        <result column="password" property="password" jdbcType="VARCHAR"></result>
        <result column="create_time" property="createTime" jdbcType="TIMESTAMP"></result>
        <result column="update_time" property="updateTime" jdbcType="TIMESTAMP"></result>

 

測試代碼:

@Test
public void testSave() {
    User user = new User();
    user.setPassword("111");
    user.setRoleId(1l);
    user.setName("aaa");
    userMapper.save(user);
}

 

接下來做user和role一對一查詢:即一個用戶對應一個角色

代碼:userMapper

public User selectById(Long id);

userMapper.xml

<resultMap id="user" type="com.example.demo.po.User">
    <id column="id" property="id" jdbcType="BIGINT"></id>
    <result column="name" property="name" jdbcType="VARCHAR"></result>
    <result column="role_id" property="roleId" jdbcType="BIGINT"></result>
    <result column="password" property="password" jdbcType="VARCHAR"></result>
    <result column="create_time" property="createTime" jdbcType="TIMESTAMP"></result>
    <result column="update_time" property="updateTime" jdbcType="TIMESTAMP"></result>
    <!--association 用來關聯對象的, property對應user表裏的role變量,column對應數據庫表user裏的role_id字段-->
    <association property="role" column="role_id" javaType="com.example.demo.po.Role" select="com.example.demo.mapper.RoleMapper.selectById"></association>
</resultMap>
<sql id="user_columns">
    id, name,password
</sql>


<select id="selectById" resultMap="user">
    select * from user where id = #{id}
</select>

 

roleMapper
@Mapper
public interface RoleMapper {

    public Role selectById(Long id);
}

roleMapper.xml
<select id="selectById" resultMap="role">
    select * from role where id = #{id}
</select>

測試:
@Test
public void testUserSe() {
    User user = userMapper.selectById(1L);
    System.out.println(user);

}

結果:

 

Mon Dec 09 21:29:46 CST 2019 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
2019-12-09 21:29:46.099 DEBUG 78268 --- [           main] c.e.demo.mapper.UserMapper.selectById    : ==>  Preparing: select * from user where id = ? 
2019-12-09 21:29:46.124 DEBUG 78268 --- [           main] c.e.demo.mapper.UserMapper.selectById    : ==> Parameters: 1(Long)
2019-12-09 21:29:46.143 DEBUG 78268 --- [           main] c.e.demo.mapper.RoleMapper.selectById    : ====>  Preparing: select * from role where id = ? 
2019-12-09 21:29:46.143 DEBUG 78268 --- [           main] c.e.demo.mapper.RoleMapper.selectById    : ====> Parameters: 1(Long)
2019-12-09 21:29:46.211 DEBUG 78268 --- [           main] c.e.demo.mapper.RoleMapper.selectById    : <====      Total: 1
2019-12-09 21:29:46.212 DEBUG 78268 --- [           main] c.e.demo.mapper.UserMapper.selectById    : <==      Total: 1
2019-12-09 21:29:46.214 DEBUG 78268 --- [           main] c.e.d.m.ResourceMapper.selectByRoleId    : ==>  Preparing: select * from resource where role_id = ? 
2019-12-09 21:29:46.214 DEBUG 78268 --- [           main] c.e.d.m.ResourceMapper.selectByRoleId    : ==> Parameters: 1(Long)
2019-12-09 21:29:46.217 DEBUG 78268 --- [           main] c.e.d.m.ResourceMapper.selectByRoleId    : <==      Total: 2
User(id=1, password=111, name=aaa, roleId=1, createTime=Tue Dec 10 04:51:22 CST 2019, updateTime=Tue Dec 10 04:51:22 CST 2019, role=Role(id=1, name=老師, createTime=Tue Dec 10 04:59:03 CST 2019, updateTime=Tue Dec 10 04:59:03 CST 2019, resources=[Resource(id=1, name=查看, createTime=Tue Dec 10 04:59:26 CST 2019, updateTime=Tue Dec 10 04:59:26 CST 2019, roleId=1), Resource(id=2, name=增加, createTime=Tue Dec 10 04:59:26 CST 2019, updateTime=Tue Dec 10 04:59:26 CST 2019, roleId=1)]))
2019-12-09 21:29:46.247  INFO 78268 --- [extShutdownHook] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} closed
2019-12-09 21:29:46.248  INFO 78268 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskEx

 

接下來做一對多嵌套查詢。一個角色對應多個資源 :

roleMapper
@Mapper
public interface ResourceMapper {
    public List<Resource> selectByRoleId(Long roleId);
}

roleMapper.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.example.demo.mapper.ResourceMapper">
    <resultMap id="resource" type="com.example.demo.po.Resource">
        <id column="id" property="id" jdbcType="BIGINT"></id>
        <result column="role_id" property="roleId" jdbcType="BIGINT"></result>
        <result column="name" property="name" jdbcType="VARCHAR"></result>
        <result column="create_time" property="createTime" jdbcType="TIMESTAMP"></result>
        <result column="update_time" property="updateTime" jdbcType="TIMESTAMP"></result>
    </resultMap>
    <sql id="user_columns">

    </sql>

    <select id="selectByRoleId" resultMap="resource">
        select * from resource where role_id = #{roleId}
    </select>




</mapper>

roleMapper.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.example.demo.mapper.RoleMapper">
    <resultMap id="role" type="com.example.demo.po.Role">
        <id column="id" property="id" jdbcType="BIGINT"></id>
        <result column="name" property="name" jdbcType="VARCHAR"></result>
        <result column="create_time" property="createTime" jdbcType="TIMESTAMP"></result>
        <result column="update_time" property="updateTime" jdbcType="TIMESTAMP"></result>
        <collection property="resources" column="id" javaType="java.util.List" select="com.example.demo.mapper.ResourceMapper.selectByRoleId"></collection>
    </resultMap>

    <select id="selectById" resultMap="role">
        select * from role where id = #{id}
    </select>
</mapper>


測試代碼:
@Test
public void testRoleSe() {
    Role role = roleMapper.selectById(new Long(1));
    System.out.println(role.toString());
}

 

結果:

2019-12-09 21:08:36.376  INFO 97936 --- [           main] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} inited
Mon Dec 09 21:08:36 CST 2019 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
2019-12-09 21:08:36.697 DEBUG 97936 --- [           main] c.e.demo.mapper.RoleMapper.selectById    : ==>  Preparing: select * from role where id = ? 
2019-12-09 21:08:36.719 DEBUG 97936 --- [           main] c.e.demo.mapper.RoleMapper.selectById    : ==> Parameters: 1(Long)
2019-12-09 21:08:36.737 DEBUG 97936 --- [           main] c.e.d.m.ResourceMapper.selectByRoleId    : ====>  Preparing: select * from resource where role_id = ? 
2019-12-09 21:08:36.738 DEBUG 97936 --- [           main] c.e.d.m.ResourceMapper.selectByRoleId    : ====> Parameters: 1(Long)
2019-12-09 21:08:36.740 DEBUG 97936 --- [           main] c.e.d.m.ResourceMapper.selectByRoleId    : <====      Total: 2
2019-12-09 21:08:36.741 DEBUG 97936 --- [           main] c.e.demo.mapper.RoleMapper.selectById    : <==      Total: 1
Role(id=1, name=老師, createTime=Tue Dec 10 04:59:03 CST 2019, updateTime=Tue Dec 10 04:59:03 CST 2019, resources=[Resource(id=1, name=查看, createTime=Tue Dec 10 04:59:26 CST 2019, updateTime=Tue Dec 10 04:59:26 CST 2019, roleId=1), Resource(id=2, name=增加, createTime=Tue Dec 10 04:59:26 CST 2019, updateTime=Tue Dec 10 04:59:26 CST 2019, roleId=1)])
2019-12-09 21:08:36.769  INFO 97936 --- [extShutdownHook] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} closed
2019-12-09 21:08:36.770  INFO 97936 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'

Process finished with exit code 0

 

通過上面可以看到一個老師對象對應了兩個資源。而且從上面可以看到日誌裏查詢了兩次數據庫。其實這也反映了嵌套查詢有個問題,激素N+1問題。

N+1問題,簡單說,在這例子就是查詢了1(1)個老師數據和2(N)個資源數據。

有時候我們查詢僅僅只需要查詢老師的屬性,並不需要馬上拿到對應的資源。這時候可以在collection標籤里加個屬性fetchType="lazy",即加上懶加載(只有在需要的時候才進行加載)

測試:

@Test
public void testRoleSe() {
    Role role = roleMapper.selectById(new Long(1));
    System.out.println(role.getName());
}

結果:

2019-12-09 21:16:04.076  INFO 102712 --- [           main] com.example.demo.mapper.UserMapperTest   : Started UserMapperTest in 7.995 seconds (JVM running for 9.684)
2019-12-09 21:16:04.649  INFO 102712 --- [           main] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} inited
Mon Dec 09 21:16:04 CST 2019 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
2019-12-09 21:16:04.849 DEBUG 102712 --- [           main] c.e.demo.mapper.RoleMapper.selectById    : ==>  Preparing: select * from role where id = ? 
2019-12-09 21:16:04.872 DEBUG 102712 --- [           main] c.e.demo.mapper.RoleMapper.selectById    : ==> Parameters: 1(Long)
2019-12-09 21:16:04.963 DEBUG 102712 --- [           main] c.e.demo.mapper.RoleMapper.selectById    : <==      Total: 1
老師
2019-12-09 21:16:04.993  INFO 102712 --- [extShutdownHook] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} closed
2019-12-09 21:16:04.994  INFO 102712 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'

Process finished with exit code 0

 

從上面可以看到跟上一個例子,並沒有把資源數據查出來。這樣就可以解決N+1問題

 

有興趣的可以關注公衆號:碼上行走

 

 

 

發佈了12 篇原創文章 · 獲贊 1 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章