The associaction object reference mybatis cached returns null

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

The associaction object reference mybatis cached returns null

feng xiao
mybatis 3.4.6 + jackson + spingMVC

The associaction object reference mybatis cached returns null when cache is enabled.

entitys:
user.java:
public class User implements Serializable {

private String id;
private String username;
private String password;

private List<Book> ownBooks = new ArrayList<Book>();

//setter getter
}

book.java
public class Book implements Serializable {

private String id;
private String name;
private Double price;
private User owner;

//setter getter
}

UserMapper:
<resultMap type="user" id="userResultMap">
<result property="id" column="user_id" />
<result property="username" column="user_username" />
<result property="password" column="user_password" />
<collection property="ownBooks" ofType="book" select="com.beyond.mapper.BookMapper.selectByOwnerId" column="user_id"></collection>
</resultMap>

<select id="selectById" parameterType="string" resultMap="userResultMap">
select
u.id user_id,
u.username user_username,
u.password user_password
from
user u
where u.id = #{id}
</select>

BookMapper:
<resultMap type="book" id="bookResultMap">
<result property="id" column="book_id" />
<result property="name" column="book_name" />
<result property="price" column="book_price" />

<association property="owner" javaType="user" select="com.beyond.mapper.UserMapper.selectById" column="owner_id">
</association>
</resultMap>
<select id="selectById" parameterType="string" resultMap="bookResultMap">
select
b.id book_id,
b.name book_name,
b.price book_price,
b.owner_id  owner_id ,
from book b
where b.id=#{id};
</select>

Service: 
@Override
public User getUserDetail(String id) {
User foundUser = userMapper.selectById(id);
return foundUser;
}
Here, the foundUser.owner is null when user is cached. Can cache not load the assosiation object?

springMVC action:
@RequestMapping("/getUserDetail")
public @ResponseBody User getUserDetail(String id) {
User userDetail = bookService.getUserDetail(id);
JsonBreakCycleUtils.load(userDetail, 3); // to avoid mutual reference
return userDetail;
}

utils:
public class JsonBreakCycleUtils {

public static void load(Object obj, int depth) {
try {
if (obj instanceof Collection) {
Collection collection = (Collection) obj;
if (collection != null && collection.size() > 0) {
for (Object object : collection) {
load(object, depth);
}
}
}
Method[] methods = obj.getClass().getMethods();
for (Method method : methods) {
Class<?>[] parameterTypes = method.getParameterTypes();
Class<?> returnType = method.getReturnType();

if (Collection.class.isAssignableFrom(returnType) && method.getName().startsWith("get")) {
Collection collection = (Collection) method.invoke(obj);

if (collection != null && collection.size() > 0) {
for (Object object : collection) {
if (depth > 0) {
load(object, depth - 1);
} else {
setNull(obj, method);
}
}
}
}

if (isMyClass(returnType) && method.getName().startsWith("get")) {
Object object = method.invoke(obj);
if (object != null) {
if (depth > 0) {
load(object, depth - 1);
} else {
setNull(obj, method);
}
}
}
}
} catch (SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException e) {
e.printStackTrace();
}
}

private static boolean isMyClass(Class clazz) {

if (User.class.isAssignableFrom(clazz)) {
return true;
}
if (Book.class.isAssignableFrom(clazz)) {
return true;
}
if (Author.class.isAssignableFrom(clazz)) {
return true;
}
if (Order.class.isAssignableFrom(clazz)) {
return true;
} else {
return false;
}

}

private static void setNull(Object obj, Method method) throws NoSuchMethodException, SecurityException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException {

String substring = method.getName().substring(3);
String setMethodName = "set" + substring;

Method[] methods = obj.getClass().getMethods();
for (Method m : methods) {
if (m.getName().equals(setMethodName)) {
m.invoke(obj, new Object[] { null });
}
}
}
}

mybatis-config.xml
<?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>

<settings>
<setting name="lazyLoadingEnabled" value="false"></setting>
<setting name="cacheEnabled" value="true"/>
</settings>

<typeAliases>
<package name="com.beyond.entity" />
</typeAliases>

<mappers>
<package name="classpath:com.beyond.mapper" />
</mappers>

</configuration>


--
You received this message because you are subscribed to the Google Groups "mybatis-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: The associaction object reference mybatis cached returns null

Guy Rouillier-2
Something is not right in your mappers.  UserMapper.userResultMap issues a BookMapper.selectByOwnerId(), but BookMapper doesn't implement that statement_id.  And if it did, BookMapper.bookResultMap issues a UserMapper.selectById(), so it looks like these two would recurse until you ran out of memory.

