Solved

Hibernate varbinary colum encoding issue

Posted on 2013-05-17
6
527 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
  • 5
6 Comments
 

Author Comment

by:jusnilesh
Comment Utility
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
Comment Utility
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
Comment Utility
What happens if you define the column as CLOB?
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:jusnilesh
Comment Utility
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
Comment Utility
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
Comment Utility
clean, minimal changes required to existing codebase
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

Introduction SQL Server Integration Services can read XML files, that’s known by every BI developer.  (If you didn’t, don’t worry, I’m aiming this article at newcomers as well.) But how far can you go?  When does the XML Source component become …
For both online and offline retail, the cross-channel business is the most recent pattern in the B2C trade space.
Via a live example, show how to backup a database, simulate a failure backup the tail of the database transaction log and perform the restore.
This tutorial covers a practical example of lazy loading technique and early loading technique in a Singleton Design Pattern.

772 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

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now