Solved

Hibernate varbinary colum encoding issue

Posted on 2013-05-17
6
590 Views
Last Modified: 2013-05-27
We are using hibernate3.0  as the persistence layer and need to store a really long string in the back end. Since there is a limit if i user Varchar (no utf-8 encoding issues there), i tried using varbinary and set the length to 700. The problem with that is, in my entity, the column is represented by String. Inserting does not seem to be a problem, but while retrieving the string, hibernate screw up the encoding for e.g changes Moiré to Moir¿ .
Table has: ENGINE=InnoDB DEFAULT CHARSET=utf8;
Hibernate properties has:

  <prop key="hibernate.connection.useUnicode">true</prop>
  <prop key="hibernate.connection.characterEncoding">UTF-8</prop>
  <prop key="hibernate.connection.charSet">UTF-8</prop>

Open in new window


Entity :

@Column(name="content")
private String getContent(){....}

Open in new window

encoding.png
0
Comment
Question by:jusnilesh
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
6 Comments
 

Author Comment

by:jusnilesh
ID: 39175758
So i tried updating the database settings

	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://localhost/t1?useUnicode=true&characterEncoding=UTF-8" />
		<property name="username" value="root" />
		<property name="password" value="root" />
		<property name="initialSize" value="5" />
		<property name="maxActive" value="10" />
		<property name="maxIdle" value="2" />
		<property name="validationQuery" value="SELECT 1" />
		<property name="testOnBorrow" value="true" />
	</bean>	

Open in new window


Result:
The utf-8 representation of value that gets persisted is correct, however, hibernate still returns a corrupted value.
0
 

Author Comment

by:jusnilesh
ID: 39176271
So it seems like Hibernate is the culprit. When i use native sql query, i get the correctly encoded value. However, when i tell the query to use my entity which has a String variable that gets populated with Varbinary on the column, hell breaks loose.

So i need a way to define an entity so that i can populate 2 variables with the same column, define one as byte[] and use that for reading and other as String for updating.

Any better ideas.

Please help !!
0
 
LVL 35

Expert Comment

by:girionis
ID: 39180566
What happens if you define the column as CLOB?
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:jusnilesh
ID: 39181688
Not sure if i want to use CLOB.
Here's one possible solution that works, not sure if it is the best though, but would definitely love to hear your opinion on it.

Added an extra attribute in my Hibernate entity

@Type(type="org.hibernate.type.BinaryType")
@Column(name="content",insertable=false,updatable=false )
private byte[] contentBin;
@Column(name="content")
private String content;

private String getContent(){
    	String content= null;
        try {
  			content= new String(this.contentBin,"UTF-8");  			
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return content;

}

Open in new window


DAO:

	public MyEntity getContent (String content){
		
		MyEntity f=  null;
			f = (MyEntity) getCloudSessionFactory()
				.getCurrentSession()
				.createQuery("from MyEntity m where m.content= ?" )
				.setBinary(0, content.getBytes())
				.uniqueResult();
		return f;
		
	}

Open in new window

0
 

Accepted Solution

by:
jusnilesh earned 0 total points
ID: 39187960
Finally figure it out.
For those who are stuck with the same problem, here a clean solution.

step-1: Override org.hibernate.type.StringType
 
 public class ContentStringType extends org.hibernate.type.StringType {
 	
 	private static final long serialVersionUID = 1L;
 
 	public Object get(ResultSet rs, String name) throws SQLException {
 		String content=null;
 		try {
 			content= new String(rs.getBytes(name),"UTF-8");
 		} catch (UnsupportedEncodingException e) {
 			// TODO Auto-generated catch block
 			e.printStackTrace();
 		}
 			return content;
 	}
 	
}

Open in new window

step-2: Apply newly created type
 
   @Type(type="com.company.hibernate.entity.ContentStringType")
    @Column(name="content")
    public String getContent() {
        return this.content;
  }

Open in new window


3:
Make sure your db url has useUnicode=true &amp;characterEncoding=utf-8
0
 

Author Closing Comment

by:jusnilesh
ID: 39198757
clean, minimal changes required to existing codebase
0

Featured Post

Enroll in June's Course of the Month

June's Course of the Month is now available! Every 10 seconds, a consumer gets hit with ransomware. Refresh your knowledge of ransomware best practices by enrolling in this month's complimentary course for Premium Members, Team Accounts, and Qualified Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this post we will learn how to connect and configure Android Device (Smartphone etc.) with Android Studio. After that we will run a simple Hello World Program.
Ever wondered why sometimes your SQL Server is slow or unresponsive with connections spiking up but by the time you go in, all is well? The following article will show you how to install and configure a SQL job that will send you email alerts includ…
Via a live example, show how to extract insert data into a SQL Server database table using the Import/Export option and Bulk Insert.
Viewers will learn how to use the UPDATE and DELETE statements to change or remove existing data from their tables. Make a table: Update a specific column given a specific row using the UPDATE statement: Remove a set of values using the DELETE s…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question