--
Guy Rouillier

------ Original Message ------
From: "feng xiao" <[hidden email]>
To: "mybatis-user" <[hidden email]>
Sent: 6/26/2018 5:43:52 AM
Subject: The associaction object reference mybatis cached returns null

mybatis 3.4.6 + jackson + spingMVC

The associaction object reference mybatis cached returns null when cache is enabled.

entitys:
user.java:
public class User implements Serializable {

private String id;
private String username;
private String password;

private List<Book> ownBooks = new ArrayList<Book>();

//setter getter
}

book.java
public class Book implements Serializable {

private String id;
private String name;
private Double price;
private User owner;

//setter getter
}

UserMapper:
<resultMap type="user" id="userResultMap">
<result property="id" column="user_id" />
<result property="username" column="user_username" />
<result property="password" column="user_password" />
<collection property="ownBooks" ofType="book" select="com.beyond.mapper.BookMapper.selectByOwnerId" column="user_id"></collection>
</resultMap>

<select id="selectById" parameterType="string" resultMap="userResultMap">
select
u.id user_id,
u.username user_username,
u.password user_password
from
user u
where u.id = #{id}
</select>

BookMapper:
<resultMap type="book" id="bookResultMap">
<result property="id" column="book_id" />
<result property="name" column="book_name" />
<result property="price" column="book_price" />

<association property="owner" javaType="user" select="com.beyond.mapper.UserMapper.selectById" column="owner_id">
</association>
</resultMap>
<select id="selectById" parameterType="string" resultMap="bookResultMap">
select
b.id book_id,
b.name book_name,
b.price book_price,
b.owner_id  owner_id ,
from book b
where b.id=#{id};
</select>

Service: 
@Override
public User getUserDetail(String id) {
User foundUser = userMapper.selectById(id);
return foundUser;
}
Here, the foundUser.owner is null when user is cached. Can cache not load the assosiation object?

springMVC action:
@RequestMapping("/getUserDetail")
public @ResponseBody User getUserDetail(String id) {
User userDetail = bookService.getUserDetail(id);
JsonBreakCycleUtils.load(userDetail, 3); // to avoid mutual reference
return userDetail;
}

utils:
public class JsonBreakCycleUtils {

public static void load(Object obj, int depth) {
try {
if (obj instanceof Collection) {
Collection collection = (Collection) obj;
if (collection != null && collection.size() > 0) {
for (Object object : collection) {
load(object, depth);
}
}
}
Method[] methods = obj.getClass().getMethods();
for (Method method : methods) {
Class<?>[] parameterTypes = method.getParameterTypes();
Class<?> returnType = method.getReturnType();

if (Collection.class.isAssignableFrom(returnType) && method.getName().startsWith("get")) {
Collection collection = (Collection) method.invoke(obj);

if (collection != null && collection.size() > 0) {
for (Object object : collection) {
if (depth > 0) {
load(object, depth - 1);
} else {
setNull(obj, method);
}
}
}
}

if (isMyClass(returnType) && method.getName().startsWith("get")) {
Object object = method.invoke(obj);
if (object != null) {
if (depth > 0) {
load(object, depth - 1);
} else {
setNull(obj, method);
}
}
}
}
} catch (SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException e) {
e.printStackTrace();
}
}

private static boolean isMyClass(Class clazz) {

if (User.class.isAssignableFrom(clazz)) {
return true;
}
if (Book.class.isAssignableFrom(clazz)) {
return true;
}
if (Author.class.isAssignableFrom(clazz)) {
return true;
}
if (Order.class.isAssignableFrom(clazz)) {
return true;
} else {
return false;
}

}

private static void setNull(Object obj, Method method) throws NoSuchMethodException, SecurityException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException {

String substring = method.getName().substring(3);
String setMethodName = "set" + substring;

Method[] methods = obj.getClass().getMethods();
for (Method m : methods) {
if (m.getName().equals(setMethodName)) {
m.invoke(obj, new Object[] { null });
}
}
}
}

mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
<configuration>

<settings>
<setting name="lazyLoadingEnabled" value="false"></setting>
<setting name="cacheEnabled" value="true"/>
</settings>

<typeAliases>
<package name="com.beyond.entity" />
</typeAliases>

<mappers>
<package name="classpath:com.beyond.mapper" />
</mappers>

</configuration>


--
You received this message because you are subscribed to the Google Groups "mybatis-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "mybatis-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.