Solved

Hibernate varbinary colum encoding issue

Posted on 2013-05-17
6
566 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
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
PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

 

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

Comprehensive Backup Solutions for Microsoft

Acronis protects the complete Microsoft technology stack: Windows Server, Windows PC, laptop and Surface data; Microsoft business applications; Microsoft Hyper-V; Azure VMs; Microsoft Windows Server 2016; Microsoft Exchange 2016 and SQL Server 2016.

Question has a verified solution.

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

Suggested Solutions

Slowly Changing Dimension Transformation component in data task flow is very useful for us to manage and control how data changes in SSIS.
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
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.
Using examples as well as descriptions, and references to Books Online, show the documentation available for datatypes, explain the available data types and show how data can be passed into and out of variables.

832 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